Walking through the IDM 4 Google Apps Driver - Part 8

over 9 years ago

With the release of NetIQ Identity Manager 4.0 Support Pack 1 (aka IDM 4.01) some bug fixes, and a few new features were added.

Specifically three partner provided drivers were included, an RSA Driver, a Blackboard driver, and a Google Apps driver.

I discussed some of the new features and bugs fixed in IDM 4.01 in this series of articles:

I have been working on a series of articles walking through driver configurations, policy by policy to try and understand what the driver is doing, under the covers.

You can see more of these walk throughs on a Wiki page I maintain to keep them all together: Detailed driver walk through collection.

For this series of articles I would like to start looking at the Google Apps driver in IDM 4.01, that is provided by Consensus Consulting.

In the first article in the series I worked my way through the Subscriber Event transform and half way through the Matching Policy set.

In the second article in the series I worked my way through the rest of the Matching Policy set.

In the third article in the series I worked my way through the Creation policy set.

In the fourth article in the series I started working through the Placement policy set.

In the fourth article I did not quite finish the Subscriber Command Transform, so in the fifth article I continued to the end of the Command Transform and part way through the Schema Mapping policies.

In the sixth article in this series I would like to finish the Schema mapping policy set and begin to work through the Output Transform policy set.

In the seventh article in this series I worked through most of the rest of the Output Transform. It turns out there is a fair bit more in the Output transform than I expected.

In this article I wrap up the Output transform Policy set and start in on the Input Transform policy sets.


Next up is handling user entitlements. This is basically the same set of actions that we saw with the Groups in the previous article, where the class name is removed, event-id, scope added back, search-class removed then added back as the driver identification class, and any read-attr nodes replaced with an empty one.

Finally a driver scoped variable UserAccountEntitlementQuery is set to true. Again it seems unlikely that this query will provide useful data, but perhaps since RMA, Reporting, etc expect this query to at least return, this approach guarantees success for the query attempt. We will see later in the Input Transform that it looks like there is really no data returned, specifically from Google, rather this tagging makes the query get a response that is basically constructed the same every time.


First rule scopes this to a delete for a UserEntry object (remember, past the schema map so User became UserEntry).

Handle Delete events by renaming object before it is deleted in Google

No conditions, since the first rule guaranteed us only the events we care about. The name indicates that they want to rename an object before it is deleted, which I do not entirely understand. I would guess that maybe the rename event is processed immediately by Google, but a delete might not make it to the global address book for a longer time? I know that some of the Profile data takes up to 24 hours to show up. This might be an attempt to get the name out of the address book faster than a pure delete would allow.

In any case, first an operational property newUserID is set to the current name (Source Name token) plus the date in CTIME (a count of seconds since Jan 1, 1970, so a large number in the 1.3 billion range right now) which probably guarantees uniqueness for the name.

Not sure why they did not just use a variable to store it, unless something in the Input Transform is going to rely on the operational property later in the flow. A quick look now does not find any such example, but you never know. It still works.

Then a variable is set from the operational property to lv-new-name, the lv-old-name gets the Source Name() value, and then a rename to the new name is performed, and the association value is changed to the new name value.

They do the association update in a funny fashion, which is using the set operation association, which being a set means overwrite the current value, but they take the current value (Using the Association() token), and apply a Replace All verb token to replace the old name with the new name. This is because the association value is the full email address, and we just renamed the first part of it. This way we get a properly formatted email address with the new name part.

I suppose they could have done a substring-after() call in XPATH looking after the @ sign to get the end bit and rebuilt it from there. Both ways ought to work fine. This way is quite clever. The only concern I would have had is if the user name might have had a special character in it that has special meaning in regular expressions, however I am pretty sure those are all illegal in email user names. Though a plus sign is legal, and Google supports it, so you might run into an issue there.

That concludes the Output transform policy set.

The Input transform policy set is about all that exists on the Publisher channel, since Google allows writes and queries for some bits of data, but no event system to tell us when changes happen in their system.

Thus the rules and policies here mostly relate to processing the query returns and success or failures of events. There are seven policy objects in this policy set.

  • NOVLADMSINFO-itp-InitManagedSystemInfo

  • NOVATRKBASE-itp-Publish

  • NOVATRKBASE-itp-WriteAccounts

  • NOVLGGLBENT-itp-InitEntitlementsConfigurationResource

  • NOVLGGLEGRPS-itp-EntitlementsImpl

  • NOVLGGLEUSER-itp-EntitlementsImpl

  • NOVLPWDSYNC-itp-EmailOnFailedPwdSub


If you read my series on the Managed Systems Gateway (MSG) driver, then this rule will be familiar to you. The MSG driver on startup initializes itself, and builds a stack of variables by reading back data from its configuration but also from all the other drivers. It looks for a GCV object named MSysInfo in every driver. With IDM 4 and Reporting support, all new driver configurations have this GCV. This is actually an interesting GCV object, since it comes out of the box, only half populated, and the second half is actually generated on the fly by this rule that is only run once at every driver startup.

I have already covered the logistics of how the MSG driver works, and how the MSysInfo object is used in an article series, so I will just suggest you go read that series instead of spending any further time on it, since there is copious amounts of information in the articles:


Now we get to the Publisher counterpart of the Account Tracking rule that was so befuddling in the Output transform.

