I’ve finally had the opportunity to work with AAD Connect over these past weeks, and its been one of those “everything old is new again” experiences. It’s one thing to hear the architectural objectives that Andreas talked about for the Azure “identity bridge” product that was to replace AADSync, and DirSync before it – but it’s only when you get your hands dirty for the first time that you really start to understand what exactly that means. In my case I am replacing a custom FIM 2010 multi-forest sync implementation with a custom AADConnect solution. FIM had previously replaced DirSync before it, and while I am finding that it hasn’t quite been the plain sailing I was hoping for, I remain confident I will get there based on alignment to one of the listed topology models.
In my target environment I have something close to the “Multiple Forests – Account-Resource Forest” scenario, with FIM 2010 currently in place providing the identity bridge. However there are some key differences too, the main one being that the FIM instance I am replacing has only a single management agent to the resource forest, with no connectors to any of the regional forests. This is made possible by a secondary FIM sync instance populating a bunch of extension attributes in the resource forest with feeds from each of the 5 AD regional forests, including the all-important immutableId.
Long story short … in the process of adjusting the OOTB sync rule solution for a multi-forest configuration, I have found myself
- disabling a bunch of sync rules (all up there were 195!);
- provisioning from the resource forest only (or “projecting” as we would say in MIM-speak) for each object type by changing the link type “provision” to “join” for all the regional connectors;
- changing the join rules for contacts and groups to only join on the immutableId extension attribute; and
- using AD groups to filter my pilot environment to reduce the sync analysis to a small managebale set of users, groups and contacts.
Now I am still to decide on whether or not point #3 is the way to go, but in the process of running the initial load sync step after changing all the contact and group rules with names that ended in “join”, I ran into this rather confusing error:
The Inbound sync rules in scope have different join criteria. Join Criteria:[objectGUID=sourceAnchorBinary CS=False], [extensionAttributeXX=extensionAttributeXX CS=False] Sync Rules: In from AD - Group Filtering[<guid>], In from AD - Group Join[<guid>] at Microsoft.MetadirectoryServices.SyncRulesEngine.JoinModule.ValidateAllApplicableSyncRules(IEnumerable`1 applicableSyncRules) at Microsoft.MetadirectoryServices.SyncRulesEngine.JoinModule.Execute(PipelineArguments argsToProcess) at Microsoft.MetadirectoryServices.SyncRulesEngine.Server.SyncEngine.RunSyncPipeline(SyncRulePipelineArguments pipelineData, List`1 pipelineChain) at Microsoft.MetadirectoryServices.SyncRulesEngine.Server.SyncEngine.Synchronize(SynchronizationOperation operation, IObjectLinkGraph inputGraph) at ManagedSyncRulesEngine.Synchronize(ManagedSyncRulesEngine* , CCsObject* sourceCsObject, CMvObject* mvObject, SynchronizationOperation operation, Char** error)
Not only did I get this error, but it occurred 5000 times and then stopped the sync run profile having reached the built-in error limit. This kind of threw me because what I had read suggested that I had changed all of the OOTB join rules for contacts and users by observing the naming standards. Yet there was obviously at least one rule I had missed – maybe more. What was concerning me at the time was that maybe I had broken something by making the change that could not be recovered. Thankfully the details I needed to identify the problem were in the details of the message … specifically that there was another sync rule which included a JOIN but which did not have a name which ended in “Join”.
It turned out that because of my use of group filters (item #4 in my list above), there were additional sync rules with a name ending in “Filtering” which also included a join statement – and these were still configured NOT to use my extension attribute.
So the remedy was simple – changing all the “Filtering” sync rules in addition to the “Join” rules, followed by a rerun of the initial load, was all that was required to restore to a working state.