Walking through the Office 365 IDM driver – Part 11


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 part five of this series I worked through the Subscriber Match and Create policy sets.

In part six of this series I started in on the Subscriber Command Transform policy set.

In part seven of this series I continued through the EntitlementsImpl policy in the Command Transform.

In part eight of this series I finished up the Command Transform and started into the Output Transform.

In part nine of this series I finished walking through the Output Transform.

In part ten of this series I started down the Input Transform policy set getting through the first six policy objects.

There are ten policies in the Input Transform, some are common ones (Account Tracking, Entitlement Configuration Resource, Init managed System Info) and some are unique to this driver configurations packages.

  1. NOVLOFFIDCFG-itp-Transform

  • NOVLAUDTENTC-itp-SendEntitlementsEvents

  • NOVLOFFIENTEX-itp-InitEntitlementConfigurationResource

  • NOVLATRKBASE-itp-Publish

  • NOVLOFMSINFO-itp-InitManagedSystemInfo

  • NOVLOFFIENTEX-itp-EntitlementsImpl

Got through the first six already, and only four more to go:

  1. NOVLDATACOLL-itp-DataCollectionQuerySupport

  • NOVLATRKBASE-itp-Publish2

  • NOVLATRKBASE-itp-WriteAccounts

  • NOVLPWDSYNC-itp-EmailOnFailedPwdSub

7. NOVLDATACOLL-itp-DataCollectionQuerySupport

This policy is part of the Data Collection package, that is generic to many drivers. What it does is reformat any attributes that are of type DN. This is important, since if you have ever looked at the trace from a driver, you will often see a message like: "Unable to Resolve reference to XXXXX" and depending on the direction and context, the value will be stripped out of the event. This is important since DN syntax attributes rarely end well, if a bad value is written into them. For example, if you write a non-valid DN into an eDirectory DN syntax attribute you get an error 613 Invalid syntax. On Active Directory I recently ran into that, and it returns an Access Denied (5) error. Neither of those two errors is greatly informative, that is, a syntax error vs access denied in terms of what the root cause is.

It is worth noting on the eDirectory case a bad DN means several things. First, a blank DN value for a DN attribute is invalid. Second a nonexistent object, like say setting a manager during an initial migrate and the manager has yet to be created in eDirectory, would throw this error. Third, if the format is not perfect, then really you run into the second case, since that object clearly does not exist, if it cannot be described.

This rule looks for attributes that have XML attributes in the <value> node of "association-ref". It does this by for each looping over the XPATH:


I wonder why they did not bother more generically look for XPATH of attr/value[@type='dn'] which in theory should detect the same case. That is, all DN type attributes. Especially since the action is to add an association XML attribute with the same value and overwrite the 'type' XML attribute with a value of {dn} which will change the way the engine processes it, and won't remove it, if the object cannot be resolved, and finally remove the association-ref XML attribute.

I wonder if there is a real case where you can have an association-ref XML attribute on a <value> node and not have it be of type='dn'? The example that comes to mind is a structured attribute, where the sub-components of the attribute have DN type values. There are a bunch of great structured attributes available in eDirectory, which I have discussed before in these articles:

Probably my favorite is Path syntax which has three components, volume (a DN), nameSpace (an integer), and path (or path.xml, long story) a string. You can see an example here in a query response for DirXML-EntitlementRef:

<nds dtdversion="3.5" ndsversion="8.x">
<product version="">DirXML</product>
<contact>Novell, Inc.</contact>
<instance cached-time="20110221221739.710Z" class-name="User" src-entry-id="813253" timestamp="1298326659#1">
<attr attr-name="DirXML-EntitlementRef">
<value timestamp="1298326653#2" type="structured">
<component name="nameSpace">1</component>
<component name="volume">\ACME-TEST-05\services\IDM\DriverSet\ADDriver\EntitleTest1</component>
<component name="path.xml">
<id>services\IDM\DriverSet\Entitlement Policies\RBE-RoleTest1</id>

