The different attribute options in Identity Manager:
op-attr, attr, src-attr, dest-attr.
One of the key differentiators between Novell Identity Manager and the other products is the use of DirXML Script as a language to manage and manipulate Identity events. DirXML Script offers a large number of conditional tests, actions, and tokens.
Conditionals are things used in a condition (IF test). Originally the only place you could use these was in the conditions of a rule, but with the release of Identity Manager 3.5 an IF action was added that allowed the use of an IF test inside the Action block of a rule. This simple addition made a world of difference and allowed for some really complex rules to be built. At a client we actually built such a deeply nested rule that we exposed a number of bugs in Designer which was unable to actually handle it. Of course we reported the bugs in the forums (http://forums.novell.com or nntp://forums.novell.com if you like using a news reader), in the novell.support.identity-manager.designer forum, and it was fixed many months ago.
One of the really nice things about the Designer team is that they are very proactive about following the forums and bug reports there. If you report a bug, someone usually will respond or send you an email that they filed a bug in bugzilla (http://bugzilla.novell.com) and often I find it fixed within a few days. Then you can download the latest nightly build and test to see if they really fixed it. This development cycle is very compelling if you use it.
Personally there have been a number of crippling interface bugs that only very complex rules exposed, and within two days of reporting them, they usually are resolved. It is tough to beat service like that!
Actions are things you can do, like set (or add. Set is for single valued attributes, or to make sure this is the only value. Add is for multi valued attributes, and adds a value to what is currently there) a value (in the source or destination). Like send an audit event, add something to the trace output, or send an email.
Any time you can provide a value, as a string, you get to Argument builder, which allows you to use tokens to develop and build strings. Tokens can be verbs or nouns. Nouns are tokens like Source Attribute, Destination Name, Time, etc. Verbs are tokens like substring, upper-case, Convert Time and many more. I have written about some of my favorites in other articles:
- Examples of using the ParseDN Token in Identity Manager
- The Query token in Identity Manager
- Mapping tables and Render browsed DN relative to policy option
- Using the Time Tokens in IDM 3.5
- Unique Name Token Functionality in IDM 3.5
There are many more than I ever would have time to discuss, and as you can see together these are pretty darn powerful!
Some of these tokens are really just nice interfaces wrapping a Java function call (Like Time and Convert Time) which you could manually configure to do exactly the same thing but no where as simply as the wrapper interface provides.
Thus in some of Novell’s competitors to Identity Manager, in principle you can do anything you can write a Java function to do (Sun Identity Manager for example) or a C# (C Sharp, in Microsoft’s competitor) but these are totally different worlds of complexity. For example look at any of the typical rules in even the simplest driver, and look at what would be required in Java or C# to do the same and it becomes pretty clear how compelling DirXML Script is as a feature.
One of the slightly confusing things about DirXML Script is that there are four different types of attributes you can use along the way.
- Operational Attribute
- Source Attribute
- Destination Attribute
Operational Attribute is the simplest. Identity Manager works by the engine catching events happening in eDirectory, (or a shim catching the event) generating an XDS document to represent the event, like:
<nds dtdversion="3.5" ndsversion="8.x"> <source> <product version="126.96.36.19980307 ">DirXML</product> <contact>Novell, Inc.</contact> </source> <input> <modify cached-time="20080611213152.664Z" class-name="User" event-id="200806112131512#0" qualified-src-dn="O=LAB\OU=EMPLOYEES\OU=NEW\CN=BSmith" src-dn="\ACME-LAB\LAB\EMPLOYEES\NEW\BSmith" src-entry-id="70312" timestamp="1213219912#14"> <modify-attr attr-name="company"> <add-value> <value timestamp="1213219912#14" type="string">ACME Fish Corporation</value> </add-value> </modify-attr> </modify> </input> </nds>
So in this sample document of a modify (note the <modify> node), we have only one operational attribute, company, from the line:
On a modify event, usually you only get the attribute that is changing. If the object is not associated, and it truly is just a modify that is all you will need.
But if you have a rule in your Create policy of the like, “Veto if operational attribute not available” then the event may run through the engine several times. For example, if you require Full Name and workforceID on a User before it is provisioned into Active Directory, then if the user is created by Console One, it basically only has the CN and the Surname populated (maybe the password) before the object is created.
That event will come through the driver, and Veto because the Create rule requires Full Name before you can create the User in Active Directory. (Of course the reason for the Create rule is that Active Directory requires Full Name as a mandatory attribute on a User object).
Then in Console One when Full Name, Given Name, and maybe other attributes are populated, (like company in the example above) the event will come through as a Modify event with just the one or two attributes changing.
Now, if this is a create, the user probably is not associated, so you will get a synthetic add event where the modify is converted to an add, and the engine will query for all the attributes in the filter and get them into the add event as operational attributes.
Having said all that, testing for an operational attribute is very powerful, but the problem is, it really only works well on events after the Event Transform, where the is going to be a synthetic add. You just cannot rely on it being there in the document otherwise.
Thus we have the next attribute type in our list, Source Attribute.
Source attribute always queries back to the source, for the value of the attribute, with the caveat that if a rule just recently did the query, it will return the value from the cache instead of doing another query. This is a very good thing as it is way more efficient and saves a lot of time, since Queries are some of the slowest operations in Identity Manager. It means talking to another system, sending a query document, running it through the rule sets, getting a response instance document back and running that through all the rules. Slow is of course relative, since eDirectory and the engine is pretty darn quick at doing this, but if you are processing thousands or hundred of thousands of events a millisecond here and a millisecond there can add up very quickly.
The caching is actually pretty darn neat, because it actually looks ahead a bit at the rule set, and on the first query event will try and get back a bunch of attributes that it knows you WILL be asking for in a moment or two. This way, in one query event you ask for the next four or five attributes you might need. The cost in terms of time is the query and the response documents. Thus accept you have to do a minimum of one query and leverage that to get as much as you can in advance. (I once asked one of the authors how this was determined, how it decided what to read ahead and query, and the answer was, patent pending technology. Oh well, I think super secret sauce would have been a funnier answer).
The problem with Source attribute is that it will pretty much always query (unless it is already in the cache), and this can get expensive. The problem with Operational Attribute is that you cannot always be sure it will in the document.
Thus we come too Attribute, which is a powerful combination of both Operational and Source attribute. If the attribute is in the operational document then it is used, but if it is not, then the engine queries to get it. (Again with the caveat that if its in the cache it will use that instead of querying).
Destination Attribute is pretty much the converse side of Source Attribute, where it looks at the Destination data store. Of course, it does not make sense to have an operational attribute in that case, so the other two version that we get for Source attributes are not needed.
Destination and Source Attribute come with a useful feature that the other two attribute types do not have, the ability to specify a Distinguished Name (DN) of the object that is the target.
The options are Current Object, which is the only thing Operational Attribute and Attribute can do, that is, the object that the subject of the event. The option Association allows you to specify the value of the Association to look for in the data store you are looking at. Finally you get to one of the most powerful options, DN. You can use all the tricks in Argument builder to generate the DN of the target object. This means you can use variables to store the DN, or put together pieces from one variable, a GCV, a string, or whatever it takes.
This way, you can get the value of an attribute from any object, in the source or destination data store, based on whatever criteria you need.
To make this more entertaining, it turns out you can replicate this functionality in XPATH.
Operational Attribute would be:
((add-attr|attr)[@attr-name = 'CN']) | (modify-attr[@attr-name = 'CN']/add-value))
This means look for the attribute CN as an add or modify event in the current event. You need to check for an add or modify, since it could really be either case, if you want the really generic case.
Source Attribute would be:
query:readObject($srcQueryProcessor, association, @src-dn, @class-name, 'CN')/attr/value
This uses the Java query class, that calls out to the srcQueryProcessor class to search the source data store for the for the attribute you care about, return an instance document, and then select the attribute with /attr/value.
Destination attribute would be:
query:readObject($destQueryProcessor, association, @dest-dn, @class-name, 'CN')/attr/value
Like the Source attribute example in XPATH, this calls out to the destQueryProcessor Java class to do the query into the destination data store and return an instance document, and then select the part you want by /attr/value.
To get the functionality of Attribute you would combine Operational Attribute and Source Attribute with an OR operator. Something like:
(((add-attr|attr)[@attr-name = 'CN']) | (modify-attr[@attr-name = 'CN']/add-value)) | query:readObject($srcQueryProcessor, association, @src-dn, @class-name, 'CN')/attr/value)
I have to thank Father Ramon for these examples, since I sure didn’t come up with them on my own.
This example in XPATH also reinforces the point I started this article with, that while you can do pretty much anything you need in a programming language like Java or C#, or in this case XPATH, it may be easier another way.