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 the third article in this series Managing multiple Active Directory domains in one IDM system – Part 3 I worked through a good chunk of the Publisher channel rules that need to changed for the DirXML-ADContexts attribute. Still need to do the same for the DirXML-ADAliasNames attribute.
In the fourth article in this series Managing multiple Active Directory domains in one IDM system – Part 4 I worked through the rest of the Publisher channel and started in on the plural DirXML-ADAliasNames that are needed, starting with the Output transform.
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.
NOVLADDCFG-itp-SubscriberUserAdd 1 rule
NOVLADDCFG-pub-etp-HandleMovesAndRenames 3 rules
Create Policy Set:
NOVLADDCFG-pub-cp 1 rule
NOVLADDCFG-pub-ctp 2 rules
NOVLADENTEX-sub-ctp-EntitlementsImpl 2 rules
NOVLADDCFG-sub-ctp-UserNameMap 1 rule.
Schema Map (done)
Create Policy Set:
NOVLADDCFG-sub-cp-Users, 1 rule
NOVLADDCFG-sub-cp-Groups 1 rule
NOVLADENTEX-sub-ctp-EntitlementsImpl 2 or more rules)
NOVLADDCFG-pub-ctp-UserNameMap 2 rules
NOVLADDCFG-pub-ctp 2 rules
New rules needed:
itp-Convert Plural Attribute
otp-Convert Plural Attribute
Now on to the Input transform, which has a minor twist that is some what important.
You would think that the Input Transform rule, to convert the simple string attribute coming from Active Directory as User Principle Name to a structured attribute would be the simple converse of the Output transform rule discussed in the previous article. But like most things in life, the devil is in the details.
First off, what should the nameSpace component be? That is a 32 bit integer field, and we are using it to store the time of the event, so I guess we should just decide to use the time in CTIME for the moment the event comes through. Of course, it might be delayed, so should we use the cached time? (Though I am not sure if Active Directory events will have this information, its an interesting idea, hmm, will have to think about that one. I know eDirectory events will come with a cached-time attribute sometimes, wonder if we get it the other way?). Probably the simplest way is to just use NOW as the time.
The path component is the simplest, its the current value of course.
The volume component looks easy, its the current driver DN, or so you would think. If you try it, you will see that the progression into the Event transform will remove it, since the Association value for the driver object is nonexistent. I suppose there are better ways to resolve this, and I am open to them, but I chose the simplest approach. I just set a nonsense association for the driver, ON the driver object. That is, I added by hand, a DirXML-Association value on the driver, with the state of 1 (associated), the DN of the driver itself, and the association value of 1234678 which was as arbitrary as I could come up with at the time. Then I added a GCV to the driver, holding that value I entered by hand. (Did you notice that DirXML-Associations use Path syntax as well? Thus you see a nice analogy of for the plural attributes as well).
Thus the following reformat operational attribute works:
<do-reformat-op-attr name="userPrincipalName"> <arg-value type="structured"> <arg-component name="nameSpace"> <token-time format="!CTIME" tz="UTC"/> </arg-component> <arg-component name="volume"> <token-global-variable name="dirxml.auto.driverdn"/> </arg-component> <arg-component name="path"> <token-local-variable name="current-value"/> </arg-component> </arg-value> </do-reformat-op-attr>
So long as you set an association-ref XML attribute onto the document, for the DN component, which you can do with the set XML attribute token. Oh I guess I could clone by XPATH as well, but since this is an XML attribute I want to add, and there is a built in token, I should use it.
<do-set-xml-attr expression="modify-attr[@attr-name='userPrincipalName']//value/component[@name='volume']" name="association-ref"> <arg-string> <token-global-variable name="driverAssocValue"/> </arg-string> </do-set-xml-attr>
Here you can see the XPATH needed is to identify WHERE to inject this attribute is:
That is, in the <modify-attr attr-name=’userPrincipalName’> node, find any child values whose <component name=’volume’> nodes exist and add it there.
What you should notice is that this only works on modify events. I could not come up with a simple XPATH to handle all three possible cases. The three cases would be a modify, add, or response to a query event. So instead, I just added three set XML attribute actions, since only one will ever succeed.
The other two XPATH examples would be:
Instance doc as a query response:
This is part of the magic of the reformat operational attribute, which is smart enough to know how to handle all three of these cases, with just one token. Alas, I do not know how to use the reformat operational attribute to add the needed XML attribute at the same time. Again, if you happen to know how, please comment and let me know!
Now I see two issues with this. In the first case, the Query response is lightly problematic, since you will set the nameSpace component to the current time, whereas the value in eDirectory will always have a value that differs, almost by definition. This means if you ever try to compare the two values they will never meet equality, even if the path value strings are the same. However, this so far does not really matter. But it is worth remembering in case you let the driver merge these two attributes. To my mind, the worst case is that the time will be updated to the current time from whatever value it had in the past, which is something I can live with.
The second thought was that it might make more sense to do this in the Event transform, at which point there is no need for the work around of adding the association-ref value. However, this is a simple enough solution. I am not sure if there is a real downside to adding an association value (nonsense that it may be) to the driver object itself, but that is a back of the mind concern I have with this approach.
Thus we have the reformat operational attribute, and then the three Set XML attribute calls in this rule.
Since we are looking at events coming in, via the Input Transform, lets continue with the Publisher channel. There are two main rules that need changes both in the Publisher Command Transform rule. The first is the pub-ctp-UserNameMap rule, that is part of the NOVLADDCFG package.
There are actually a pair of Username map rules, one in the Publisher channel and one in the Subscriber channel. These exist to manage the mapping of eDirectory’s naming attributes to the possible options in Active Directory. As a quick refresher, Active Directory has a number of naming like attributes. They differ from eDirectory, where almost any attribute could be a naming attribute. (It requires a flag in schema for the object class, that this attribute COULD be a naming attribute, and there can be many possible naming attributes in a single object class).
There is sAMAccountName, which is the old NT style NetBIOS name that needs to be unique across the entire domain, regardless of any structure you build inside the domain. Also called the Pre-Windows200 Login name in the MMC view.
Almost always, the User Principle Name is based on the sAMAccountName followed by @domain.com. It technically will accept any value, as there is no back end validation in Active Directory to watch out for this. However, it is best to be correct with proper values. However it could also be your email address, which it looks like, but it does not have to be a valid email address. This needs to be globally unique across the forest (that is conglomeration of trees). On that side note, is it me, or does an Active Directory tree really represent an O in eDirectory, and a forest more closely represent the eDirectory tree root?
To me it seems like something of a semantic distinction. Sort of Orwellian in that you know people did not like having many trees in an enterprise, therefore you say, well now you have a single forest made up of many trees, so there is no issue of many trees, since they are all part of one forest. But I digress…
Then there is the CN of the object. That is, when you consider the full distinguished name of the object in Active Directory, the entire DN needs to be unique, but here you can have duplicate end node values (cn=geoffc in two containers if you like) so long as the entire DN is unique. I.e. No duplication within the same container. This is much like eDirectory’s naming model where your naming attribute (whatever it happens to be for this object) must not duplicate another object in the same container’s naming attribute. (The first time you see object in DSBrowse using uid (uniqueID) as a naming attribute is when you realize how weird it looks)).
Finally there is displayName, which is what actually shows up in the Active Directory Users and Computers (ADUC) MMC console. Many people will rearrange that to be Last Name, First Name, because it sorts much nicer that way, since it would then sort by last name.
The default Active Directory configuration maps displayName to Full Name in eDirectory. Usually the CN= component is named based on the displayName value, but that is an MMC shortcut doing it for you, since you can actually use whatever you like if you create it low level enough.
The driver supports a number of the naming models here in this Publisher Command Transform rule. The Full Name mapping approach is controlled by a GCV and if selected, the DN of the user to be created in Active Directory will be cn=Full Name Value followed by the rest of the DN. If you change the Full Name attribute in eDirectory, then this is a rename event in Active Directory. Otherwise it uses the eDirectory naming attribute (usually CN for Users, but by no means guaranteed, and since it uses the Source Name token it will use whatever eDirectory is using as a value).
This UserNameMap policy object is dedicated to enforcing the naming decisions you have made via GCV. Additionally it enforces how User Principle Name is managed, when it is mapped to the Active Directory email address attribute, (UpnMap set to ad-mail-auth). The Subscriber channel version of this also has similar mappings.
Here we need to handle two of the possible cases.
map e-mail address to Active Directory logon name
unmap e-mail address from Active Directory logon name
These are the cases where UpnMap GCV is set to ad-mail-auth and the Active Directory email is changing. So we need to use the usual loop through the destination attribute DirXML-ADAliasNames, make sure to find any reference to our driver, and remove that one. Then add the correct value based on the changing email address. Then send it back to Active Directory, to the source, remembering that we need to send it as a structured attribute since out Output Transform will strip it back down to a single value.
Then in the unmap email address rule, we basically need to just remove it, since that is handling the case where the email address is just being removed. Use the same approach to handle the destination attribute value, by looping through the values to find the one for this driver, and then remove just that one (or more values). Again as in the previous rule we send a remove source attribute as a structured attribute with all three components so the Output Transform can strip it down as it goes into Active Directory.
Now as it happens, I have never actually used the ad-mail-auth setting for User Principle Name, so I never really paid much attention to these rules, but as I worked through these for this series of articles I started to wonder if the way this policy is laid out would even work properly. So in the defaults before we change it for this project, the two rules are basically the same and adding/removing the email address (Internet EMail Address in eDirectory name space). as the value of the old DirXML-ADAliasName attribute.
The first rule uses the Set token, which issues a remove all values first, then adds a value in one operation. That is fired when the operational attribute Internet EMail Address is available. That means there is an <add-value> or <add-attr> node for this attribute in the event document.
However the second case is if operation attribute Internet EMail Address is changing from the regular expression .+ which means any values. Usually this means it is being removed. This then sends a remove attribute both to the source and destination.
If you had a modify, you might get the remove value for the old value, and an add value for the new value. In that case both the rules would fire, wouldn’t they? Then you get two remove values, well one explicit remove value and a remove all values. Though I guess as I think about it, since this is in the Publisher Channel you do not get the nice removed values and add values that you would get out of an event in eDirectory. That is, eDirectory will forward both pieces on a modify, but the Active Directory shim only shows you the new removed value by itself (going to blank or null in Active Directory) or in the case of a modify the new value being added. So this is probably ok in general, even if it looks a bit off.
One more policy object in the Publisher channel and we will get to that in the next article, then on the Subscriber channel and we can wrap this one up.
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.