For a structured attribute, the <value> node is type of 'structured', and then each component, has a name, but no type attribute. I am not sure if an association-ref attribute will be added to the volume component by the engine or not, but the XPATH in this policy won't catch that anyway.

A better way, if that is true for structured attributes would be to change the loops XPATH from:


To something more like:


which would look for any node with an association-ref XML attribute, and then the rest of the existing code should just continue to work. Well almost work. It probably should not set type="{dn}" on a component of a structured attribute, but that is a minor change.

At the end of this, the DN type attributes do not get stripped out if the object is not in the Identity Vault, and thus the Reporting module can get the proper value back and process it.

8. NOVLATRKBASE-itp-Publish2

9. NOVLATRKBASE-itp-WriteAccounts

These two policies are part of the Account Tracking generic policies and are a bit complicated. Basically an operation property is set in the first one, with the DN of the object. The second policy object decides what to finally write out to the DirXML-Accounts account. In practice, this is sort of annoying in trace, since it does tons of work, on almost every event, since it tries to decide if this event is changing the users state from active to inactive or deleted. Once that is determined it updates the DirXML-Accounts attribute which the Sentinel driver synchronizes so that Sentinel can know who has an active or disabled account at any moment in time.

You would think this is simple, but in fact, it could be a different attribute than Login Disabled that determines account activity. These packages support naming the attribute to use as a flag, but only supports a single attribute. Perhaps, you need a pair of attributes set to properly flag it? Well you could copy the Account Tracking package, and modify the policies here to manage your pair (or more) of attribute cases.

I have reviewed these policies before, so will not get into serious detail here.

10. NOVLPWDSYNC-itp-EmailOnFailedPwdSub

This is the standard Password Policy that looks for a failed password change attempt, and if the GCV is set, notifies the user. You can read more about this entire sub-package of policies in this series, which although written before the days of Packages, have not materially changed.

That completes the Input Transform, lets move on to the Publisher Event Transformation now. There are two policy objects to look at:

Publisher Event Transformation

  1. NOVLOFFIDCFG-pub-etp

  • NOVLOFFIENTEX-pub-etp-EntitlementsImpl


There is only a single rule here:
re-format CN

This looks for User events, and reformats the CN value.

It is interesting how they approached this. Again it looks like they do not know about the Reformat Operation Attribute token, as we have seen elsewhere in this driver, and basically have to recreate it from scratch.

First up they get the CN values with a fairly complex XPATH:

modify-attr[@attr-name='CN']//value | add-attr[@attr-name='CN']/value

That is, for modify-attr and add-attr nodes (since a modify and add event look different in the underlying XML) and then get the value for the CN attribute. One subtle difference between the modify and add case, is the use of a double slash in the modify case, since under a modify-attr, you have either an <add-value>, <remove-value>, or <remove-all-values> nodes, before having the child <value> node.

Anyway, they then do something that I first looked at and said, this won't work. But I ran a sample through Simulator and it does work. Now why?

But first what?

The issue is, they loop over the variable holding all CN values from either the add or modify case.

Then they split the value based on the @ sign, since CN in the Office 365 is really the UserPrincipalName of Active Directory fame, which should also be the email address at this point.

But the line that does this is what threw me initially.

<do-set-local-variable name="nodeVal" scope="policy">
<token-split delimiter="@">
<token-xpath expression="$current-node/text()"/>

They use the Split token, which returns a nodeset usually, but store it in a string variable. Then they strip the current node value, then add back in the nodeVal value instead.

The key seems to be, taking nodeset output from Split, and treating it as a string, does not do the same thing it does when the nodeset is XML with text in it. In the XML case, you get the concatenated values of all strings in the nodeset. In the string case you get the first value only, which is quite interesting to me. Learn something new every day, I assumed I would get all the values concatenated together from the nodeset. I shall have to keep that in mind. I was expecting that to get the first value only something like this XPATH of $nodeVal[1] would be needed.

