Trying to understand the Managed System Gateway driver in IDM 4 - Part 2


In Identity Manager 4.0 Novell has introduced a number of new features. There are four new driver configurations, two for applications ( and Sharepoint) and two for IDM itself to use, the Managed System Gateway driver and the Data Collection Service driver.

The Managed System Gateway driver is primarily used by the Reporting module to get information about users out of IDM and into the Reporting database. This is somewhat analogous to how the Identity Audit extension policies that were added to drivers are used to get Identity information into the Sentinel database.

As with many things in IDM 4, this is totally new stuff, and will take some time to get used too. You can read more about the changes between the various IDM versions in these articles:

One of the main new features is Packages, which is critical for all this working, as there are packages that add support for the reporting module to each of the many driver configurations. In fact the same approach is used for the Identity audit extensions as well. This is different than in the past, where the policies were stored in Libraries, centrally and linked into each driver as needed. Now with packages the content is actually duplicated in many places, but with Packages, upgrades are made easier than the previous model. I have been working on a series on Packages in Designer 4, that you can use to gain some insight:

The Managed System Gateway (MSG) driver is one interesting critter. It is doing all sorts of funky and interesting things that it is worth discussing the low level functionality. After all, if you do not know what it is supposed to be doing, how would you know what it is not doing, when it is not working. Most connected system drivers are pretty traditional, that is an event comes out of the application of eDirectory, as an XDS document (which is what the shims job is, convert the applications event into XDS and convert XDS into things the application understands) which is then processed in the flow.

There was the ID Provider driver from Novell that basically allows you to get ID's that are unique and next in sequence. There was the State Machine driver in the Compliance Management Platform for handling the lifecycle of users. I have not really looked at the Sentinel driver, but I imagine it is doing something somewhere in between. Now we have a couple more that are not doing traditional synchronization tasks.

  • In the first article Trying to understand the Managed System Gateway driver in IDM 4 - Part 1 of this series I started looking at how it builds up a cache of various interesting things. It stores them as driver scoped local variables. That means they are available while the driver is running. On every restart they need to be recalculated. There is the SERVER_INTERFACE, and DRIVER_DN variables that we talked about. These are in the Input Transform, in a series of policy objects.

Next the driver does something that astonished the heck out of me! They go on to build a Rule Cache, stored as MANAGED_SYSTEM_MATCHING. But they do it by reading the Matching and Create rule, and infer what objects are being managed this way! I found this one so astonishing, I managed to track down one of the authors. The notion is that they would like, in Reporting, to be able to understand the matching criteria used in the driver, so that they could try, via the Data Collection Service (DCS) driver (next on my list to dissect like this, by the way) to generate a report on unmatched objects and possibly speculate on why it did not match. To do that they need to know what the matching criteria do. In this case, rather than make the Admin repeat the match logic in a GCV or some such, they decided to make an attempt to infer from the policy objects themselves, reading back the DirXML Script and see if it was doable. This will work fine for the shipping Packages from Novell, and is just one of those things you need to consider now, when building a matching policy. Things like, if class name is not equal to User or some such kind of matching rule logic, will not be properly inferred, and just be more straightforward about it. The additional detail is that rather than code this in the driver shim itself, they decided to implement it in Policy, which is good, as it is a really ambitious rule and everyone can learn from it, but if they realize they have a mistake, we can fix it ourselves (dirtying the package of course) but since it is part of a Package, distributing an update that is easy to apply will be quite easy and realistic. Whereas in the past this would have been a pain to make sure everyone had the latest code, even if they wanted it.

Let's dissect some of how this works, since it is quite so interesting, to IDM Policy voyeurs like me.

First it reads back information about the drivers. It does this by grabbing all the MSysInfo Global Configuration Variable (GCV) objects, and looping through them. Thus once per supported driver. Grabs this drivers linkage (The Managed System Gateways, I realized I read this wrong the first time. I thought it was getting the linkage for each driver it found, but in fact it is getting the MSG drivers linkage) into a variable, gets the Schema Map objects DN out of the linkage, with a cute XPATH of:


The variable linkage holds the DirXML-Policies attribute node from this driver, and is of syntax Typed Name, which has three components, dn, level and interval. Novell uses this to indicate the Policy linkage. They used Typed Name as it holds two integers and a DN attribute. The DN attribute is the policy object reference, and the interval value indicates which of the many policy objects you see in the fishbone diagram it is referring too. They chose a numbering scheme that is mostly immaterial for us, other than to note that the Schema Map rule is value 0. The Input Transform is 1, and output transform is 2, and then it works through the rest of the policy set options. Then the component named level is used to indicate the ordering within the policy set. Thus you could have 12 policy objects in the Input transform, all would have interval equals one, but they would all have different level values to indicate how you ordered them via Designer or iManager. This is the linkage change that was done for IDM 3.5 to allow for Library objects. Now an object in a library is just a DN reference, and can have a interval (policy set identifier) and level (ordering within the policy set) that shows where it should be executed. In IDM 3.0 and before, there were discrete attributes, named things like DirXML-EventTransformationRule, and DirXML-MatchingRule on the DirXML-Publisher and DirXML-Subscriber object classes. This was a single valued attribute, and then to link in additional policies. there was the DirXML-NextTransformation on the DirXML-Rule object. The new policy linkage model is much more flexible.

Anyway, the XPATH looks at the redacted nodeset below (I removed all the other value nodes to make it simpler) that is stored in the variable, linkage.

