Walking through the IDM 4 Google Apps Driver - Part 10


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 the eighth article in this series I wrapped up the Output transform Policy set and start in on the Input Transform policy sets.

In the ninth article in this series I continued on through the Input Transform policy set.

In this article I continue through the Input Transform.

Still in the Account Tracking package policy object.


Now let's get on to the rest of the policy object that I did not quite get through in the last article.

AccountTracking - update DirXMLAccounts attribute on regular operations

Here again we have two condition groups, to handle the two ways we could get here. Either by an event of an object changing on the Publisher channel, or a Subscriber event returning success as a Status document.

First condition group is for a change from the application side, and we look at four op properties.

AccountTracking-Operation is not available, and the other three are available. They are:




I understand why we need the three to be available, because that means we know the target user, we know the status of the user object. But I am not sure why we only want to fire if the operation is not known. Something to think about.

The second condition group is for events coming back as a status event after being submitted on the Subscriber channel.

For these it has to be a Status event, with a success or warning value in the XML attribute 'level'. We need the AccountTracking-Operation op property, it should not be a delete event, we need the AccountTracking-ObjectDN op property and the two account status op props AccountTracking-IdvAccountStatus and AccountTracking-AppAccountStatus.

Now on to the actions, where first a test for the variable AccountIdentifiers, if it exists, then we have an object in the directory and this is either a match or a modify. If there is no such variable, then we probably need to add the object class of the aux class DirXML-Identity to the object as part of the add operation so we can then safely add the DirXML-Accounts attribute.

Then we loop through the drv.accTrck.identifiers GCV values, which for the Google Apps driver is just UserName and set up much as we did in the delete or remove case. We get the account status op properties into local variables, and set the search-key to the driver GUID a # sign, and then the identifier. Which does not make sense initially as we would want the attribute with the identifier attribute name. Hmm.

If the GCV for account tracking mode is 121 then we set the realm variable to the realm GCV, which is just Google in this case.

Otherwise, if this is a fanout driver we do a lot more work, which is not directly relevant to this driver so I will skip it I think. I think I will come back and address just the Account Tracking rules in another series, where I will work through the Fanout case more fully. Thus ends that first if-then code block. Now for all cases we march onwards.

An empty nodeset variable is defined as var-accountElements. When you want to build a nodeset, that is actually XML, I always thought you had to put in the parent node, with an XML Parse token of something like <top-node/> so that there was a parent node. But it looks like you can get away with just nothing as you define the nodeset! This is great to know. I have an article about using the XML building tokens, Append XML Element, Set XML Attribute, and Append XML Text.

to build XML as you need it. This can be done into a local variable as well as into the current event. You can read more about it in this article:
Common Mistakes Newcomers to IDM Make - Part 10

Now we do a for each over the AccountIdentifiers values (which is the DirXML-Accounts attribute values) again with an XPATH that limits it just our drivers, as we did at the end of the remove case.

$AccountIdentifiers[starts-with(.,$search-key) and contains(concat(.,'#'),concat('#',$realm,'#'))]

This looks for the value that starts with the search key, which is the driver GUID followed by a # sign, and then the rest contains our realm value surrounded by # signs, so as not to conflict with a user named Google. (I.e. Even if the username was the realm, it would not match unless the name was #realmName# which seems unlikely to naturally occur.

Inside the for each we set the var-accountElements empty nodeset variable to the components of the value, split on the # signs. This makes a nodeset of values, which can be looped over, but not XPATHed since it is not XML in the nodeset.

Then, after the loop we test again to be sure we actually got some DirXML-Accounts values back, by testing the AccountIdentifiers variable, then inside we test if the count of the var-accountElements is greater than 1. I imagine this is to make sure we did not get a nonsense value for a DirXML-Accounts entry. If there were no # signs in the value of DirXML-Accounts to be split into a nodeset, there would be only one node.

Inside this if-then block, we check to see if the op properties with the account state are set to -, the defaults. If so we read the 4th and 5th element of the split up var-accountElements variable. This uses a set local variable var-idvStatus to XPATH of $var-accountElements[4] which means the 4th node, and var-appStatus to the 5th element. (Sorry no Bruce Willis here).

Next we have a big if-then block, still inside the loop over the identifiers GCV values, so probably current-node is UserName at the moment, testing if the op property Account-Tracking-$current-node$ is available. That lets you build variable names dynamically, so really it is looking for an op property named AccountTracking-UserName.

If so, we trace out that the account identifier Username changed. The variable search-key gets set again, even though the entire for each loop still has access to it,

