Walking through the Office 365 IDM driver - Part 5


In part one of this series I walked through some of the configuration, Packages, and GCVs used in the Office 365 IDM driver.

In part two of this series I walked through more of the GCVs and looked at some possible values for the License entitlements.

In part three of this series I looked at the Filter and Schema Map and some more entitlement issues.

In part four of this series ( ) I looked at the configuration settings and then on to actual policies, getting through the Subscriber Event Transform policy set.

In this article I will continue down the Subscriber channel, continuing from the Match Policy Set.

Matching Policy set

The Matching Policy set has three policy objects:

  1. NOVLOFFIDCFG-sub-mp-scoping

  • NOVLOFFIENTEX-sub-mp-EntitlementsImpl


1. NOVLOFFIDCFG-sub-mp-scoping

This policy object has two rules:

  1. Remember relative position in hierarchy

  • Set Operation Property for Groups

Remember relative position in hierarchy

This is the very typical user matching policy, that later policies rely on. If this is a User, in the subtree defined by the GCV idv.dit.data.users then using the Unmatched Source DN token, it sets a operation property called unmatched-src-dn, which is one of those confusing things. In trying to break this policy out into two separate steps, so entitlements could be nicely handled by an add on package, they need to do this test here, then carry the data forward into another rule, so an operation property is a good choice. However, by naming it unmatched-src-dn, sort of makes it look like maybe the Unmatched Source DN noun token in Argument Builder should be setting it. But it is a conscious decision made by the policy writers. If there is no such property, a later rule, after Entitlements have had a chance to consider their case for a veto, then this event would get vetoed. This was we can take two different approaches to how to stop an inappropriate event.

On a side note, there are other ways of scoping the events than just this approach. The first would be to run this driver on an engine, only with replicas of the data you wish to synchronize. That is, if the Users container is in a replica on this engine server, but not the groups, or not ancillary users you do not wish to sync, then there will never be an event on those users, for the engine to process and then veto.

Alternatively if that is not a possibility, perhaps since you only have one engine, and one replica to work with, then you could create an object (It does not actually have to be a user object, in eDirectory everything is a security principal. I think using a Printer here would be a pretty amusing in fact) with limited rights. There will be an event shown in the trace, but the engine will report that although it knows something has changed, it does not have permission to see it and therefore no event is processed. From a time perspective, it seems like it fairly quickly figures this out, but I have not specifically timed it to see how long it really wastes in this approach.

One other operational property, 'attempt-to-match' is set to true as well, which is used later as well.

However this is now the basic scoping approach used in Packaged driver, so nice to see consistency.

Set Operation Property for Groups

This is the same basic policy modified for Group objects, as was used for User objects in the previous rule. Change the GCV to the Group container GCV, the class name test to Group, and it is otherwise identical.

2. NOVLOFFIENTEX-sub-mp-EntitlementsImpl

This policy has a single rule, "UserAccount entitlement: do not match existing accounts" which says, if the Entitlement "UserAccount" is not available on this user, and the GCV drv.entitlement.UserAccount is set to true, then set the operation property attempt-to-match to false. This way a GCV controls the use of Entitlements or not, and then do not match non-entitled users. This operation property will be checked in a moment to see if it is requiring of a veto or not.


This policy has three rules.

  1. veto out-of-scope events

  • Match Users

  • Query Display Name

veto out-of-scope events

Here we finally check for the operation property "attempt-to-match", and if it is not available, or false, we veto. I wonder why they did not just test for not equal to true. Seems like that one test would cover both cases. If it were out of the Users or Groups GCV specified containers, it would be absent and thus not equal to true. If it were a user without an entitlement we would have it set to false. So again, not equal to true.

Not that this is a huge difference, just wondering if there was a reason for this decision. It is fun to second guess folk.

Match Users

For User objects, we do use a Find Matching Object action token using the CN value as the match criteria. We saw earlier in the Sub-Event that if the operation attribute is multivalued, it is stripped down to the naming value. We probably could have just specified a value for CN of Source Name() to get the same affect. However this rule is using the Source Attribute token to get the CN, which means it ignores any work done to help fix a multivalued example. In fact it seems like Source Name would have been a much wiser choice at this point.

I know that later we will see in the output transform that the CN will be transformed into a User Principal Name like format by adding on @domain.com from the GCV drv.domain.name for both the Modify and Query cases, so even though it seems like we are matching on just the simple CN value, really we are looking for User Principal Name.

Query Display Name

Finally for Users and Groups, assuming we did not yet find the User by CN/UPN then we try to match by displayName. The problem is that there is no displayName in the filter, coming out of eDirectory, nor any rule that adds it on before this point, so this is unlikely to ever work. Additionally the Schema Map does map these attributes to Full Name on Users and CN on Groups, but when the query is executed, there is no displayName value available. Additionally, the schema map seems to show that the mapping of Full Name (for User) and CN (for Group) is to DisplayName, and often in schema case sensitivity matters. So I am not entirely sure what is going on here.

