Walking through the Office 365 IDM driver – Part 6


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 this article on to the next policy set, Placement and beyond. However there is no Subscriber placement rules, I guess that the name space is flat from the perspective of a tenant of Office 365.

The Command Transform policy set, in the Subscriber channel, looks a lot like most Command Transforms, with the following nine policy objects:

  1. NOVLADAUDENT-sub-ctp-Audit-TagEvent

  • NOVLOFFIDCFG-sub-ctp-Rename

  • NOVLOFFIOPTL-sub-ctp-HandleAttributes

  • NOVLOFFIENTEX-sub-ctp-EntitlementsImpl

  • NOVLPWDSYNC-sub-ctp-TransformDistPwd

  • NOVLPWDSYNC-sub-ctp-DefaultPwd

  • NOVLPWDSYNC-sub-ctp-CheckPwdGCV

  • NOVLPWDSYNC-sub-ctp-AddPwdPayload

  • NOVLOFFIPSWD-sub-ctp-TransformPwd

Some of these are generic policies that come from common packages, like the first one for Audit of entitlements. Others like the NOVLPWDSYNC policies come from the Password Synchronization Common package, and are common with most drivers. This one has a twist, that it adds an additional driver specific policy as the last one (NOVLOFFIPSWD-sub-ctp-TransformPwd).

1. NOVLADAUDENT-sub-ctp-Audit-TagEvent

There are three rules in this policy:

  1. User UserAccount Entitlement change (Delete Option)

  • User UserAccount Entitlement change (Disable Option)

  • User UserAccount Entitlement remove (Delete Option)

All three do the same basic thing, just in different cases based on configuration settings in the GCVs. There is a GCV that controls what the driver should do when the UserAccount entitlement is removed. Should you delete the remote user or disable them. Well here we handle both settings in the first two rules, doing basically the same things, just with a different value set into one operation property, but we also handle a third case of an eDirectory based delete event, as a result of an entitlement change.

These three rules, as the name suggests are here to tag some info onto the event for later use.

It seems like it sets the following operation properties in the three various cases:

  • accountAction

  • sourceDN

  • association

  • guid

  • objectClass

The accountAction is either accountDeleteByEntitlementRevoke or accountCreateByEntitlementGrant on the Delete approach to entitlements, or accountDisabledByEntitlementRevoke or accountEnabledByEntitlementGrant.

In the Input Transform, there is a policy, NOVAUDTENTC-itp-SendEntitlementsEvents that reacts to this op data and sends appropriate Audit events to Sentinel or the like.

This is a downside to packages, as it is hard sometimes to bundle everything needed into one focused package, and sometimes content needs to span multiple related packages. But this is not so terrible. I think a comment in the rules that explained this minor issue would have gone a long way to helping though.

With the three rules in this policy, the first two handle the op data payload for when an entitlement is changing (added or removed) and the cases where the GCV in charge says Delete or Disable the user on a removed entitlement. Thus the accountAction has a different value in terms of saying Delete or Disabled and Create or Enabled as the GCV manages it.

The third rule is interesting and clever since it handles the case as seen before where the user is just deleted in the identity vault and this event is flowing to the connected system. This is an implicit Entitlement remove since there is no entitlement anymore if the object is gone. Thus sending an event through that this user was deleted in the connected system makes sense for auditing.

2. NOVLOFFIDCFG-sub-ctp-Rename

There are four rules in this policy, for handling rename events.

  1. break if not rename

  • escape source object name

  • map rename to modify

  • discard unwanted renames

break if not rename

This is a common scoping rule, just break out of the policy entirely if this is not a <rename> event.

escape source object name

The allowed characters in a name in Office 365 are probably the same as for an account name in Active Directory, and so we have a similar clean up case, where any of the illegal characters found by this Regular Expression are removed.


Popping that into Regex Buddy (a nice Regular Expression tool I like) you get this explanation:


Basically the [] brackets mean this is a set of characters to be matched, and any of them found should be replaced with the replace text, which in this case is nothing. Then there is a caret (^) which negates the set, that is to say anything that is NOT this set of characters. Then some easy ones. a-z and A-Z get you the English letters upper and lower case. Then we move on to ASCII values and Unicode values who I could list, but I do not really know what they represent. But suffice to say, only this set of characters seems to be legal in a name in Office 365.

Thus any illegals are removed. This has a downside of unexpectedly changing a users name in the connected system, but since they would not sync otherwise, there is not a lot of choice here.

This is used to clean up the Source Name and store it in a variable, object-name.

map rename to modify

In Office 365 there is not really a rename event, since probably the name you login with, is not the actual object name. To be fair, I am not sure what the actual object name in the hosted system is for an object. But since it is really the login name for the user that needs to change, the User Principal Name is thus what is changed. This is mapped to CN by the driver already and gets appended the @ sign, then the domain from the GCV.

discard unwanted renames

Finally the <rename> event itself is discarded. There are no conditions, just a Veto, but since we started with a rule that limited us to just <rename> events we should be safe.

