Choosing a sourceAnchor for Multi-Forest Sync with AAD Connect - Part 4, Using msDS-SourceAnchor

Update 25th May 2017:- As of AAD Connect May 2017 release, version 1.1.524, the default sourceAnchor used by the setup wizard is mS-DS-ConsistencyGuid. This renders most of this blog post series moot but it will be maintained for reference.

 

This blog post series is based upon and tested with AAD Connect, December 2016 release, version 1.1.380.0. Test all deployment designs before production implementation.

Table of Contents

Part 1, Introduction

Part 2, Lab Setup

Part 3, An Aside on EmployeeID

Part 4, Using msDS-SourceAnchor

Part 5, Using mS-DS-ConsistencyGuid

Part 6, Moving off objectGuid

Part 7, Migrating Users

Green Fields Deployment with msDS-SourceAnchor

Following on from my previous sourceAnchor posts, let's assume a new deployment with AAD Connect into an empty Azure Active Directory tenant.

I step through the AAD Connect setup wizard, adding the Forests from my lab (forest1.com and forest2.com), scoping sync to a single OU in each case (SyncOU) and choosing msDS-SourceAnchor as my sourceAnchor attribute -

sa10

I complete the wizard allowing initial sync to be triggered and wait … and wait … and nothing shows up in my Azure Active Directory tenant!

What's Going On?

If you go back to Part 2 of this series, I demonstrated that msDS-SourceAnchor starts life as a NULL value. What this means is that sourceAnchor in the AAD Connect Metaverse is not populated when the default sync rules are used. I can see this by running

"C:\Program Files\Microsoft Azure AD Sync\UIShell\miisclient.exe"

I then click on Metaverse Search and then the Search button which displays the objects imported from my Forests into the AAD Connect Metaverse -

sa11

If I double-click on one of these objects, I can see the attributes in the Metaverse that have been populated -

sa12

