New versions of AAD Connect has been released rapidly from Microsoft, earlier this week 9th version of the year (1.1.614.0) saw daylight.
I have installed last fresh AAD Connect version at April 2017 and a lot of things has been happening in production development since then. Quite significant change was introduced in version 1.1.524.0 which was released at May 2017.
ms-DSconsistencyGuid as SourceAnchor
Azure AD Connect now automatically enables the use of ConsistencyGuid attribute as the Source Anchor attribute for on-premises AD objects. Further, Azure AD Connect populates the ConsistencyGuid attribute with the objectGuid attribute value if it is empty. This feature is applicable to new deployment only.
Microsoft docs contains information about sourceAnchor and msDS-ConsistencyGuid design concept which can be found from links below:
What this means
By default, it doesn’t affect to existing installations and it can only be enabled to fresh and new environment installations during AAD Connect installation. You can switch sourceAnchor from objectGUID to ms-ds-ConsistencyGuid (from version 1.1.561.0, user objects only) but that’s totally different story.
How it works
If your environment is capable of using ms-DS-ConsistencyGuid as sourceAnchor AAD Connect automatically configures the synchronization rules to:
- Use msDS-ConsistencyGuid as the sourceAnchor attribute for User objects. ObjectGUID is used for other object types (groups, contacts).
- For any given on-premises AD User object whose msDS-ConsistencyGuid attribute isn’t populated, Azure AD Connect writes its objectGUID value back to the msDS-ConsistencyGuid attribute in on-premises Active Directory. After the msDS-ConsistencyGuid attribute is populated, Azure AD Connect then exports the object to Azure AD.
Latter causes that AAD Sync account needs write permission to msDS-ConsistencyGuid attribute for synced user objects. If AAD Connect is installed with “Express Settings” service account get needed permissions during installation but if custom mode is used permission to service account needs to be granted manually.
RW permissions needed to AAD Connect sync account when using ms-DS-ConsistencyGuid
Permissions can be granted via Active Directory GUI or dsacls. ADDS GUI don’t show ms-ds-ConsistencyGUID at ADUC security by default but if service account has permission to manage user objects needed permissions are in place.
When following least privileged permissions dsacls would solve the problem
“dsacls ‘OU=Users,DC=domain,DC=com‘ /I:S /G ‘`”domain\svc_aadconnect`”:RPWP;`”mS-DS-ConsistencyGuid`”;user’”
Impact to federation (ADFS or 3th party)
If you start using new sourceAnchor default ADFS claims which are being sent inside authentication token to Azure AD will not be consistent anymore. Following options available:
- If AAD Connect has been used to configure ADFS trust it automatically create needed claims (and bunch of more)
- If ADFS is managed outside AAD Connect (like I do) claims needs to be manually modified.
Option 1 – Use AAD Connect to configure ADFS claims. AADC will create following claims during installation if ms-DS-ConsistencyGuid is used as sourceAnchor among other claims, for example Device Registration, Password expiration and network location.
@RuleName = “Issue UPN”
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”%5D
=> issue(store = “Active Directory”, types = (“http://schemas.xmlsoap.org/claims/UPN”), query = “samAccountName={0};userPrincipalName;{1}”, param =
regexreplace(c.Value, “(?<domain>[^\\]+)\\(?<user>.+)”, “${user}”), param = c.Value);
@RuleName = “Query objectguid and msdsconsistencyguid for custom ImmutableId claim”
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”%5D
=> add(store = “Active Directory”, types = (“http://schemas.microsoft.com/ws/2016/02/identity/claims/objectguid”,
“http://schemas.microsoft.com/ws/2016/02/identity/claims/msdsconsistencyguid”), query = “samAccountName={0};objectGUID,mS-DS-ConsistencyGuid;{1}”, param =
regexreplace(c.Value, “(?<domain>[^\\]+)\\(?<user>.+)”, “${user}”), param = c.Value);
@RuleName = “Check for the existence of msdsconsistencyguid”
NOT EXISTS([Type == “http://schemas.microsoft.com/ws/2016/02/identity/claims/msdsconsistencyguid”%5D)
=> add(Type = “urn:federation:tmp/idflag”, Value = “useguid”);
@RuleName = “Issue msdsconsistencyguid as Immutable ID if it exists”
c:[Type == “http://schemas.microsoft.com/ws/2016/02/identity/claims/msdsconsistencyguid”%5D
=> issue(Type = “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”, Value = c.Value);
@RuleName = “Issue objectGuidRule if msdsConsistencyGuid rule does not exist”
c1:[Type == “urn:federation:tmp/idflag”, Value =~ “useguid”]
&& c2:[Type == “http://schemas.microsoft.com/ws/2016/02/identity/claims/objectguid”%5D
=> issue(Type = “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”, Value = c2.Value);
@RuleName = “Issue nameidentifier”
c:[Type == “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”%5D
=> issue(Type = “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”, Value = c.Value,
Properties[“http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format”%5D = “urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified”);
@RuleName = “Issue accounttype for domain-joined computers”
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value =~ “-515$”, Issuer =~ “^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$”]
=> issue(Type = “http://schemas.microsoft.com/ws/2012/01/accounttype”, Value = “DJ”);
@RuleName = “Issue onpremobjectguid for domain-joined computers”
c1:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value =~ “-515$”, Issuer =~ “^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$”]
&& c2:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer =~ “^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$”]
=> issue(store = “Active Directory”, types = (“http://schemas.microsoft.com/identity/claims/onpremobjectguid”), query = “;objectguid;{0}”, param = c2.Value);
@RuleName = “Pass through primary SID”
c1:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value =~ “-515$”, Issuer =~ “^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$”]
&& c2:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid”, Issuer =~ “^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$”]
=> issue(claim = c2);
@RuleName = “Pass through claim – insideCorporateNetwork”
c:[Type == “http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork”%5D
=> issue(claim = c);
@RuleName = “Pass Through Claim – Psso”
c:[Type == “http://schemas.microsoft.com/2014/03/psso”%5D
=> issue(claim = c);
@RuleName = “Issue Password Expiry Claims”
c1:[Type == “http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime”%5D
=> issue(store = “_PasswordExpiryStore”, types = (“http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime”,
“http://schemas.microsoft.com/ws/2012/01/passwordexpirationdays”, “http://schemas.microsoft.com/ws/2012/01/passwordchangeurl”), query = “{0};”, param = c1.Value);
Option 2 – perform modifications manually. Needed modifications – docs.microsoft.com.
Rule 1: Query attributes = “Query objectguid and msdsconsistencyguid for custom ImmutableId claim”
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname“]
=> add(store = “Active Directory”, types = (“http://schemas.microsoft.com/ws/2016/02/identity/claims/objectguid“, http://schemas.microsoft.com/ws/2016/02/identity/claims/msdsconsistencyguid), query = “samAccountName={0};objectGUID,mS-DS-ConsistencyGuid;{1}”, param = regexreplace(c.Value, “(?<domain>[^\\]+)\\(?<user>.+)“, “${user}”), param = c.Value);
Rule 2: = “Check for the existence of msdsconsistencyguid”
NOT EXISTS([Type == “http://schemas.microsoft.com/ws/2016/02/identity/claims/msdsconsistencyguid“])
=> add(Type = “urn:federation:tmp/idflag”, Value = “useguid”);
Rule 3 “Issue msdsconsistencyguid as Immutable ID if it exists”
c:[Type == “http://schemas.microsoft.com/ws/2016/02/identity/claims/msdsconsistencyguid“]
=> issue(Type = “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID“, Value = c.Value);
Rule 4= “Issue objectGuidRule if msdsConsistencyGuid rule does not exist”
c1:[Type == “urn:federation:tmp/idflag”, Value =~ “useguid”]
&& c2:[Type == “http://schemas.microsoft.com/ws/2016/02/identity/claims/objectguid“]
=> issue(Type = “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID“, Value = c2.Value);
Why the change has been made and why it’s a best practice nowadays
ObjectGuid is ‘immunitable’ attribute and in some scenarios it can cause issues, for example:
The Cross-forest Migration Challenge
The Accidentally Deleted Challenge
Excellent blog series about using ms-DS-ConsistencyGuid as sourceAnchor, what is it, why change was made and how to start using consistencyGuid as sourceAnchor in existing installation.
Summary
Start using ms-ds-ConsistencyGuid in new installations is straightforward task to perform. If you are going to change sourceAnchor for user objects it needs a lot of planning and testing. More information from links below
sourceAnchor docs.microsoft.com
using msDS-ConsistencyGuid as the sourceAnchor attribute
multi-forest sync with AAD Connect