3. NOVLOFFIOPTL-sub-ctp-HandleAttributes

There are two rules in this policy:

  1. Handle attribute conversion for CN on Modify events

  • Handle attribute conversion for Login Disabled on Modify events

This policy comes from an Optional Package which is interesting, as these seem kind of important as things to have, and not all that optional.

Handle attribute conversion for CN on Modify events

For modify events, this one looks for two cases. Where XPATH of:

or XPATH of:

I am not sure why they took this approach, it would have sufficed to test for If Operational Attribute CN is changing instead. Much simpler, understandable and out of the box. I suppose this would distinguish between my example, and a case were CN is being cleared, with just a <remove-all-values> node, under the <modify-attr> node, but I cannot imagine that is why they did not just use if op attr is changing.

Regardless, a variable valueCN is set using Parse DN, length of 1, start of -1, on the Source DN token. This is amusingly redundant at several levels.

Most simplistically, Source Name() provides this exact function. Slightly more complex, the Source DN token includes the ability to truncate itself, with a sort of mini-Parse DN functionality built in. That is, you can specify on a Source DN noun token, the length and start all in one operation..

Then they use a Strip By XPATH expression token, for the XPATH:

Which is the modify of the CN attribute and all its children. Personally I would have just done a Strip Operation Attribute token for the CN attribute instead.

Then a test for If Class Name is user, we add a destination attribute value, CN, as the valueCN variable with @ domain name from the GCV appended to the end.

I.e. This reformats the operation attribute CN to be more like a User Principal Name or email address for Office 365s consumption.

If the class is a group, then the CN is added as just the valueCN variable. Oddly an Append XML Element token is used, to add a <remove-all-values> node, to the XPATH target of:

Which is to say, convert the Add Destination Attribute Value they just performed into a Set Destination Attribute Value. Which leaves me wondering why they did not just use the Set Destination Attribute Value in the first place.

To the authors credit, they used a comment on this rule, that says "Due to schema differences between eDirectory and Office365, this rule will get only the 1st value of cn attribute being removed from eDirectory when sending it to office365."

If that was their goal, then to be fair, they have not entirely accomplished the task. Because this is not getting the first value of CN, this is in fact getting the naming attribute, which is actually better, but different. The CN ordering is indeterminate so you cannot predict that the naming attribute will be first.

Now as a critique again, the same comment is copied into the next rule, which has nothing to do with CN. Alas.

Handle attribute conversion for Login Disabled on Modify events

Here we test for a modify event and XPATH of:
./modify-attr[@attr-name="Login Disabled"]/add-value

which is basically looking that we are adding a Login Disabled value. If you are removing a value only (and thus NOT adding one) you would be clearing the value of the attribute, and the absence of the value implies false. This is one of those funny boolean things in IDM where a boolean has three possible values (though only two actual effective values). It can be explicitly set to True or False, the obvious ones, but it can also be blank, which equates to false.

Next a variable accountValue is set to the XPATH of:
./modify-attr[@attr-name="Login Disabled"]/add-value/value/text()

This gets the value being added in the event. This of course is identical to the behavior of the Operation Attribute noun token, so not sure why they chose to do this the 'hard' way.

Then a Strip By XPATH for: ./modify-attr[@attr-name="Login Disabled"] instead of just simply using Strip Operational Attribute (since we have already established that there is at least a value being added, it would not matter if something was being removed as well).

Then the Login Disabled attribute value is added back to the event, using a Add Destination Attribute Value token, and a value of the local variable accountValue.

But then they do something very odd.

<do-append-xml-element expression='./modify-attr[@attr-name="BlockCredential"]' name="remove-all-values"/>

This tries to convert the modify of a BlockCredentail attribute into a Set Destination Attribute Value. But this seems like an error as well, as Login Disabled is the current attribute name, since we are before the schema map, which would have mapped it to BlockCredentail.

Of course, more simply they could have just done a Set Destination Attribute Value for Login Disabled a moment ago, instead of an Add Destination Attribute Value.

There is an entirely different additional issue.

These rules probably really belong in the Output Transform not in the Command Transform policy sets. The transformation of the meaning of the attribute values should be done there, in the Output Transform, not here in the Command Transform. Likely the Reformat Operational Attribute would be a good choice to use as well as it would then handle the Add and Modify cases nicely in one step.

This brings up yet another issue. The reformatting of the CN in the <add> case is done in the Output Transform, where it should be, in the policy NOVLOFFIDCFG-otp-Transform, but not using Reformat Operation Attribute, so thus a case is needed to handle Query, Add, and Modify events. As we will see when we get to the Output Transform there is lots to be said about the approach taken there as well, so stay tuned.

The use of BlockCredentail at the very end of this last rule, leads me to think that this was initially written for use in the Output Transform but was moved back to the Command Transform for some reason. I am not sure I can come up with a valid reason for that yet, but would be interested if anyone had an idea why they might have chosen to move it this way.

Stay tuned for the next article where I continue on through the Subscriber Command Transformation policy set.


How To-Best Practice
Comment List