We loop over the AccountIdentifiers variable, again with the XPATH predicate that it has to start with the driver GUID, and contain the realm and if we find one, we remove it. (No easy way yo modify an entry in IDM. You have to remove the old one and set a new one. The set tokens do this on pass by sending a remove-all-values and then adding back the new value.)

Then the op property that got us into this in the first place, Account-Tracking-$current-node$ is stored in a local variable tmp. If the string length is greater than 0 (since you can have empty op properties and they are 'available' but empty) then we reset the value of tmp to be the following elements, separated by # symbols.

Driver GUID

current-node (UserName in this driver)

op prop Account-Tracking-$current-node$ value




Thus we have the basic make up of all the components of a DirXML-Accounts value.

Thus earlier when we read back the 4th and 5th elements you can see that they represent the idv and app status of the account.

Then we add this value to the DirXML-Accounts attribute.

If the current-node of our loop over the Identifiers GCV is 'association' then clear the op property Account-Tracking-$current-node$.

Now if Account-Tracking-$current-node$ was not available, we do the else block.

If the op property Account-Tracking-$current-AccountStatusChanged is true then we need top repeat much of above to remove the old value, build up the new one, this time for the third element using the data in the split up nodeset we built from the old value instead of the non-available op prop Account-Tracking-$current-node$. This assumes that the var-accountElements has more than one node. If not, then use the alternate approach in the else block.

If the identifier is association, build up the value to add, but use the association for the third element. But if the identifier is LDAPDN then query for the destination object into a nodeset and if the association node is not blank (I.e. it is associated) then query the source using the association, test if the src-dn XML attribute got a value, and then use that as the identifier in building the DirXML-Accounts string value.

If the identifier is still not matched then the catch case is probably an attribute name. So we query the IDV for the object by the Account-Tracking-ObjectDN path, check that it is associated, and then use the association to read back the attribute named from the object and updating the DirXML-Accounts attribute.

Now part of this work seems inefficient. Source attribute would work instead of this double query approach. I think we ought to be able to simplify this a fair bit. In fact, I probably would have just done the loops to figure out the Identifier value case and just done the remove and add in a single action, instead of repeating it all nested each time.

Finally we are done with this rule, just some op property cleanup for:





AccountTracking - update DirXMLAccounts attribute on mapped operations

This rule is meant for the fanout case, and I think I will skip it as it is not relevant and it is pretty complicated. I think I will revisit this when I do my series on the Account Tracking Packages.


Now this rule is an interesting one, and it is needed to support Resource objects as added in RBPM (Roles Based Provisioning Module).

I have already addressed this rule. You can read the original article by Volker Schreuber and John DaSilva on what needs to be done in this article: Convert Driver Entitlements to New RBPM 3.7 Resource Model

I looked at the policies and walked through what is happening in this article: Converting Entitlements to Resources, more details

So I will skip this one as well since I have covered it fully before.


There is only one rule in this policy.

Intercept GoogleGroup (tagged identity query) query response

Now this is the second half of what we saw in the Output transform, where queries for Group info were converted into odd looking queries that looked like they were driver startup document requests.

At that time I suggested that maybe they could not support queries and thus made sure that it succeeded even if the data was nonsense so as not to hang up the driver. But it looks like I was wrong and in fact it uses the tags set in the Output Transform to properly handle the query.

The first thing done to tag it was set GroupEntitlementQuery variable to true, and make it driver scoped. So if it is true, then we know we are in the proper case. Now as it happens, this helps to stop this rule from firing on a driver startup document, since both are for the same object class, "__driver_identification_class__" (the underscores are intentional), and thus we do not want to fire on a real driver startup event. They also make sure it is an instance document, which is a query response.

The first thing done when this rule fires is to set the GroupEntitlementQuery variable to false to make sure the next event does not think it is a query again.

Then the operation class name is set to GoogleGroup, so we morph the object class away from the funny driver startup class.

Now I do not entirely understand this rule, since it looks like it removes all the data and then basically does nothing. So I will assume this is another example of how Group support is not yet complete in the current driver configuration.

It looks like having seen a driver trace that queries into Google for group names can work, but this specific Entitlement query that might come from say the Reporting modules, sends back a simple response.

We will see in the next policy that the User equivalent of this query returns the same document, formatted for the main domain and any sub domains.

Well this is a good spot to stop, almost done with the Input Transform just one more article to go, and we can wrap it all up. I hope you are enjoying this series, and if you have any questions, please let me know.


How To-Best Practice
Comment List