Example of using XPATH in Identity Manager:
Novell Identity Manager originally started as Novell DirXML and required all work to be done in XSLT (XML Style sheets). XSLT is powerful language but not my personal favorite to work in.
With the release of Novell NSure Identity Manager 2.0 we saw the advent of DirXML Script an XML based language designed for the task of managing XML event documents. With each release of Identity Manager since, it has gotten better and better.
Just for the heck of it, I even wrote this article trying to track down what you can only do in XSLT at the moment, with the goal of chipping away at that list, where possible!
There have been new features that make life a lot easier, and new tokens that are very powerful.
The nicest thing about using DirXML Script is that the management tools, iManager with the Identity Manager snapins, or Designer for Identity Manager (an Eclipse based tool for offline editing of a project) parse the XML into a really nice GUI interface that allows you to type it free form in XML, manipulate it in a GUI, or any combination of both. In fact, sometimes, due to the way nested items (if then code blocks, or for each loops) are shown in the GUI it is easier to fix things by switching over to the XML view and working there.
Some examples of the various tokens and things that can be done with DirXML Script are:
One of the languages that has been available inside XSLT and DirXML Script is called XPATH, the XML Path language, which is described here: http://www.w3.org/TR/1999/REC-xpath-19991116
However there is just not enough out there in terms of how to use XPATH in an Identity Manager context for people learning Identity Manager.
I have been working hard on that topic, and you can read some of my articles on the topic at:
XPATH General Concepts:
XPATH Cool tips:
I keep my eyes open as I work in Identity Manager for good examples of XPATH usage that might be handy to others, and this one happened to me today. I walked one of my coworkers through it, who is still learning XPATH, and realized it would be a great example to write an article about the process of debugging what I wanted to do.
For those who do not know, Designer has an XPATH tool built in. It is not perfect, we are told in the forums that there is one or two major issues that make it not 100% complaint with the way Identity Manager views XPATH, but for 99% of the things you need to do in XPATH in Identity Manager it should be fine.
Whenever you use an XPATH related token (strip by XPATH expression, if XPATH expression condition token, clone by XPATH expression, or the XPATH token in Argument Builder) you get a little icon to the right of the text box, that pops open the XPATH tool.
I will try and include some screen shots to make it clear what I mean, where it makes sense.
So what problem was I working on? Well we are syncing POSIX attributes (that is uidNumber, gidNumber, gecos, homeDirectory, loginShell and so on) between two trees. However, the posixAccount auxiliary class that often is used to contain the POSIX attributes that Unix and Linux need to define a user, has some mandatory values.
On a side note, it is a really bad idea in general to make an Auxiliary class have mandatory attributes. It makes it a ROYAL pain to work with! You cannot just add the class to an object by editing say Object Class, in Console One, since you need to save that change, before the UI will let you add one of the new attributes, but if the new attribute is mandatory, you cannot add the Object Class value without the mandatory attribute!
I do not dispute the logic behind this specific case, since it makes little sense to have just uidNumber without gidNumber, from a Unix server perspective, nonetheless it is really annoying.
Now in this particular tree, somehow the base class User got extended with the needed posixAccount attributes. Thus when we originally set this up and populated the tree, all was good, as we could add the POSIX attributes without problem to users in either tree. It was just part of base schema, no need for a posixAccount attribute.
Then things got strange. We found that some LDAP applications, I think it was AIX's equivalent to PAM on Linux, (Pluggable Authentication Modules, which I was sure AIX called LAM, but the AIX guy says he has never heard of that, not that it matters) when doing an LDAP bind to get user information we found that NMAS was throwing a strange failure error, and it looks like you explicitly require the posixAccount object class on the user for it to work. It is not enough to just have all the needed attribute, even though the query does not look for posixAccount. But if the object class does not include posixAccount it does not work. Crazy, but easy to fix.
Thus to fix it, we started adding posixAccount to users. However, we had a couple of edge cases where we should not have been sending it and I wanted to strip out the add object class for posixAccount. Usually when we are missing one of the POSIX attributes, in which case the entire event fails with a 609 Missing Mandatory error. (Because we are missing a mandatory attribute, that posixAccount requires)
Well you say, thats easy, that is what the token, strip operational attribute is for. Just do a strip operational attribute Object Class, and all will be fine.
Well there are way more instances where this might occur, and in fact there are legal cases where there might be several object class changes in one document, so what I really want is just to strip the specific object class add value of posixAccount.
Well thats what strip by XPATH expression is for. So what is my XPATH expression to remove the add of the value posixAccount into the Object Class attribute.
Off the top of my head, I tried the following XPATH statement:
modify-attr/add-attr[@attr-name="Object Class' and value/text()="posixAccount]
I opened it in the XPATH editor, (here is what it looks like empty)
<nds dtdversion="3.5" ndsversion="8.x">
<modify cached-time="20091029133625.703Z" class-name="User" dest-dn="corp\acme\americas\Test Users\LDAPTEST" dest-entry-id="37551" event-id="AMERICAS-AD##124a0832994##0" qualified-src-dn="O=acme\OU=Users\CN=LDAPTEST" src-dn="\acme-IDV\acme\Users\LDAPTEST" src-entry-id="38906"
<value timestamp="1256823385#2" type="string">LDAPTEST@acme.corp</value>
<modify-attr attr-name="Object Class">
Before we start using the XPATH editor for real, lets make sure we can get it to work at all! So lets try a simple common XPATH selection. Lets select the src-dn XML attribute of the <modify> node. With XPATH, you can do a couple of very different things, which sometimes gets confusing, and the different uses depend on the context of tier use, which makes it more confusing.
Basically you can use XPATH to select a node, value, or attribute. That is the sort of thing you do in a set local variable kind of context. Makes sense, you want to set a variable to something in the event document.
Conversely you also can use XPATH to do math, and some string functions, in which case, you might also in a set local variable context try to add 86400 seconds to a Time value, to set the value to tomorrows time. erPrincipalName"] but wanted the value before the @ sign. Well you could combine the two into something like substring-before( attr[@attr-name="userPrincipalName"], "@") to get what you wanted.
Back to our example, lets make sure we can get the XPATH editor working with a simple test or two, starting with our -dn, which KNOW will work, since it is the most common example used in Identity Manager.
Ok, so I have my event doc on the left hand side, looks good, type in -dn as my expression, hit the arrow button to Go, and no nodes are found. What the dickens?
Well this stymied me for the longest time, and I just assumed this was broken, but it is really the simplest thing to resolve. The XPATH editor is a very generic XPATH editor. Identity Manager is a specific XPATH usage case, and it all comes down to the context node!
Here you can see I switched over to the XML Tree view on the left has side. The most important thing is I clicked on the Modify node. This sets the current context to the modify node (Which the XPATH Select Context bit on the right says is now /nds/input/modify) which is the default context in an Identity Manager example. Now suddenly we see a result! Once you do this, it starts being a really useful tool!
Back to my actual example now, and I had thought that this ought to be close:
modify-attr/add-attr[@attr-name="Object Class' and value/text()="posixAccount]
Well first thing the editor complained about where my typos. Miss matched the " and ' around the Object Class, and missed a close " at the end of posixAccount.
That left me with:
modify-attr/add-attr[@attr-name="Object Class" and value/text()="posixAccount"]
I switched the left hand pane to the tree node view of the sample XML event document and start looking at the actual document, and I realized my memory stinks!
First off, I got an <add> and <modify> event mixed up. In an <add> event, you get add-attr nodes, with an attr-name attribute, and then an add-value node and then a value node, or something like that. But in a modify, you get a modify-attr node, with an XML attribute of attr-name and then an add-value or remove-value (or remove-all-values) node under that, followed by a value node.
Thus no need for the add-attr, and the predicate (the stuff in square brackets ) needs to be on the modify-attr node.
That gets me closer with:
modify-attr[@attr-name="Object Class" and value/text()="posixAccount"]
But I get nothing the XPATH Editor, since nothing matches that criteria, and as I looked closer I realized I forgot that there is an add-value node to include in there. That leads me closer with:
But there is an error at the end I am told. Oops, left a trailing ] and then I take that off and still an error.
Well I think I need to put a predicate on the add-value test, so that it looks more like:
So lets parse that out. Select the modify-attr node that matches the condition where the XML attribute attr-name is equal to the string "Object Class" and then under that node, lets select a add-value node, who has a value whose text string is equal to "posixAccount".
Now you can see the in the XPATH editor what it should look like:
I switched tabs over to the XML Source view, since in this case it is more useful when looking at results. Then you can see on the right hand side the XPATH Selected Context is still /nds/input/modify, which is what we want, and the XPATH expression is what I typed above, and in the results section, it selected an element, lines 16-18.
Look over the to the left hand side, and you can see that lines 16-18 is the <add-value> node to the close version of </add-value>. In this case I selected a node set, and it since what I originally wanted was to strip this out by XPATH, that looks to be what I wanted. This way if there is more than one Object class change, I will only remove this one node, and it is the only one, it leaves an empty modify-attr node, which usually gets cleaned up by the engine.
Tada. See was that so hard? Well yes, a little bit, but it gets a lot easier as you do it more often, and get better at it.