That wraps up the Matching Policy Set, onwards to the Creation Policy Set.

Creation Policy Set

There are two policy objects in this set.

  1. NOVLOFFIENTEX-sub-cp-EntitlementsImpl



There are two rules in this policy:

  1. UserAccount entitlement: Veto account creation when entitlement not granted

  • Prepare to check group entitlements after add

These two look to be cloned from another driver, and are the pretty common approach being taken in drivers lately.

UserAccount entitlement: Veto account creation when entitlement not granted

This is a gatekeeper rule, so that user accounts without entitlements are blocked if the GCV is set to require entitlements.

Prepare to check group entitlements after add

If this is a user object with a Group entitlement, then add an operation property, "check-group-entitlements" that will be considered in the Input Transform, once the <add-association> event is detected. That is, once the user is successfully created, then look at any group entitlements and implement them on the now instantiated user object.


There are four rules in this policy object, and at least one of them is reasonably unique to this driver.

  1. Check for needed User attributes

  • Veto if nspmDistributionPassword is not available

  • Check for AD driver association

  • Check for needed Group attributes

Check for needed User attributes

The main purpose of the Create policy set is to block incomplete objects from syncing and in this case, it is Full Name (and in the next policy Universal Password) that are the required attributes. Thus if no Full Name attribute in the current event, then the event is vetoed. If you are new to IDM you might ask, but my modify, that became an add (since it was not yet associated) did not have the Full Name attribute in it, so of course it will be vetoed. In fact, the conversion from a modify to an add of an unassociated object is called a synthetic add, and in the process the current state of the object is read out of the source (works in both directions) via a query and the results are used to build the <add> event document. Thus if Full Name was set on the user in eDirectory, it will be there in the synthetic add event.

Veto if nspmDistributionPassword is not available

Like Full Name, this driver requires a password, specifically nspmDistributionPassword which is the Universal password.

Check for AD driver association

This driver is interesting as it has two modes, sync users in general (with or without entitlements as configured) but also to only sync those with an Active Directory account in a specific domain or domains. This is determined using the DirXML-Associations attribute and a GCV listing the domains being supported.

The GCV drv.sync.identity is a structured GCV with multiple instances, one per supported domain. You give it a domain name, and the DN of the driver connecting it to your IDM system.

This loops over the drv.sync.identity GCV values, which is an <instance> node with the two GCVs defined inside it. They nicely trace out which driver they are working on first with a trace token, using the XPATH:

So inside the current <instance> document, find the <definition> node, whose XML attribute "name" is drv-ad-driver-dn, and then get the text of the <value> node.

Then there is a condition of:
<if-xpath op="true">count(add-attr[@attr-name='DirXML-Associations']/value[component[@name='nameSpace']/text()='1' and component[@name='volume' and contains(.,$current-node/definition[@name="drv-ad-driver-dn"]/value/text())]])=0</if-xpath>

This says test if the following XPATH is true:
count(add-attr[@attr-name='DirXML-Associations']/value[component[@name='nameSpace']/text()='1' and component[@name='volume' and contains(.,$current-node/definition[@name="drv-ad-driver-dn"]/value/text())]])=0

This requires that DirXML-Associations be in the filter as subscriber notify at least, so that we have the DirXML-Associations values in the event document (thus no query needed, which is how I would normally do it). Then count() the number that match our current AD driver DN we just traced out, and if it is zero, then we will send a status (level of warning) that we veto this event.

Inside the count() we have the following:
add-attr[@attr-name='DirXML-Associations']/value[component[@name='nameSpace']/text()='1' and component[@name='volume' and contains(.,$current-node/definition[@name="drv-ad-driver-dn"]/value/text())]])

This part:

gets us our specific attribute, and then we fool around in the <value> node, looking for a nameSpace value of 1 (associated), and the volume component set to our current value.


This nicely limits events, in the case we only sync AD accounts to O365, to only those with associations to supported AD Domains, and actual active associations.

You can read more about handling association values in XPATH in this article:
Using XPATH to examine Association values

It looks a bit tough, because the attribute is structured in Path syntax with three components and we need to match two of those components to detect our specific case.

Then of course the loop would proceed for the next AD driver.

Actually, as I think about this I realize that this policy will not work if there are two or more AD drivers listed, and the user does not have an association to the first AD driver. It will loop through in sequence of the GCV, and if the user is not associated to the first AD driver then it will veto, even if they do have an association in the second or third. I will report this issue to get it fixed.

Check for needed Group attributes

Like the check for Full Name on a user, the required attribute on a group here is just CN. You know, it needs a name, which is actually sort of silly since the Group objects naming attribute is CN by default, so if a group exists it must have a CN. I am not entirely sure of the point here. This is worth distinguishing from an Active Directory driver, where in fact CN is not used in the filter as the naming attribute for AD, rather the DirXML-ADAliasName attribute is used instead.


How To-Best Practice
Comment List