Recently I had an interesting job at a customer, who used a web application with an address book. The web application used LDAP queries to Active Directory to get all users addresses and phone numbers. This information was then searchable on a public web site located in DMZ.
The problem here is that we had an internet facing server. We could not allow it to make queries directly to the internal Active Directory. We decided to install a new AD LDS (Lightweight Directory Services) partition in the DMZ where we could ask our queries.
Next problem: We have to populate our new LDS partition with users. Normally this would be done with a system designed for it, like Forefront Identity Manager. Here we needed a quick-and-dirty solution to get started, and I therefore wrote a PowerShell script that copied the attributes we needed from our Active Directory.
One of the first things to solve was to find who and what to sync. With ten thousands of users in Active Directory we needed a solution to select users, even though they were spread across several OUs. Also, Swedish laws regulate what information to publish, so we had to filter sensitive information.
We ended up with a solution where only users in a specific OU were synced, but they also needed to be member of a specific group. We also filtered disabled users.
$ADUsers = Get-ADGroupMember -Identity "grp_ADSyncUsers" -Recursive | Get-ADUser -Properties ` SamAccountName,GivenName,Surname,DisplayName,Title,Office,Department,Company,EmailAddress,Mobile,OfficePhone,Modified,Enabled | ` Where-Object { $_.Enabled -eq $true -and $_.DistinguishedName -like "*$sourceou" }
We now have too much data. Our sync will be too slow, so we need to filter again.
There is no need to process accounts that haven’t been changed recently. We simply checked the Modified attribute in active directory and skipped these.
if ((get-date $modified) -ge ($(get-date).AddDays(-1.5))) { ... }
We also needed a method to detect deleted accounts. Here we simply got all users in AD LDS and compared it with the users in AD DS. Any extra users were removed.
Compare-Object $PhoneBookUsers.Name $ADUserNames | Where-Object { $_.SideIndicator -eq "<=" } | ForEach-Object { $id="cn=$($_.InputObject),$destou" Remove-ADUser -Identity $id -Server $destserver -Credential $cred -Partition $destpartition -Confirm:$false }
Below is the entire script, but as I wrote, it is a quick-and-dirty solution just to get started.
$destserver = "10.10.10.5" $destpartition = "dc=cloud,dc=net" $destou = "ou=PhoneBook,dc=cloud,dc=net" $sourceou = "ou=MyBusiness,dc=contoso,dc=com" $cred = Get-Credential $i = 0 Import-Module ActiveDirectory # Define users to process Write-Host "Collecting user information..." $ADUsers = Get-ADGroupMember -Identity "grp_ADSyncUsers" -Recursive | Get-ADUser -Properties ` SamAccountName,GivenName,Surname,DisplayName,Title,Office,Department,Company,EmailAddress,Mobile,OfficePhone,Modified,Enabled | ` Where-Object { $_.Enabled -eq $true -and $_.DistinguishedName -like "*$sourceou" } Write-Host "$($ADUsers.Count) user(s) found in Active Directory." # Create/update users $ADUsers | ForEach-Object { $sam = $_.Name $givenname = $_.GivenName $surname = $_.Surname $displayname = $_.DisplayName $email = $_.EmailAddress $department = $_.Department $office = $_.Office $title = $_.Title $company = $_.Company $tele = $_.OfficePhone $mobil = $_.Mobile $modified = $_.Modified if ((get-date $modified) -ge ($(get-date).AddDays(-1.5))) { # Process user accounts modified the last 36 hours $i++; try { # Create new account in AD LDS New-ADUser -SamAccountName $sam -Name $sam -DisplayName $displayname -GivenName $givenname ` -SurName $surname -EmailAddress $email -Title $title -Office $office -Department $department ` -Company $company -OfficePhone $tele -MobilePhone $mobil ` -Enabled $false -Path $destou –Type iNetOrgPerson ` -Server $destserver ` -Credential $cred Write-Host "Creating user $sam" } catch [System.Exception] { switch($_.Exception.GetType().FullName) { 'Microsoft.ActiveDirectory.Management.ADException' { # User already exists. Update existing account Set-ADUser -Identity "cn=$sam,$destou" -DisplayName $displayname -GivenName $givenname -SurName $surname ` -EmailAddress $email -Title $title -Office $office -Department $department ` -Company $company -OfficePhone $tele -MobilePhone $mobil ` -Server $destserver ` -Credential $cred ` -Partition $destpartition Write-Host "Updating user $sam" } } } } } # Remove deleted accounts Write-Host "$i user(s) processed." Write-Host "Searching for users to delete..." $i=0 $PhoneBookUsers = Get-ADUser -Server $destserver -SearchBase $destou -Filter * -Credential $cred | Select -Property Name $ADUserNames += $ADUsers.Name Compare-Object $PhoneBookUsers.Name $ADUserNames | Where-Object { $_.SideIndicator -eq "<=" } | ForEach-Object { $id="cn=$($_.InputObject),$destou" Remove-ADUser -Identity $id -Server $destserver -Credential $cred -Partition $destpartition -Confirm:$false Write-Host "Deleting user $($_.InputObject)" $i++ } Write-Host "$i user(s) deleted." Write-Host "Done!"
/ Andreas