Watching Group Membership Changes coming from the AD driver

0 Likes
Group membership change coming from AD:

Publisher channel

Novell Identity Manager at its core, works by taking an event, converting it to an XDS document (an XML dialect defined by Novell), and sending it through the engine for processing by the policies and rules. There are two channels, Publisher, where events originate in the connected systems, and the Subscriber channel where events originating in eDirectory are processed.

Each channel has a set of predefined points where policy objects (which can be DirXML Script rules, or XSLT style sheets) are linked in, and applied to the document at hand. I was going to say the input document, but in fact, the output document (the response, after the input document has been processed and handed off) also runs through some of the rules as well.

In Novell's second interface to manage Identity Manager, iManager with the Identity Manager plugins, (the first was a Console One snapin for DirXML 1.x), the flow is portrayed as the 'fishbone' diagram, with the eDirectory instance at the left, and the connected system on the right. For me personally this is not helpful, as it turns out I am a bit right left dyslexic and can never keep directions straight like that. Designer for Identity Manager, the third (and my personal favorite) management interface for Identity Manager uses a more useful paradigm, (at least for me) of the eDirectory vault at the bottom, and the connected system (the Application) at the top.

This second approach is much easier for me to visualize. The Publisher channel is for inbound events to the Vault, coming 'down' the channel. Whereas the Subscriber channel is sending events up to the Application. When you think about the eDirectory driver, which is somewhat surprisingly one of the harder drivers to understand, it is easier to realize that all events are coming down the channel, inbound, as I like to think of it, and it just depends what eDirectory instance is at the bottom. This leads to the strange circumstance where if you are learning Novell Identity Manager it is easiest to start with the Active Directory driver, not an eDirectory driver.

Along the flow of the event through the fishbone diagram, there are some points at which rules are linked. In order to right meaningful policies to process the events the first thing you need to do is generate one of the events you care about, look at it, understand what is happening, and then you can try and apply policy to it.

