Wednesday, February 13, 2008

Search Active Directory for New/Deleted objects in PowerShell (Full)

First I would like to thank Chrissy LeMaire for giving me the opportunity to write this script. She initially wrote a VBScript file to audit the domain for any new computer or user objects added in Active Directory in the last 60 days. Excellent work Chrissy!

I so then converted this script to Powershell and also added in the previous posts TombStonedObjects function to also include not only what was added but also included what objects have been deleted. Very much like Chrissy's script it will email you the results.

   1:  #REQUIRES -pssnapin quest.activeroles.admanagement
   2:  #REQUIRES -pssnapin Pscx
   3:  
   4:  param ($strSMTPServer="xx.xx.xx.xx",[int]$DaysAgo=60,$strEmailFrom="AD_Admin@yourdomain.com",$strEmailTo="you@yourdomian.com")
   5:  
   6:  begin {
   7:  
   8:  # Get negative value to pass to Get-Date
   9:  $DaysAgo = $DaysAgo * -1 
  10:  $borders = "=" * 25;
  11:  
  12:  function TombStonedObjects {
  13:      # create Directory Searcher object and set properties to search
  14:      # for tombstoned objects
  15:  
  16:      $ds = New-Object System.DirectoryServices.DirectorySearcher
  17:      $ds.Tombstone = $TRUE
  18:      $ds.Filter = "isDeleted=TRUE"
  19:  
  20:      # Query for objects and filter for DN 
  21:      $DSResults=$DS.FindAll() | select path
  22:  
  23:      # Build simple RegExp to get just Common Name
  24:      $r=[regex]"(?<=CN=).+(?=\\)"
  25:      $DSR2=$DSResults | % { $r.Matches($_);$script:delCount++}
  26:      foreach ($DSobject in $DSR2) { $delMessage += "Deleted object: " + $DSobject.value.trim() + "`n" }
  27:      
  28:      $delMessage
  29:      
  30:      # end function
  31:      }
  32:  
  33:  
  34:  function AddedComputersAndUsers {
  35:  # Query AD for Computer and users created in the last 'x' amount of days.
  36:  $ADObjects=Get-QADObject | ? {$_.type -match ("computer|user")} | ? {$_.whencreated -gt ((get-date).addDays($DaysAgo))}
  37:  
  38:    if ($ADObjects) {
  39:      foreach ($ADObject in $ADObjects) {
  40:          switch ($ADObject.Type) {
  41:              'user'    {
  42:                  $usrCount ++;
  43:                  $ADObject | fl * | Out-Null; #This is needed for some reason some objects are not returned without it 
  44:                  $usrMessage += "Display Name: " + $ADobject.displayname + "`n";
  45:                  $usrMessage += "SAMAccountName: " + $ADObject.get_LogonName() + "`n";
  46:                  $usrMessage += "Container: " + $ADObject.parentcontainer + "`n";
  47:                  $usrMessage += "When Created: " + $ADObject.whencreated + "`n";
  48:                  $usrMessage += "Principal Name: " + $ADObject.userPrincipalName + "`n";
  49:                  $usrMessage += "Groups: `n";
  50:                      # Build array of groups and populate $usrMessage variable
  51:                      $groups=$adobject.MemberOf
  52:                      foreach ($group in $groups) { $usrMessage += "$group `n"}
  53:                  $usrMessage += "`n";
  54:                  }                
  55:              'computer' {
  56:                  $computerCount ++;
  57:                  $ADObject | fl * | Out-Null; #This is needed for some reason some objects are not returned without it 
  58:                  $compMessage += "DNS HostName: " + $ADObject.dnsname + "`n";
  59:                  $compMessage += "OperatingSystem: " + $ADObject.osName + "`n";
  60:                  $compMessage += "OS Service Pack: " + $ADObject.osservicepack + "`n";
  61:                  $compMessage += "Computer Role: " + $ADObject.computerrole + "`n";
  62:                  $compMessage += "When Created: " + $ADObject.whencreated + "`n";
  63:                  $compMessage += "Container: " + $ADObject.parentcontainer + "`n";
  64:                  $compMessage += "`n";
  65:                  }
  66:              }
  67:          }
  68:      
  69:      $deletedobjects = TombStonedObjects
  70:      
  71:      # Build emailBody with the Usermessage and ComputerMessage variables 
  72:      $script:emailMessage = "AD User/Computer Objects created in the last " + [math]::abs($DaysAgo) + " day(s).`n";
  73:      if ($usrMessage) {$script:emailMessage += "$borders Users $borders`n" + $usrMessage;}
  74:      if ($compMessage) {$script:emailMessage += "$borders Computers $borders`n" + $compMessage;}
  75:      if ($deletedobjects) {$script:emailMessage += "$borders Deleted Objects for the last 60 days $borders `n" + $deletedobjects;}
  76:      $script:emailSubject = "Users Added: " + $usrCount + ". Computers Added: " + $computerCount + ".  Objects Deleted: " + $script:delCount + ".";
  77:      
  78:      }
  79:      
  80:      else {
  81:      # No users or computers found created in the last 'x' days.
  82:      $deletedobjects = TombStonedObjects
  83:      $script:emailSubject = "Users Added: " + $usrCount + ". Computers Added: " + $computerCount + ".  Objects Deleted: " + $script:delCount + ".";
  84:      $script:emailMessage = "No Users or Computers have been added in the last " + [math]::abs($DaysAgo) + " day(s). `n";
  85:      if ($deletedobjects) {$script:emailMessage += "$borders Deleted Objects for the last 60 days $borders `n" + $deletedobjects;}
  86:          }
  87:      # end function
  88:      }
  89:  # end Begin
  90:  }
  91:  
  92:  
  93:  process {
  94:  
  95:  
  96:  AddedComputersAndUsers
  97:  Send-SmtpMail -Subject $script:emailSubject -To $strEmailTo -From $strEmailFrom -SmtpHost $strSMTPServer -Body $script:emailMessage;
  98:  
  99:  # end Process
 100:  }

Pay close attention to the first 2 lines!

#REQUIRES -pssnapin quest.activeroles.admanagement
#REQUIRES -pssnapin Pscx

These are statements that I dont see much but are *Extremely* useful if you are using Powershell snapins inside your script. They are not only useful to the person reading the code and letting him know that he must have those snapins installed but it also puts a lock in Powershell not permitting the script to execute without those snapins loaded. If you try to run this script and you do not have these loaded you will receive an error like this.


No comments: