The Active Directory driver in all versions of Identity Manager from 2.0 and up, when we started using DirXML Script instead of XSLT for policies have had a pair of attributes in common. DirXML-ADContext and DirXML-ADAliasName.
These are used to handle the strange circumstance of a rename or move event in Active Directory. The shim cannot tell the difference between a rename or move event. Both cases are actually a modify of the distinguishedName (DN) attribute.
For example: cn=geoffc, ou=Users, dc=acme, dc=com
If this were to change, it would depend where the change occurred to know if this was a move or rename event. If the cn=geoffc part changed, then that is a rename event. If any of the ou=Users, dc=acme, dc=com part changed, then this was a move event, since the parent container for the object is now different, in other words a move event.
You can find the policies that manage this in the Publisher Event Transformation rule set. There have been a number of different shipping default configurations for Identity Manager, so the name of the rule and its exact workings have changed over time. With the advent of IDM 4 and Packages, we should see this stabilize and become more manageable.
The problem with using single valued, simple string attributes for this task is how do you handle a second AD driver in a different domain? Well if the user is only ever in a single domain, that is fine, but if you have worked with IDM then you know that one of the cool things about IDM is how easy it would be to manage users in multiple AD domains, eDirectory, and many other connected services.
If you add a second Active Directory domain to your IDM world, then the values of DirXML-ADAliasName and DirXML-ADContext will be incompatible between drivers and domains.
In the first article in this series Managing multiple Active Directory domains in one IDM system – Part 1 I discussed an approach in general of a plural version of the attributes, using Path syntax.
In the second article in this series Managing multiple Active Directory domains in one IDM system – Part 2 I discussed more of the specific implementation details of making this work. I provided some sample code for making sure you update the attributes correctly.
In this article I will work through more of the niggling little details needed to get this going.
As a quick recap, we will use DirXML-ADContexts and DirXML-ADAliasNames (note the plural) as multi valued, path syntax attributes instead of the single valued string equivalents that IDM ships with. In the previous article I showed some sample code on how you might update that attribute. The key is to remember to find the current value associated with this driver, remove it, then add a new value in.
Next up, is to decide WHERE do we need to make these changes? Well the easy way to manage this is to export the driver configuration as an iManager configuration file, open it in a text editor and then search for the various attribute names.
I wanted to use the latest configuration, since the IDM 3.6.1 has several possible configurations. (V4, V5, V6, and with one of the patches V7). However I happen to know that there are a number of bugs fixed in the IDM 4 Package version of the driver. I was starting a new project that needed an Active Directory driver but could not yet use IDM 4 for this project, instead had to use IDM 3.6.1. So I decided to try something funny.
I started a scratchpad Designer project, set up an IDM 4 Identity vault, added the Active Directory packaged driver, with all the options, and then I configured it for the most part.
Next I exported the driver to an iManager configuration file, and edited that, making it work with IDM 3.6.1. I have to find the time to write up that exercise as that was quite interesting to see how Packages have changed some things in the config files.
Then I searched through to find all the locations these attributes are in use. Here are my results, shown for the two different attributes, in case you want to identify them independently.
Input Transform: NOVLADDCFG-itp-SubscriberUserAdd 1 rule Publisher Channel: Event Transformation: NOVLADDCFG-pub-etp-HandleMovesAndRenames 3 rules Create Policy Set: NOVLADDCFG-pub-cp 1 rule Command Transform: NOVLADDCFG-pub-ctp 2 rules NOVLADENTEX-sub-ctp-EntitlementsImpl 2 rules (more?)
Filter (done) Schema Map (done) Subscriber Channel: Create Policy Set: NOVLADDCFG-sub-cp-Users, 1 rule NOVLADDCFG-sub-cp-Groups 1 rule Command Transform: NOVLADENTEX-sub-ctp-EntitlementsImpl 2 or more rules) Publisher Channel: Command Transform: NOVLADDCFG-pub-ctp 2 rules NOVLADDCFG-pub-ctp-UserNameMap 5 rules
New rules needed:
itp-Convert Plural Attribute
otp-Convert Plural Attribute
Lets start with DirXML-ADContexts as it is slightly less complex than the DirXML-ADAliasNames case.
The Input transform is actually one of the newest rules in the Active Directory driver, or more correctly is one of the later bug fixes. I am not really sure how this ever worked and why no one really noticed it before, but it turns out that on a merge event, the association and whatnot would correctly be added, but the DirXML-ADContext was missed.
The solution was this rule, the itp-SubscriverUserAdd rule, (part of the NOVLADCFG package in IDM 4), which I have discussed with the author (Hey Fernando!) and we agree it could be improved, but since it basically works, it is ok as is. Basically on the <add-association> event, the shipping rule would get the association value (the only text node in the event) use that to query back to Active Directory for the object (effectively doing what the Resolve token does) and then getting the src-dn from the resulting <instance> document to use as the value for DirXML-ADContext.
Well this is an easy modify. Instead of adding a destination attribute, use the rules discussed in the second article in this series and just loop through the destination objects DirXML-ADContexts values, look for one with this drivers DN in the volume component, and if found, remove it (which would clear up any duplicates nicely as well!) and then finally add the structured attribute with the nameSpace component being the current time in CTIME (count of seconds since Jan 1, 1970), the volume being this drivers DN via the dirxml.auto.driverdn GCV, and the path component being the LDAP formatted DN of the object in Active Directory.
Pretty much everything else for this attribute happens in the Publisher channel. After all as we discussed its main purpose is to enable the detection of whether the change to distinguishedName in Active Directory was a rename (the cn= value changed) or a move (any of the rest of the DN changed) event.
The biggest use of this attribute is in the Publisher Event Transformation, in the rule pub-etp-HandleMovesAndRenames (part of the NOVLADCFG package).
Here we have three rules to be modified.
setup for move validation
Previously this rule read the DirXML-ADContext (singular) and parse DN’ed it to start of 0 and length of -2, which means it takes the DN path, but not the CN part.
In other words cn=geoffc,ou=wranglers,dc=acme,dc=com gets the value ou=wranglers,dc=acme,dc=com into the cached-object-value attribute. Then current-object-value does the same ParseDN to the src-dn, which will later let us tell if the DN path has changed at all, thus making it a move event.
In our case, because the DirXML-ADContexts is plural now, we need to for each loop through the values, find the value with the volume component of our current driver, and set cached-object-value to the ParseDN processed value of the path component.
The code for that would look like:
<do-for-each> <arg-node-set> <token-dest-attr name="DirXML-ADContexts"/> </arg-node-set> <arg-actions> <do-if> <arg-conditions> <and> <if-xpath op="true">$current-node/component[@name='volume']="~dirxml.auto.driverdn~"</if-xpath> </and> </arg-conditions> <arg-actions> <do-set-local-variable name="cached-object-value" scope="policy"> <arg-string> <token-parse-dn length="-2"> <token-xpath expression='$current-node/component[@name="path"]'/> </token-parse-dn> </arg-string> </do-set-local-variable> </arg-actions> <arg-actions/> </do-if> </arg-actions> </do-for-each>
You have seen the loop over the destination attribute token in the previous article, and using the same basic IF XPATH true test of:
That is, since we get back one instance node, with many values, and the current context are the value nodes, (Because it is a destination attribute token instead of a Query token result, in which case the current context would be the <instance> node and thus our XPATH would look different, more like
to account for the different results) we are looping through the <value> nodes, and thus the current-node is the <value> node, whose child node <component> has the XML attribute name = ‘volume’ equal to our current driver DN.
This time we reuse the ParseDN token from the original rule of start of 0 and length of -2, on the path component string.
Now we have the value we used to get, but from our plural attribute instead. As I re-read this, I realize I could probably do this in a single XPATH statement instead of needing to loop through the values. Store the destination attribute DirXMl-ADContexts into a nodeset local variable, called say CONTEXTS and then this XPATH I think would work to get the initial value (that would then need to be ParseDN’ed)
Basically that means, get the attribute of interest, the value node whose <component> whose name attribute is volume and equal to our driver DN, then get that <value> nodes <component name=’path’>
Heck for fun you could technically replace the CONTEXTS local variable with an XPATH query command like:
query:readObject($srcQueryProcessor, association, @src-dn, @class-name, ‘DirXML-ADContexts’)
which would make it look more like:
query:readObject($srcQueryProcessor, association, @src-dn, @class-name, 'DirXML-ADContexts')/attr[@attr-name='DirXML-ADContexts']/value[component[@name='volume']="~dirxml.auto.driverdn~]/component[@name='path']
Hmm, type that ten times fast. Kind of elegant, but I think my loop approach while technically less efficient would be MUCH easier to read. I suppose if you had hundreds of AD drivers, the XPATH solution is the way to go, but for pretty much anything less than that, I would not worry about performance here.
setup for rename validation
This rule is basically the same as the previous rule and differs only in the ParseDN parameters, as it is trying to get the cn=geoffc part out of the attribute, so instead of start of 0 and length of -2 it uses start of -1, length of 1 (which since it is the default is usually not specified in the XML), which means start at the leaf most node, (cn=geoffc) and go one node long, thus selecting just the cn=geoffc part. The current-object-value gets the same value from the src-dn attribute.
The next rule move or rename validation fires twice, once for the <rename> event and if cached-object-value has a string value, and is equal to current-object value, then of course it was not a rename event. Then for the <move> event, if the same tests are true then it is not a move event. Thus one (or both in fact) will be vetoed as appropriate. Thus only one of the <move> or <rename> events gets through. In fact, if AD decides you modified the DN but there is no actual change, both events would get knocked out Uncle Vito. Cute approach? I love it when something this simple and elegant works! But no changes needed for our use case.
move or rename cache context update
If one of these events have happened, it is important to update DirXML-ADContexts with the new correct value, so we have to replace the simple set destination attribute with the same basic approach. Loop through the destination values of DirXML-ADContexts, find the one (or more) for this driver, remove those specifically, and then add in the current new value properly as our structured attribute.
Next up in the Publisher channel is a rule in the Create policy set in the policy object pub-cp (part of the NOVLADDCFG package).
There is a rule, add attributes for all objects, that adds the DirXML-ADContext attribute. Now we could probably just add the DirXML-ADContexts attribute and forget about it, but since there are a number of error cases where such a value might have been left behind, it is probably best to do the loop through the destination attribute DirXML-ADContexts, find the ones referencing this specific driver, and removing any found. An example where you might get into this error condition is if you removed the DirXML-Association for the user in the Identity vault and possibly deleted the object in Active Directory to test migrating them again, but forgot to clean up DirXML-ADAliasNames or DirXML-ADContexts (which I do all the time). This way you are certain to clean it up in the driver when you next run through this rule.
Thus use the same basic code I have been discussing for most of these rules, and we get to reuse it again. One nice thing is if you copy the rules in Designer’s Policy Builder view, you can paste them into a text editor (anything but Wordpad or Notepad please! Those are the worst editors ever!!! Get TextPad, NotePad++. UltraEdit, whatever. Or emacs, I hate vi. Emacs rules! Please no holy wars on editor choices, lets all agree to hate Notepad and Wordpad equally, and together!). Then when you need to re-use it, you can just copy the complete XML, and paste it into the appropriate place in Policy Builder. If Designer is giving you a hard time, just flip over to the XML Source page and find the right spot to paste it in there. If you have not noticed yet, the token names are very descriptive (if you speak English)
Next up we have a couple of rules left in the Publisher Channels Command Transform, and I will get to those in the next article in this series. As you can see, while it looks quite complex, really I am repeating the same basic logic time and again after having identified all the various places the attributes are referenced. Hope this is helpful to some of you!
Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment. It just worked for at least one person, and perhaps it will be useful for you too. Be sure to test in a non-production environment.