The best example I can think of is discussed in the article (http://www.novell.com/communities/node/1858/more-about-veto-command-scoping-events) where I talk about scoping an Active Directory driver to block delete events. In that case, I had previously in another article (http://www.novell.com/communities/node/2052/avoiding-startup-vetos-scoping-rules) discussed being careful with the Veto action, because if you Veto too carelessly you can veto the driver startup documents, and the driver will not be able to start. (The drivers handshake and send several documents back and forth between the engine and the shim, at startup time.)

In that example, of a delete from the Active Directory driver, on the Publisher channel, the XDS document that the Active Directory driver shim generates to send to the engine, includes the operation, delete, but does not include an object class. Thus being an exception to my advice in the second article to always scope events by object class, or something else.

Another category of events that can be tricky, depending on the connected system is how Groups and their membership are handled. eDirectory has some pretty cool features in how Groups are handled, that are quite useful. In eDirectory, a User being made a member of a Group requires four attributes to be updated. Two on the user, and two on the group. The User gets Group Membership populated with the distinguished name (DN) of the group object, and it gets the Security Equals attribute set with the same DN. The Group object gets a value added to its member list attribute, Member, with the DN of the User object being added, and the Equivalent To Me attribute gets the same DN value set.

It turns out that there is really nothing in eDirectory itself that maintains these four attributes, rather it is up to the tools, and NWAdmin, Console One, iManager, and pretty much all proper third party tools do all the work behind the scenes for you.

But it does not have to be that way. Any object can be Security Equal To any other object in eDirectory, (I think. Can anyone think of an exception? It would be some quirk of schema I imagine, and you could just add an Auxiliary class that included Security Equals attribute to get around it, if you needed too.). You can be a Member of a Group, but not be Security Equal To. Which actually has real implications. If group objects are being used to confer rights to eDirectory or the NSS on OES filesystem (Can't call it Netware anymore, it could be NSS on OES Linux) then if you only have the Group Membership attribute on the user populated with the Group objects DN, you will not actually inherit the rights or trustees.

Identity Manager recognizes these as two pairs of reciprocal attributes, and if you set one half of a pair, it will try and set the other half for you automatically. In fact you will see a line in DSTrace saying that it is doing that for you. With the coming release of Identity Manager 3.6 this summaries, you will be able to pick any two attributes (they should make sense of course) and declare them to be reciprocal attributes and then if you set only one, Identity Manager will do the fancy footwork in the background to set the other half.

For group membership, you still need to set two halves at least, and let the engine fix the other halves for you. I.e. Group Membership/Member and Security Equals/Equivalent To Me and independent pairs of reciprocal attributes.

Now having looked at how it should be done, lets see another approach, how Active Directory does it. In actual fact, with the advent of fast enough query capabilities some of the benefits of the second half of the attribute pair starts to go away.

In Active Directory, Group Membership is maintained by a single attribute "member", stored on the Group object. Thus the Group has the list of its membership. In the MMC (Microsoft Management Console) for Active Directory Users and Computers, when you click on a User and select the Member Of tab, it actually does a query (I think against the Global Catalog, but I am not sure) for all groups that contain your DN in their member list.

The major consequence of this in regards to Identity Management is what a group membership change would look like, and how you can react to it in Policy to handle it.

This trace comes from a test system I was using at a client, with the names obscured to protect the innocent. For a variety of reasons I was looking at the contents of the Domain Admins group in Active Directory.

I made the change of adding a single user, Lateefah Smith (LSmith3 in eDirectory) using the Active Directory Users and Computer MMC tool, and when the next polling cycle came around, I saw this event as the start of the event on the Publisher channel. This is the document the driver shim sent to the Publisher channel of the engine.

<nds dtdversion="2.2">
<source>
<product version="3.5.11.20080307 ">DirXML</product>
<contact>Novell, Inc.</contact>
</source>
<input>
<modify class-name="group" event-id="0" src-dn="CN=Domain Admins,CN=Users,DC=Test,DC=domain">
<association>f0dc778ec5ff9441b3c3474358f89993</association>
<modify-attr attr-name="member">
<remove-all-values/>
<add-value>
<value association-ref="527eb9cd965a8e4bbfebc0c4cd3c3e73" naming="false" type="dn">CN=Lateefah Smith,OU=Fac,OU=19TH,DC=Test,DC=domain</value>
<value association-ref="694ddd53961ff844b039be979189de4f" naming="false" type="dn">CN=Alonzo Duncan,OU=CustSvc,OU=NY,DC=Test,DC=domain</value>
<value association-ref="664a7fdec9a1da4aa7538cdd23bc431b" naming="false" type="dn">CN=Jeanie Jones,OU=CustSvc,OU=NY,DC=Test,DC=domain</value>
<value association-ref="d2cfd892b8b02d4fb6eed27438d3991f" naming="false" type="dn">CN=Armando Corona,OU=CustSvc,OU=NY,DC=Test,DC=domain</value>
<value association-ref="7190689305255e4fa6d557e762e9f921" naming="false" type="dn">CN=idmUser,CN=Users,DC=Test,DC=domain</value>
<value association-ref="88feb6a1c5e64b46aee994f79919843b" naming="false" type="dn">CN=Administrator,CN=Users,DC=Test,DC=domain</value>
</add-value>
</modify-attr>
</modify>
</input>
</nds>



This is an input document with a modify operation, with two types of things happening, a remove-all-values, then a multi valued add of the member list.

It is important to note that first the shim translates what I did in the MMC snapin to a Remove all values and then it adds back in all the current members. This as you can imagine has the potential to be horrible from a performance perspective on large groups. I am not sure of the exact underlying mechanism, whether it is Active Directory doing this in the background whenever you modify a multi valued attribute or if it is just how the shim is forced to interpret it via the API's in use. With an Active Directory forest in 2003 functional mode and the latest patches to the driver shim, the events are supposed to come across as a single modify, but I have yet to see that happen.

Take note that as the event document comes into the engine it is named in Active Directory's namespace, we have an association value for the group, and it includes an association reference value for each DN specified as a member.

We run through the Input Transformation rule which is meant to convert syntax between Active Directory and eDirectory styles, none of which are really relevant to this event.

Then we run through the Schema transformation that converts the attribute and object class names between the two worlds. Note that group became Group in the class-name= XML attribute, and that the attribute being changed is Member now, not member. This operation is a bad example of Schema mapping since they attributes and classes involved are almost identical.

Also we see that the DNs specified in the document have changed from AD style DNs to eDirectory style DNs.

The resulting document looks like:

<nds dtdversion="2.2">
<source>
<product version="3.5.11.20080307 ">DirXML</product>
<contact>Novell, Inc.</contact>
</source>
<input>
<modify class-name="Group" event-id="0" src-dn="CN=Domain Admins,CN=Users,DC=Test,DC=domain">
<association>f0dc778ec5ff9441b3c3474358f89993</association>
<modify-attr attr-name="Member">
<remove-all-values/>
<add-value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\LSmith3</value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\ADuncan</value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\AJones</value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\ACorona</value>
</add-value>
</modify-attr>
</modify>
</input>
</nds>



We do not do anything to groups in the default Active Directory driver configuration, so after the Event transform the document looks much the same. You will also notice that the Administrator user who was listed in the Active Directory side of the event as a member is not in the list any longer. That is because the Administrator (from AD) user is not synchronized into the Identity Manager system. This is generally a good thing, as you want to keep your administrator level accounts excluded from the system. If something goes wrong, and say all managed accounts get deleted or disabled, you need an account to be able to connect with to fix the problem. In our case, we had scoped the driver to only look at users starting at a specific container, and to ignore the default Users container in Active Directory, where the Administrator user and other service accounts often reside. (On a side point, worth noting that the default container in Active Directory, in LDAP is actually CN=Users,dc=domain,dc=com not OU=Users as you might expect if you are used to eDirectory.

In this case, the Group object happens to be associated, so we did not need to try to Match, Create, and then Place it, so we go on towards the Command Transform rule.

Just before the Command Transform, the engine does something pretty cool and optimizes out the changes (queries for the current values), and sends only the differences between the way Active Directory is saying the group should look and the way eDirectory says it currently looks:

<nds dtdversion="2.2">
<source>
<product version="3.5.11.20080307 ">DirXML</product>
<contact>Novell, Inc.</contact>
</source>
<input>
<modify class-name="Group" dest-dn="LAB\EMPLOYEES\ADGroups\Domain Admins" dest-entry-id="8656
4" event-id="0" src-dn="CN=Domain Admins,CN=Users,DC=Test,DC=domain">
<association>f0dc778ec5ff9441b3c3474358f89993</association>
<modify-attr attr-name="Member">
<add-value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\LSmith3</value>
</add-value>
</modify-attr>
</modify>
</input>
</nds>



As part of that process of optimizing the event we include the XML attribute in the modify node of dest-dn, since we now know where our associated Group object is in eDirectory.

The engine requests the current group membership from eDirectory with a <query> event document, which is returned as an <instance> document. Then it compares the two lists of users in the Member attribute and figures out what is actually changing. This is a good thing as writes to eDirectory end up being only the changes, a single modify event, adding one value to Member, instead of five events.

This makes the process much more efficient, since eDirectory is very quick (and multi threaded) at reads, but writes are single thread process and can take longer.

The engine applies the Command Transformation ruleset, which normally does the conversion work for password events and some other things, most of which are not relevant to Group objects usually. (See http://www.novell.com/communities/node/1474/password-transformation-rule-sets) In this case it add a few extra attributes. Normally they would already be on the Group object in the Vault, but this event was from a test lab that had been restored from a snapshot so things were a bit wonky in places.

One of the interesting attributes to notice is that it decided that we need to also add the Equivalent To Me attribute on the group, half of the second of the pair of reciprocal attributes involved in Group membership in eDirectory.

<nds dtdversion="2.2">
<source>
<product version="3.5.11.20080307 ">DirXML</product>
<contact>Novell, Inc.</contact>
</source>
<input>
<modify class-name="Group" dest-dn="LAB\EMPLOYEES\ADGroups\Domain Admins" dest-entry-id="86564" event-id="0" src-dn="CN=Domain Admins,CN=Users,DC=Test,DC=domain">
<association>f0dc778ec5ff9441b3c3474358f89993</association>
<modify-attr attr-name="Member">
<add-value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\LSmith3</value>
</add-value>
</modify-attr>
<modify-attr attr-name="Object Class">
<add-value>
<value type="string">DirXML-ApplicationAttrs</value>
</add-value>
</modify-attr>
<modify-attr attr-name="DirXML-ADContext">
<remove-all-values/>
<add-value>
<value type="string">CN=Domain Admins,CN=Users,DC=Test,DC=domain</value>
</add-value>
</modify-attr>
<modify-attr attr-name="Equivalent To Me">
<add-value>
<value naming="false" type="dn">\ACME-LAB\LAB\EMPLOYEES\ACTIVE\LSmith3</value>
</add-value>
</modify-attr>
</modify>
</input>
</nds>



This is the document that finally gets submitted to eDirectory, and then the engine in the background (trace will show the event if you are at level 3 or higher) fixes up the other two halves of the reciprocal attributes. Interestingly enough, it looks like it just does it directly, it does not seem to generate an event document that you can apply rules to, in order to modify its behavior.

Having seen all this you can see that attempting to apply policy on a Group membership modification event on the Publisher channel pretty much should be done in the Command Transformation rule for the Active Directory driver. If you tried it in the Event Transformation rule, probably you would lose most of your work as the engine optimizes the event to only send the differences in the Member list.

Unless you have a good idea of what the event will look like, it is pretty hard to write policy to handle it. It is usually the small details that get you in trouble, like the AD Delete event not including the object class (as discussed in: http://www.novell.com/communities/node/1858/more-about-veto-command-scoping-events).

Hopefully this exercise will be helpful in understanding how this kind of event transpires.


Labels:

How To-Best Practice
Comment List
Related
Recommended