PowerShell Workaround: "Replicate Directory Changes" Permissions in AD Required for SharePoint 2010 Profile Syncs

According to the SharePoint 2010 Communities FAQ, Microsoft is burdening SharePoint 2010 Administrators with new requirements to obtain Active Directory accounts with "Replicate Directory Changes" permissions because...

In order to interrogate AD about “what has changed since time xyz”, we need the replicate-directory-changes permissions on partitions being synchronized, for example the domain partition being synchronized.These permissions are needed in particular to be able to read data within the deleted objects container of the partition. Standard users do not have permissions to read the content of this container, and we cannot simply grant rights over that container to the synchronization account.

While this may be the cleanest way to go about things, it's an unfortunate requirement for SharePoint admins within organizations which understandably frown upon making such concessions for service accounts, especially when the change wasn't required for SharePoint 2007 farms.

Microsoft's recommended architecture is to to use the published information from a centralized farm but some SharePoint administrators are on their own and do not have that luxury. I encountered this issue in a lab environment and was able to circumvent it by writing a quick and dirty script to add new users from AD and sync all SharePoint users with AD. This script only addresses one site collection and does not drill down to its subsites. Run it as often as you would run a regular sync.

# SharePoint <-> AD Group Sync # netnerds.net # # What it does: # Uses LDAP to get a list of users from a specific group in AD (in this case the "All Finance Users" group) # Enables "Allow Unsafe Updates" for the given Site Collection then returns it to its previous state. # Adds AD Users (but ignores nested AD groups) to the specified SharePoint Group # Syncs all Site Users with Active Directory. This includes name changes, etc.

# 1,2,3 Go $ldappath = "LDAP://CN=All Finance Users,OU=Finance,DC=icanhas,DC=net" $spgroupname = "Icanhas Intranet Members" $sitename= "https://sharepoint" $domain = $env:USERDOMAIN

$adgroup = [ADSI]($ldappath) $spsite = SPSite($sitename) $rootweb = $spsite.rootweb $spgroup = $rootweb.Groups[$spgroupname]

$allowUnsafeUpdates = $spsite.AllowUnsafeUpdates $spsite.allowUnsafeUpdates = 1

foreach ($memberDN in $adgroup.member) {

$member = [ADSI]("LDAP://$memberDN") | where {$_.properties.objectcategory -match "CN=Person"} if ($member){ $username = $domain + "\" + $member.sAMAccountName $spsiteuser = $rootweb.EnsureUser($username)

$spUser = $rootweb.AllUsers[$spsiteuser] $spgroup.AddUser($spsiteuser) } }

$spsite.allowUnsafeUpdates = $allowUnsafeUpdates

$rootweb.dispose() $spsite.dispose()

Get-SPUser –Web $sitename| Set-SPUser –SyncFromAD   Note the AD Sync on the last line. Surprisingly enough, PowerShell's SyncFromAD works without explicitly allowing Replicate Directory Changes. To test this, first I tried a domain account with regular privileges then I went a step further and denied Replicate Directory Changes for that account and it still worked.

You may want to make additional changes such as: deleting users that no longer exist in AD, and replicating all changes to subsites.

Ahh, just good enough :)