In this case, we cannot see sourceAnchor (I'll discuss sourceAnchorBinary in a later post)

It follows that AAD Connect can't create an object in Azure Active Directory. We'll need to modify the sync rules.

Editing the Sync Rules

The sync rules editor is opened by running

"C:\Program Files\Microsoft Azure AD Sync\UIShell\SyncRulesEditor.exe"

When this opens, you'll notice that the rules are filtered by Inbound and that for each Forest, there are three rules that relate to Users -

sa13

The rules for each Forest are

  • In from AD - User Join
  • In from AD - User AccountEnabled
  • In from AD - User Common

Note: It is unsupported to edit the built-in rules. All you can do is copy them which disables the original. I'll copy the User Join rule and create a new rule that overrides the other two rules for just the sourceAnchor attribute

Notice that the lowest precedence on these rules is 100. Starting from a precedence value of

(100 - (2 x number_of_forests)) we'll number each new rule

In my example, this value will be (100 - (2 x 2)) = 96

I'll have

  • In from AD - User Join Custom = 96
  • In from AD - User Join Custom = 97
  • In from AD - msDS-SourceAnchor = 98
  • In from AD - msDS-SourceAnchor = 99

Modifying User Join Rules

Note the precedence value you're up to

Click Edit and then click Yes when prompted to copy the rule

Provide a meaningful Name (e.g. In from AD - User Join Custom)

Set the Precedence

Click Next twice

On the Join Rules page, in the existing join rule, change the Source Attribute to msDS-SourceAnchor and the Target Attribute to sourceAnchor

On the Join Rules page, click Add group

On the Join Rules page, in the new join rule, change the Source Attribute to objectGuid and the Target Attribute to sourceAnchorBinary

sa14

Click Next

On the Transformation page, edit the second rule so that the FlowType is Expression, Target Attribute is sourceAnchor and the source is

 IIF(IsPresent([msDS-SourceAnchor]),IIF(IsString([msDS-SourceAnchor]),CStr([msDS-SourceAnchor]),ConvertToBase64([msDS-SourceAnchor])),IIF(IsString([objectGUID]),CStr([objectGUID]),ConvertToBase64([objectGUID])))

On the Transformation page, add a third rule so that the FlowType is Direct, Target Attribute is sourceAnchorBinary and the source is objectGuid

sa15

Click Save

If prompted with an Expression Warning, click Yes

Repeat for each additional Forest being synchronised

Overriding User AccountEnabled and User Common Rules for sourceAnchor

The process for creating a new rule to override each of the other rules is -

Note the precedence value you're up to

Click Add New Rule

Provide a meaningful Name (e.g. In from AD - msDS-SourceAnchor)

Set the Connected System to the Forest you're configuring for

Set the Connected System Object to user

Set the Metaverse Object Type to person

Set the Link Type to Join

Set the Precedence

Click Next three times

On the Transformations page, click Add transformation

Set FlowType to Expression

Set Target attribute to sourceAnchor

Change the source expression to

 IIF(IsPresent([msExchRecipientTypeDetails]),IIF([msExchRecipientTypeDetails]=2,NULL,IIF(IsPresent([msDS-SourceAnchor]),IIF(IsString([msDS-SourceAnchor]),CStr([msDS-SourceAnchor]),ConvertToBase64([msDS-SourceAnchor])),IIF(IsString([objectGUID]),CStr([objectGUID]),ConvertToBase64([objectGUID])))),IIF(IsPresent([msDS-SourceAnchor]),IIF(IsString([msDS-SourceAnchor]),CStr([msDS-SourceAnchor]),ConvertToBase64([msDS-SourceAnchor])),IIF(IsString([objectGUID]),CStr([objectGUID]),ConvertToBase64([objectGUID]))))

sa16

Click Add

If prompted with an Expression Warning, click Yes

Repeat for each additional Forest being synchronised


For reference it may be easier to understand the code if viewed with formatting. Note that the following formatting should NOT be used in the expression box -

 IIF(
   IsPresent([msExchRecipientTypeDetails]),
    IIF(
        [msExchRecipientTypeDetails]=2,
     NULL,
       IIF(
            IsPresent([msDS-SourceAnchor]),
         IIF(
                IsString([msDS-SourceAnchor]),
              CStr([msDS-SourceAnchor]),
              ConvertToBase64([msDS-SourceAnchor])
            ),
          IIF(
                IsString([objectGUID]),
             CStr([objectGUID]),
             ConvertToBase64([objectGUID])
           )
       )
   ),
  IIF(
        IsPresent([msDS-SourceAnchor]),
     IIF(
            IsString([msDS-SourceAnchor]),
          CStr([msDS-SourceAnchor]),
          ConvertToBase64([msDS-SourceAnchor])
        ),
      IIF(
            IsString([objectGUID]),
         CStr([objectGUID]),
         ConvertToBase64([objectGUID])
       )
   )
)

Also understand that the conditions surrounding msExchRecipientTypeDetails are used to handle linked mailboxes in a Resource Forest and are implemented by the AAD Connect setup wizard (we want to keep them).


Creating a Rule to Write sourceAnchor back into msDS-SourceAnchor

Now we have rules that correctly populate sourceAnchor in the Metaverse, we need rules that write sourceAnchor back into the on-premises msDS-SourceAnchor attribute -

Change the rule editor filter to show Outbound rules

Take note of the precedence of the last rule in the list

Click Add new rule

On the Description page, set the Name to Out to AD - msDS-SourceAnchor

On the Description page, set Connected System to the Forest you're currently configuring the rule for

On the Description page, set Connected System Object Type to user

On the Description page, set Metaverse Object Type to person

On the Description page, set the Precedence to a value higher than the precedence noted above (this will need to increase for each new rule created for each Forest)

sa17

Click Next three times

On the Transformation page, click Add transformation

In the new transformation set the FlowType to Direct, the Target Attribute to msDS-SourceAnchor, the Source to sourceAnchor and the Merge Type to Update

Click Add

Repeat for each additional Forest being synchronised

Close the rules editor

Trigger a Full Sync

Open a PowerShell prompt and execute

Start-ADSyncSyncCycle -PolicyType Initial

You should now find that users are successfully synchronised to Azure Active Directory and that sourceAnchor is written back into msDS-SourceAnchor for on-premises objects.

sa19

 

sa20

Conclusion

The rule changes configured here prefer msDS-SourceAnchor as the sourceAnchor source but use objectGuid when msDS-SourceAnchor is NULL. sourceAnchor is written back to msDS-SourceAnchor in the on-premises object so that this attribute is always used after the initial sync, even after a migration of the user object between Forests.