2. NOVLOFFIENTEX-pub-etp-EntitlementsImpl

This entire policy object is dedicated to making sure that events coming out of the Publisher channel, map properly to objects in the Identity Vault, when considered in an Entitlement model context. For example, if a Group Membership changes, that should not start in O365, it should start based on an Entitlement change in IDV, sent to Office 365.

There are three rules in this policy object:

  1. GroupMembership entitlement: veto membership without entitlement

  • Disallow user account delete when using entitlements

  • Strip Login Disabled from operation (Disable Option)

1. GroupMembership entitlement: veto membership without entitlement

First up is for Group objects changing, the GCV controlling entitlements is enabled, then an odd Strip XPATH of:

./add-attr[@attr-name="Member"] | ./modify-attr[@attr-name="Member"]

That is, two statements, joined with an OR, one for the add case and one for the modify case. But of course, Strip Operation attribute for Member would do exactly the same thing, and is much easier to read.

With the release of the project formerly known as Jade, now called Permission Collection and Reconciliation Services, it seems this particular policy will need to be changed. The idea behind Jade (ok, PCRS, that was better somehow?) is that you read the groups and other role like objects out of the connected system to map them to RBPM roles in the IDM system, and when changes happen in the connected system, you reflect them in the Role model in IDM. This is a good way to start up existing systems and get them into Roles based models. Perhaps you maintain that two way flow, or perhaps you just turn it off once everything is loaded in, and running. But you can see why this particular rule is important when they get ready to add the Jade services to this driver. Initially PCRS is just supported on the Active Directory and Delimited Text drivers, but the expectation is that more drivers will get the functionality added.

2. Disallow user account delete when using entitlements

If the GCV that controls using User entitlements is enabled, and a delete event comes through, veto the event, after first removing the association out of the Identity Vault.

From the fact they do not test for class name of User, I suspect one of two things. First that Office 365 may not send class information on events (Since Active Directory does not either), and second that possibly Group deletes probably are rare or do not happen.

3. Strip Login Disabled from operation (Disable Option)

Same condition, that the User entitlement controlling GCV is enabled, the class is a User (leading more credence to my thoughts on the previous rule) and the attribute Login Disabled is available. When an attribute is 'available', it means an attribute value is being added. This is distinct from 'changing' which means an attribute is being added, removed, or cleared (Remove all values).

This too is an interesting choice, since this rule will Strip the operation attribute Login Disabled, if a value is being added. But not if a value is being removed. I am not sure if it is possible in Office 365 to remove a value only and not replace it, specifically for the Login Disabled attribute.

What this does not do, is write back to Office 365 and re-enable the user, which is possibly what it should do, if truly enforcing the entitlement model. That is, if you have the UserAccount entitlement, (still) and you get disabled in Office 365 that is an error. The entitlement should have been removed in the IDV (By removing a resource that grants it, or by removing a parent Role that has the Resource assigned to it). This is also true of the Delete rule a moment earlier, since it should look at the Entitlement and consider some action to remove it. That is trickier than it sounds, since an Entitlement can be granted due to a specific Resource or Role grant, to the object, its parent containers, or to a group it is a member of. Boy that would be a useful token in the engine, a Verb token in Argument Builder that takes input of an Entitlement, and traces back and returns the source object to remove that grants it. Sort of a reimplementation of the RRSD (Roles and Resources Service Driver) logic for figuring out the Entitlements an end node gets. If you knew what the root parent (or parents, could be the Resource is attainable multiple ways) Role for getting this entitlement would be, you could look at the currently assigned Roles, and then submit a request workflow to remove it, for approval, and if not approved, go put back the values.

Anyway that ends this section of this series. Stay tuned for the next installment as I try to finish the rest of the Publisher channel.


How To-Best Practice
Comment List