Friday, 8 February 2019

Powershell LDAP query to find Azure / O365 users synchronised with AD Sync

 

 

Recently I needed to create a quick report that would allow me to see at a glance which accounts in that domain had been synchronised with AD Sync into Azure AD.  It wasn’t possible using Get-ADuser and I knew an LDAP query would do the trick.  First I had to download a powershell module called System.DirectoryServices.Protocols.  Once the module is downloaded run:

 

 

Add-Type -AssemblyName System.DirectoryServices.Protocols

Import-Module C:\Cloudwyse\Tools\S.DS.P.psm1

 

Then to query the information I required I ran:

 

 

$MigratedUsers=Find-LdapObject -SearchFilter:"(msDS-ExternalDirectoryObjectId=*)" -SearchBase:"DC=contoso,DC=com" -LdapConnection:"server01.contoso.com" -PageSize 500

 

 

Conversely, if you wanted to find all users that HADN’T been synchronised you could run the following:

 

 

$MigratedUsers=Find-LdapObject -SearchFilter:"(!msDS-ExternalDirectoryObjectId=*)" -SearchBase:"DC=contoso,DC=com" -LdapConnection:"server01.contoso.com" -PageSize 500

 

 

I still had a few service accounts showing so I just filtered these in Excel based on the DN.  To export the fil just run…

 

 

Export-CSV C:\Cloudwyse\User_report.csv

 

 

 

Friday, 1 February 2019

Update Job Title and Department in Active Directory with Powershell

 

 

Here is a short powershell script to update job title and department in Active Directory, though this could be used to update any of the AD fields.  Obviously you will need to create a CSV file beforehand which is populated with the required information.  When the CSV is imported, no headers are specified in the script so ensure these are in the first row file already.  As a minimum here I needed SAMAccountName, Title and Department.

 

The script will first check to see if the user in the file actually exists (I am working in an environment with multiple domains and forests and I didn’t want the script to produce lots of ugly errors if the user weren’t found).  This is done with try and catch.  If you are adapting this script for a different use you will need to make sure you catch the correct error.  The way I got the correct error text was to run the command that produces the error and then run:

 

$Error[0].Exception.GetType().FullName

 

 

I then used ‘catch’ to pick up the accounts that didn’t exist (ie that errored) and set a variable to skip the next command, which is done by the ‘if’ statement.  At the end of that particular row in the ‘foreach’ loop, I set $Nextaction back to $null ready for the next check and so on…

 

 

 

$LogFilePath = $env:LOCALAPPDATA + "\Cloudwyse\Logs\update_job_titles_" + $(get-date -Format ddMMyy_HHmmss) + ".log"

Start-Transcript -Path $LogFilePath -NoClobber

$NewPass = cat C:\cloudwyse\secureinfo.txt | convertto-securestring

$NewCred = new-object -typename System.Management.Automation.PSCredential -argumentlist "contoso\username",$NewPass

$NewEnvDC = "server01.contoso.com"

$JobStart = Get-Date

$Totalprocessed = $null

$Totalupdated = $null

$Userlistpath = "C:\cloudwyse\jobtitles.csv"

$Userlist = Import-csv $Userlistpath

$NewSession = New-PSSession -ComputerName $NewEnvDC -Credential $NewCred

Invoke-Command $NewSession -Scriptblock {Import-Module ActiveDirectory}

Import-PSSession $NewSession -Module ActiveDirectory

 

foreach ($User in $Userlist) {

       Try    {

             Get-ADuser $User.SAMAccountName -ErrorAction Stop | out-null

             }

       Catch [System.Management.Automation.RemoteException]        {

             Write-Host -ForegroundColor Cyan "The user" $User.SAMAccountName "was not found... skipping to next record..."

             $NextAction = "skip"

             }

       Finally {

             if ($NextAction -ne "skip") {

             Set-ADUser $User.SAMAccountName -Department $User.Department -Title $User.Title

             Write-Host -ForegroundColor Magenta "The title for" $User.SAMAccountName "was set to" $User.Title "and the department was set to" $User.Department

             $totalupdated = $totalupdated +1

             $NextAction = $null

             } else {

             $NextAction = $null

             }

             }

       $totalprocessed = $totalprocessed +1

       }                                                                 

$JobEnd = Get-Date

$JobSecondsTaken = ($JobEnd - $JobStart)

Write-Host -ForegroundColor Yellow "Processed $totalprocessed record(s) in" $JobSecondsTaken.Minutes "minute(s) and" $JobSecondsTaken.Seconds "second(s)."

Write-Host -ForegroundColor Yellow "Updated $totalupdated record(s)"

Remove-PSSession $NewSession

Stop-Transcript

 

 

Thanks and feel free to recycle/reuse.