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 Walking through the IDM 4 Google Apps Driver - Part 1 I worked my way through the Subscriber Event transform and half way through the Matching Policy set.
In the second article in the series Walking through the IDM 4 Google Apps Driver - Part 2 I worked my way through the rest of the Matching Policy set.
In the third article in the series Walking through the IDM 4 Google Apps Driver - Part 3 I worked my way through the Creation policy set.
In the fourth article in the series Walking through the IDM 4 Google Apps Driver - Part 4 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 Walking through the IDM 4 Google Apps Driver - Part 5 I continued to the end of the Command Transform and part way through the Schema Mapping policies.
In the sixth article in this series Walking through the IDM 4 Google Apps Driver - Part 6 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 Walking through the IDM 4 Google Apps Driver - Part 7 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 Walking through the IDM 4 Google Apps Driver - Part 8 I wrapped up the Output transform Policy set and start in on the Input Transform policy sets.
In this article I continue working through the Input Transform policy set.
In the last article I did not quite finish up this policy object, so lets continue with the rest of the rules, this is still part of the Account tracking package.
AccountTracking - add interested properties to current doc for future use.
Again testing for add, modify, delete, move, rename, but this time also checking for status operations, this rule fires.
The GCV drv.AcctTrck.objectClass lists the eDirectory name space names for the object classes tracked in this driver. The drv.AcctTrck.identifiers uses the Google Apps side name space for the attribute that identifies the object. This is a List GCV, which means it is stored in <item> nodes in the GCV, and if treated in a node set context, works as a node set to be looped over. You can read more about how the different GCV behave if you treat them as a string or if you treat them as a node set in the following article: Structured Global Configuration Values in IDM
Structured GCV's are the extreme example of this, as the article discusses but a List GCV can be very useful to use in the fashion this driver uses it.
A for each loop over the GCV handles the case of 0, 1, or more values cleanly and this looks like the rule we saw on the Subscriber side that looks just plain wrong, now makes a bit more sense, but I still think is wrong on the Subscriber side.
You may recall we saw a rule that did not loop, but looked at current-node and compared it to some clearly non relevant values, like LDAPDN, and others. Here we do properly loop, and compare the variable current-node to LDAPDN, then it further tests for the operation property named AccountTracking-$current-node$ which uses variable replacement inside the name of the op property itself, which is always kind of neat. The SIF driver, also from Consensus does this quite a bit which is quite clever. However it is clear from this policy that valid values in the List GCV are things like 'LDAPDN', and 'association' in addition to actual attribute names. However that previous rule was still clearly broken, because it was looking at current-node, outside the context of a loop, so it is not set at that moment in time.
So if that op property is not available but we do have a Source DN then the AccountTracking-$current-node$ is set to the Source DN. That would become AccountTracking-UserEntry since that is the only value in the GCV for this driver, that is being looped over.
If not, there is a nested if-then test, for if the current-node value is 'association', and for the op property AccountTracking-$current-node$ not available, but there is an association available, then the op property AccountTracking-$current-node$ becomes the association value. In other words make sure that the association value is represented somehow, regardless of how many different ways we might have to try to get it.
Now if this nested internal test is not three, then there is one more nested if-then test, this time for op property AccountTracking-$current-node$ not available, and the operational attribute is available, then set the op property AccountTracking-$current-node$ to the value sent in.
What this does is allow you to specify an identifier coming in that is an attribute value (name the attribute), a special case of the LDAPDN, which then uses the Source DN value (Probably NOT the LDAP DN for most drivers however), or the association value. A little convoluted and ought to be commented in the GCV description, but a neat way to handle these exceptions.
AccountTracking - Initialize status properties on published events
This time we are back to testing for the operation of add, modify, delete, move or rename (no status) to fire this rule.
This is the converse of the Subscriber rule we had that looks at the object and decides if it is Active, Inactive, unknown, or undefined. (A, I, U, or -)
Two variables, var-idvAccountStatus and var-appAccountStatus are set to dash, which is default, and then using the GCVs drv.AcctTrck.statusAttr to see if we have one of these named attributes in our event doc (if operational attribute ~drv.AcctTrck.statusAttr~ is available) then we set the op property AccountTracking-StatusChanged to true, since we have an event with this data in it.
Then we test to see if the event is activating or deactivating the user. This is done by testing the op attribute named in the GCV drv.AcctTrck.statusAttr if it is equal to the defined drv.AcctTrck.ActiveStatus.
If so we set the var-appAccountStatus to A for active.
If not, we test again, but this time the same attribute for the value of drv.AcctTrck.InactiveStatus, and if so we set it to I for inactive.
If still not, then we know we have a value but it is neither the Active nor inactive defined values, therefore we set it to U, for what I assume is undefined.
Now going back to the else block of the first if-then block, if there is no operational attribute that indicates active status, then maybe it is an add event, in which case we set the variable to the GCV drv.AcctTrck.idvDefaultStatus.
Finally we set the op properties AccountTracking-IdvAccountStatus and AccountTracking-AppAccountStatus to the values of the variables we have been working with either the A, I, U or dash (-) value.
Up till now the various rules have been adding in operation data and not really doing anything to the objects yet. Finally we get to a policy where we will start writing data to the directory.
AccountTracking - Initialize Realm Mapping
This is a repeat of the Subscriber channel Realm mapping initialization. This is another reason why the realmMappingInitialized variable is set to a driver scoped variable. This needs to be in both channels, since the event that first triggers it might come from either channel. You can read earlier in this series (### Link to Article with Sub channel version####) to see more details of this rule.
AccountTracking - disregard if disabled
This simply checks the GCV to see if Account Tracking is even enabled. If not, break out of here.
AccountTracking - query DirXML-Accounts Attribute
If the operation property set in either channel, AccountTracking-ObjectDN is available, then it sets up a local variable AccountIdentifiers, with the DirXML-Accounts attribute from the destination object (aka in eDirectory, the Identity Vault). We will use this to know whether this system is already listed as a DirXML-Accounts entry and whether we need to change it based on the event data.
AccountTracking - remove Dirxml-Account values on regular delete operation
This rule is trying to handle deletes, per the title of the rule. To do this, it really needs to handle two cases. First a natural delete coming down the publisher channel from the application, and second a delete that was sent on the Subscriber channel, and react to the status document where it succeeded. Thus we see two condition groups.
If the operation is delete or remove-association and the AccountTracking-ObjectDN op property is available (since we need to know which object to modify, and in both channels we made sure to set it, if it is available).
Then a second condition block if it is a Status event, we have the AccountTracking-ObjectDN op property, and the AccountTracking-Operation is delete.
Now the first action is an if-then, but with a condition that seems a bit off at first, if the GCV drv.AcctTrck.mode is equal to 121. If you go and look, in the GUI the options are fanout and One To One, but it is a GCV of type enum, an enumeration. This type of GCV allows you to specify pretty names to select from a list, but have either a simpler or just plain different value as the actual value stored in the GCV. Here they were being cutsey and One To One becomes 121. Thus a drv.AcctTrck.mode of 121 is the opposite of the fanout mode.
If so, the realm variable is read from the drv.AcctTrk.realm value.
If it is not a 121 case, then it must be a fanout case so the Else block is for fanout, and then a quick check since nothing stops you from editing in nonsense, so check to be sure this is a fanout case, by checking the value of the GCV for mode.
If so we need to start looking into picking apart the realm data, since a fanout case is meant initially (at least) for the SAP UM drivers where one driver may push a user into multiple SAP modules (User modules, I think, thus the UM). However, since this is irrelevant to the Google Apps driver I think I will drop it quickly. What I will say is that it uses a GCV to identify how to pick the realm key, and then an extractor, which is a Regular expression to pick it apart. It is kind of neat, and I intend to revisit the Account Tracking Package as a series on its own in the near future.
After the fanout else case, we trace out a message about which realm is involved, which for this driver is just Google.
Then, for each of the DirXML-Accounts we stored in the variable, AccountIdentifiers, but with an XPATH twist to only select the ones we want:
$AccountIdentifiers[starts-with(.,$dirxml.auto.driverguid) and contains(concat(.,'#'),concat('#',$realm,'#'))]
This means, in the nodeset variable AccountIdentifiers (since XPATH does not work on a string in this fashion) lets find using a predicate (the  brackets), where the value of the moment (the period) starts with the driver GUID value from the auto GCV, and also contains a # symbol, but that segment is tricky to parse. Lets break that apart.
So contains() takes two parameters, the complete string as the first one, then the value to see if it is contained within that first string.
So the string is therefore: concat(.,'#') which means the current context document, but treated as a string, with a # sign at the end of it. Then we look to see if the string defined by concat('#',$realm,'#') is within it.
concat('#',$realm,'#') means a # followed by the realm variable followed by a pound. I guess they append the trailing # to the overall string in case the last element is realm value. Then by surrounding the realm in # signs they can be sure that there won't be a user named Google for example that this might fire on. Or that the DN of the driver might have Google in the name. Nice way of protecting the value to be certain we are not going to accidentally have a user or other object with the same name as the Realm name.
Thus basically the whole point of that XPATH was to only loop over the relevant DirXML-Accounts values, that represent this realm. Then for each such entry, trace out a notice that we are removing this value and then remove the destination attribute value.
The Realm is set per driver, when you import it into your project either via iManager (for the CMP (Compliance Management Platform) driver versions where the Account Tracking stuff initially came from) or via Designer with the new packages, and used in Sentinel to identify the driver. Thus you could have three Active Directory drivers, each considered a different Realm.
The Sentinel driver sends the DirXML-Accounts attribute to Sentinel for inclusion and tracking in the Sentinel database, thus allowing Sentinel to know the accounts each user has, so that when an event is correlated to a single event, it can link it to other accounts that might be vulnerable. After all if your password is synchronized between systems so you can remember it, should it be compromised in one system you really want to know and possibly do something about it, like locking or disabling it in all systems post haste!
That about wraps up this article. Getting closer to the end, only a few more policies to get through to finish the Input Transform.
Disclaimer: As with everything else at Cool Solutions, this content is definitely not supported by Novell (so don't even think of calling Support if you try something and it blows up).
It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.