<nds dtdversion="3.5" ndsversion="8.x">
<product version="4.0.0">DirXML</product>
<contact>Novell, Inc.</contact>
<instance class-name="DirXML-Driver" event-id="0" qualified-src-dn="O=system\CN=driverset1\CN=Managed System Gateway Driver" src-dn="\IDM4-IDV-01\system\driverset1\Managed System Gateway Driver" src-entry-id="33288">
<attr attr-name="DirXML-Policies"> <value timestamp="1287424832#1029" type="structured">
<component name="dn">\IDM4-IDV-01\system\driverset1\Managed System Gateway Driver\NOVLIDMMSGWB-smp</component>
<component name="level">0</component>
<component name="interval">0</component>
<status event-id="0" level="success"></status>

Thus $linkage, whose component, whose name is interval, and has a XML text value of 0 ($linkage[component[@name='interval']/text()='0'] ) then at that node level, look for the text value of the component whose name is DN and return that value (/component[@name='dn']/text() )

This way you get the Schema Map DN. Now it turns out in this case, the driver has two schema maps, and this rule only gets the first one. I am not sure if that is an oversight or by design, but the policy is halfway there to get both (or all), but is not one hundred percent I will follow up with someone at Novell to track this one down. (I need to find someone who truly understands what this driver is doing and why).

Then it loops through the found drivers that support the MSG driver (Those that have the MSysInfo GCV object) and looks at the driver filters. It tests to see if they are syncing User objects on each channel, but using XPATH against the driver filter XML. Then for each channel if the User class is set to sync in the filter, it reads back that channels Matching Rule, and this time it does it right and loops through all possible Matching rules on that channel, by looping through the nodeset given by the XPATH:


This looks at the local variable driver, which was loaded a step ago with the Policy linkage, filter, and GUID for this driver, for the <attr> node whose attr-name is DirXML-Policies (since there are three different attributes in the returned nodeset), and then finding the value (or values, since this is a nodeset selection, if more than one match the XPATH, all matching node sets will be returned) for whom the interval is 6, which is the Subscriber Matching rule value. Note there is no predicate for level equals anything, so it will select all that are there, thus if there are three rules, three DN's will be returned.

Then they load in the Policy data, in XML format, base 64 decoded to read it as XML of course, and the XML Parsed. They could have just used the Document() token as I discuss in this article: Parse DN Custom DN Delimiter Example but this is a six of one, half dozen of the other type situation.

Then the loop through each node in the Matching rules, and use the following two very interest XPATH examples to detect what is being matched:

There are two cases too look out for, directly mentioned classes, and indirectly handled classes.

The directly handled classes uses this XPATH:

count($current-node/conditions/node()/if-class-name[@op='equal'][@mode='case' or @mode='nocase'][es:lowerString(text())='user'])   count($current-node/conditions/node()/if-class-name[@op='equal'][@mode='regex'][es:match('User', text())]))>0

So what is that doing? By using count() and testing if the result is greater than 0, it is an easy way to bundle a whole bunch of tests together via predicates. So what is inside the count() function? Well there turn out to be two count functions, I hope by breaking it up further it gets more easily readable.

count($current-node/conditions/node()/if-class-name[@op='equal'][@mode='case' or @mode='nocase'][es:lowerString(text())='user']) 
count($current-node/conditions/node()/if-class-name[@op='equal'][@mode='regex'][es:match('User', text())])

The first looks at the condition blocks, for tokens, with the op='equal' and it is not regex (the mode = case and nocase part, since the alternative is probably a Regex compare of mode='match') then use an ECMA function from the Advanced Java Class ECMA library to lower case the text() value and compare it user. This is needed as XPATH equality tests are case sensitive. Prior to using the AJC ECMA functions, you would have to use the XPATH translate() command with the alphabet in uppers, then lowers, and that is really wordy.

So the first will select any condition blocks in the rule that have a class-name="User" test and return a count of how many such nodes there were. The second part will try and catch the regular expression based compare, where you might have User|Group in your Matching rule. That is, you can do a if class name test, and instead of testing for one class at a time, if you change the type of compare from case insensitive to regular expression, then it will do a regex compare. I often use this in the case of if operation match regex add|modify|delete|rename|sync or the like.

This too will return an integer with the number of matched nodes. Finally, if the sum of the two is greater than 0, then we have inferred that this driver is matching for User classes.

The Indirect case, looks for the case where there is no equal or regex compare.

count($current-node/conditions/node()/if-class-name[@op='equal'][@mode='case' or @mode='nocase' or @mode='regex'])=0"

In both those cases it stores store true or false in the various variables used.

Next the rule tests to see if we have a find matching action with this XPATH:


Same basic notion, count the number of nodes, under <actions> and then any instance (//) of the <do-find-matching-object> token, whose <arg-match-attr> is there. This confirms that we have a rule doing attribute based matching somewhere in this policy, and returns true or false.

This is a good stopping point, stayed tuned for part 3.


How To-Best Practice
Comment List
  • As part of some troubleshooting, I've recently gone through the trace of a MSG driver for a customer. During the startup, I couldn't see any sign of the create rules being read (as you mention in this post). Definitely the matching rules for both sub and pub are read and processed including any rules that are in a disabled state (which looks like a bug to me).

    By my understanding creation rules would be interval 8 and 9. There's nothing in the policy or trace that I can see which indicates these are read. Have I missed something?