AccountTracking - disregard if disabled or wrong object class

First up we have a rule that limits events to the monitored classes, and active users (remembering we are before the Schema map, so we need to use the correct class names).

The first test is if the GCV says Account Tracking is even on. If not, break and skip the rest of this policy.

Then if class name is available, we need to loop over the GCV holding the object classes we support. These are named in the application name space. Then each current-node is tested against the current class value. If this one matches, then the variable 'pass' is set to true.

Interestingly enough this could be simplified by setting class name into a variable and then doing an if local variable test, where the class name variable we just set is the variable name, and we test if it is equal to the GCV name, enclosed in dollar signs (used to insert a variables data). You might need to set the GCV into a nodeset variable, since this has to be done as a single value to a nodeset. Then the test will return true if any one value matches and false if none match. However this approach works fine as well.

If local variable pass is not true, in other words none of the classes listed match the current events object class then we break.

AccountTracking - on add-association sync the operation-properties to status operations

This tests for an operation of add-association, which is what the shim generates on a successful add, using whatever method is coded into the shim to set the association. You can see a list of the various known association values for all the drivers I was able to track down information about in this article: Open Call - IDM Association Values for eDirectory Objects

We continue adding to the operation properties that were built up in the Output transform, to be used soon enough. AccountTracking-association get sets with the XPATH of text() because an add-association event is a little bit funny and looks different than an add or modify event.
<nds dtdversion="1.1" ndsversion="8.7">
<product asn1id="" build="20101214_120000" instance="\MCOMMUNITY\services\IDM\DriverSet\UMROOT-AD" version="3.5.13">AD</product>
<contact>Novell, Inc.</contact>
<add-association dest-dn="\ACME\com\acme\People\abc40350" dest-entry-id="2363386" event-id="thornbill#20111017135943#4#2:d6352e78-0368-40d0-b387-782e35d66803">01c493b278e14a478315fca37512ecc3</add-association>

You can see that you cannot use the Association() token (I tried, it is not smart enough to know to handle the add-association event properly) and the normal XPATH of 'association' won't work either. But just getting the text() node of the current context is actually sufficient. This leads me to think that the Association() token is really just a wrapper around an XPATH call of 'association'. Thus looking at the above document you can see why text() is sufficient to get it. The current context is the <add-association> node, so you just want the text value of that node. In fact there is a rule in the Active Directory driver that basically just casts the <add-association> to a string, and that returns the string value as well. It threw me at first, but it does work that way as well.

Next the eventId variable is set with the add-association events event-id XML attribute.

Then an interesting clone by XPATH is performed to copy the operation-data/@AccountTracking-association, the value we just set, to the XPATH of:

This is because when a user or other object is added via the Subscriber channel, you get back two (or more) events. One is an <add-association> event that we are currently processing, and the other is a <status> event with either success or failure, though you won't add an association on a failure case.

So this XPATH says, search for any (//) status event, whose XML attribute event-id is the same as this add-associations event-id (That's why we set the variable a moment ago, though I do not see why [@event-id=@event-id] would not work. That is find the node via a predicate that says whose event-id XML attribute is equal to the current events XML attribute event-id. But I can see how that might be confusing to read. And finally the target is the operation-data node. This basically copies the association value we just set into the <status> document.

AccountTracking - Query for destination DN using Association

This rule looks it was designed for a standard two channel driver, since it starts by looking for modify, delete, move, or rename events to work with, and then if there is no AccountTracking-Operation op property available but there is an association available then it will process the rule.

A local variable ObjectDN is set to a node set value, using the Query token, using the association value of this event, to find the object.

This is really what the Resolve token is meant for, which allows resolving from a DN to an association and from an association back to a DN. However this works as well.

Then a quick XPATH test of
string-length($ObjectDN) > 0

Basically the question is, did we get a result back from the query? I.e. Did the association value in the event document resolve to an object in the directory with a matching association. The answer might very well be no. If there is no returned value, a <status> document is returned that is basically empty. If a value (or values) is found, an <instance> document is returned. Now it is interesting that they chose string-length, to use it on a nodeset. This forces the nodeset to be treated like a string and then to count its length.

I usually use count($ObjectDN) > 0 to do the same test. That is, count the number of nodes. A returned <instance> doc would include one node per object found. I have also seen a test of $ObjectDN/@src-dn used. This will only be true if the returned value has a src-dn XML attribute in it.

But in discussions with one of the original IDM designers, he pointed out that in fact, the best and most efficient test is just a simple XPATH of $ObjectDN, since if there was no returned value at all, that there would be no node set variable to exist and be true.

Regardless all the various methods I described work, just a question of which is more efficient, and unless you are doing this test thousands of times in short time intervals, it is not a big enough difference to really matter.

Now if there actually is returned value, then the XPATH of $ObjectDN/@src-dn is used to get the DN for the user in eDirectory and add an op property of AccountTracking-ObjectDN.

That is a good place to stop. Only a few more articles to finish up this series, just got to get through the rest of the Input Transform.


How To-Best Practice
Comment List
  • Handle Delete events by renaming object before it is deleted in Google

    A deleted Google Account can remain cached for up to 5 days for restore purposes. This means that although the account is not visible, you cannot create a new account with the that particular name for up to 5 days. Renaming an account before deleting it solves this.
Related Discussions