Back in 2002, Israel Forst published this article (Group Membership Updater) using an XSLT stylesheet to allow simpler LDIF operations to update a User's Group Membership while still keeping all four eDirectory DN links correctly updated. It's a nice bit of XSLT, but most Identity Manager development is now done in Policy Builder (aka DirXML Script). This makes development faster and easier, and debugging a lot easier.
So, presented here is an updated version of Israel's Updater driver.
Group Membership in eDirectory is actually four links between two objects. The User has two links (Group Membership, Security Equal To) to the Group object, and the Group has two links (Member, Equivalent To Me) to the User object. All four of these are DN references, so that if an object moves, the links are updated so that everything is still correct. All four of them are also multi-valued, so that a User can be a member of more than one Group, and a Group can have more than one member.
To correctly add a User to a Group, then, is really four object updates. These can be done in any order, but all four must be done. In an LDIF file, these four updates would be expressed like:
Here you can see that the User object (cn=userbob) is being updated with Group Membership and Security Equals, and the Group object (cn=groupname) is being updated with Member and Equivalent To Me.
Some other directory services do things differently. In Active Directory, for example, only the Group is ever updated. It has one link back to the User object that is a member of the group, but the User has no link to the Group object. This simplifies things, a bit, for LDIF operations, as adding a User to a Group is simply a matter of updating the Group like:
Some people do not realize that all four attributes must be updated, so they apply an LDIF file modeled on something they found via Google, and they end up only updating one of the four attributes. While eDirectory is happy to let you do this, it does not help you out by filling in the missing three attributes. The result is often a cry of "it doesn't work".
This problem can be solved. Identity Manager can watch for changes to an attribute, and can then apply policies to update other attributes, on other objects, as needed. So all it has to do, in this case, is watch for changes to Member (Group) and reflect them as updates to Group Membership on the User, and watch for updates to Group Membership (User) and reflect them as updates to Member on the Group.
For this example, I am using the Identity Manager "Null" driver. This implements a Subscriber channel only and is handy for things like this where we want to watch eDirectory for something to happen, then do something about it in eDirectory.
In order to make this work both ways, the Identity Manager driver Filter must be configured to watch for changes to User or Group objects. We are interested in the User/Group Membership, and the Group/Member attributes. If either one changes, we want to do something about it.
This policy set has two rules in it.
This rule watches for changes in a Group object's Member list. If the Member attribute is changing, we know that a User is being added to, or removed from, this Group. Since add and remove can be in the same event document, this rule has to handle both.
First, for clarity, the DN of the Group is saved in to a local variable (GroupDN).
Second, a nodeset local variable (UserAddDN) is created to contain the User(s) that are being added to this Group.
Third, a nodeset local variable (UserRemoveDN) is created to contain the User(s) that are being removed from this Group.
Then, a pair of do-for-each() loops are used to loop through the add and remove nodesets, generating <modify> events for the User(s) adding or removing the needed Group Membership values.
This rule watches for changes in a User object's Group Membership list. If the Group Membership attribute is changing, we know that this User is being added to, or removed from, a Group. Since add and remove can be in the same event document, this rule has to handle both.
First, for clarity, the DN of the User is saved in to a local variable (UserDN).
Second, a nodeset local variable (GroupAddMember) is created to contain the Group(s) that this user is being added to.
Third, a nodeset local variable (GroupRemoveMember) is created to contain the Group(s) that this user is being removed from.
Then, a pair of do-for-each() loops are used to loop through the add and remove nodesets, generating events for the Group(s) adding or removing the needed Member values.
Carried over as a concept from Israel's original driver, this driver sample is configured with a "scope" so that it only applies to User and Group objects in a specific sub-tree of eDirectory. This is configured with Global Configuration Variables (GCVs) in the driver configuration. Set the "Users Container" and "Groups Container" GCVs to reflect your tree's layout.
Alternately, to un-scope the driver so that it works on all User and Group objects, disable the "if source DN in subtree ..." condition on the two rules discussed above.
I did not mention the Security Equals and Equivalent To Me attributes in the descriptions of the two rules, yet looking at the DirXML Script code for the rules you can see that these are being handled just like the Group Membership and Member attributes.