One of the new features introduced in IDM 4 was the bidirectional driver for eDirectory, which should ease the process of connecting a remote eDirectory-Tree to an IDM system. This article is written for those having a good understanding of the NetIQ IDM framework, but have not yet implemented this (new) driver.
In this article I will try to roughly describe the basic functionality of this new driver and point out some of the pitfalls deploying the driver for the first time.
Before Novell/NetIQ released the bi-directional eDirectory driver, there were two possible ways to connect a remote eDirectory-Tree. First using the (old) eDirectory driver and second using a native LDAP driver – either way has its drawbacks, which I want to stress here quickly.
The old eDirectory driver was designed in a way, which forces the deployer to create/develop two driver configurations – one for each tree – that were communicating with each other. This solution works, but it comes with some configuration overhead due to the two drivers. In addition to this, entitlements were not (officially) supported for this configuration.
On the other hand a native LDAP driver could be connected to the remote tree. This is a good solution as long as you only want to send data to the remote tree through the subscriber channel. To receive events from the remote eDirectory the LDAP driver needs to implement the “search publication method” which automatically builds the delta between the datasets of two sequential LDAP searches. Due to this approach, the driver does not work on a real event-driven basis on the publisher channel and not all attributes (like passwords) are accessible through native LDAP-API the driver is using.
To avoid the drawbacks of either of the drivers Novell/NetIQ developed the new bi-directional driver for eDirectory.
The new driver utilizes the LDAP-API for the subscriber channel which offers full access – including password synchronization and entitlements – to the connected managed eDirectory tree. For this reason the driver needs a correctly schema-mapping policy. Through a driver parameter the base context of the remote tree is configured. This is working fine as long as common contexts like “O=Corp” can be configured. If the managed system offers two contexts directly under the root of the three the driver cannot be configured correctly. In this case, the base context should be something like “T=Tree-Name”, which is possible against the LDAP-API of eDirectory, but it is not accepted by the publisher channel. (I raised a feature request on this one, but I do not know when it will be officially solved).
To receive data from the managed eDirectory tree, the driver does neither use the LDAP- nor the NDAP-API of the remote eDirectory. This driver is depending on a new eDirectory extension called “eDir – change log”, which must be installed on the server which the driver is communicating with. The installation of these modules is quite simple, as long as DirXML (IDM) never has been installed on this server before. These new modules establish a filtered local event-log, which is read by the driver. During startup of the driver, these modules receive the eDirectory context to be synchronized for this driver.
In this version, only one context can be configured. The option to synchronize the whole tree (T=Tree-Name) is not recognized, as mentioned above. This is the first real drawback of this driver, because it forces you to either use two new drivers – one for each context – or change the tree structure in the managed system.
The new eDirectory change log is quite nice; since it catches only the events the driver is configured to receive through its filters. More precisely: The change log only logs events on classes and attributes configured with the publish option in the filter of the driver.
This sounds great, but if the driver is running with limited rights within the IDM directory, as NetIQ recommends it the driver will not start. This happens because the driver itself is trying to read the filter configuration of the driver object from eDirectory. This is strange, because most other drivers only need the corresponding rights to the synchronized data.
If rights are assigned correctly, the driver is working in both directions as long as the synchronized classes and attributes are spelled 100% the same in both eDirectory schema definitions. If you are challenged with the problem that in one tree the attribute is named idmSurname and in the other corpSurname the synchronization is only working on the subscriber channel – as long as the attribute is correctly mapped in the schema mapping policy.
A work-around to this problem is to manually exit the XML-Data of the driver filter configuration and include all such attributes in the schema of both the trees.
This can only be a workaround, since after manually adding attributes not available in the local schema the current iManager Plugins do not allow to edit the filter anymore – I do not know yet if other problems will come up in this configuration. In at least one project we think that strange eDirectory cores could be related to this configuration as well.
Because of that situation I was searching for a better way to solve the problem. To understand what I did, we need at first to come back to the new change log modules. As I mentioned above, those modules only have to be installed on the server running the eDirectory instance to be connected by the driver. No further configuration has to be done. But how does the remote change log configuration work? If you have a look at the dib directory of the managed server you will find (at least) there additional files if the driver has started correctly.
The first one lists all registered bidirectional drivers in the syntax nnnn_CCCC where nnnn is the local objectID of the driver object in the IDM directory and CCCC is the name of the driver. So if more than one driver is “talking” to the remote tree this file has multiple entries in it.
The last one provides the “filtered” change log for the corresponding driver.
The second file is magically automatically built during the starting of one driver. This file contains the configuration options for the corresponding drivers change log. More or less it is a “converted” version of the drivers filter.
<filter-class class-name="User" publisher="sync" publisher-create-homedir="true" publisher-track-template-member="true" subscriber="sync"><filter-attr attr-name="Full Name" merge-authority="edir" publisher="sync" publisher-optimize-modify="true" subscriber="reset"/> <filter-attr attr-name="Title" merge-authority="edir" publisher="sync" publisher-optimize-modify="true" subscriber="reset"/> <filter-attr attr-name="nspmDistributionPassword" merge-authority="default" publisher="sync" publisher-optimize-modify="true" subscriber="sync"/> <filter-attr attr-name="idmUserEmployeeMail" merge-authority="default" publisher="notify" publisher-optimize-modify="true" subscriber="ignore"/><filter-attr attr-name="idmUserStudentMail" merge-authority="default" publisher="notify" publisher-optimize-modify="true" subscriber="ignore"/><filter-attr attr-name="Internet EMail Address" merge-authority="default" publisher="sync" publisher-optimize-modify="true" subscriber="notify"/><filter-attr attr-name="icmsUserProduktionsfreigabe" merge-authority="default" publisher="reset" publisher-optimize-modify="true" subscriber="sync"/> <filter-attr attr-name="tudUserAssignedCardSnMifare" merge-authority="default" publisher="reset" publisher-optimize-modify="true" subscriber="sync"/> <filter-attr attr-name="Login Expiration Time" merge-authority="default" publisher="ignore" publisher-optimize-modify="true" subscriber="sync"><?comment Has to be in the Filter to recognize Changes from the managed system?> </filter-attr> <filter-attr attr-name="creatorsName" publisher="sync" subscriber="sync"/><filter-attr attr-name="modifiersName" publisher="sync" subscriber="sync"/></filter-class> </filter>
This data is sent to change log because of a query made to the IDM directory during the startup of the driver.
[08/20/14 16:27:25.156]:DRIVER PT:Receiving DOM document from application. [08/20/14 16:27:25.157]:DRIVER PT: <nds dtdversion="4.0"> <source> <product build="20140805_1039" instance="DRIVER" version="22.214.171.124">Identity Manager Bi-directional Driver for eDirectory</product> <contact>NetIQ Corporation</contact> </source> <input> <query class-name="Dirxml-Driver" dest-dn="\IDMS-DEV\tu-darmstadt\res\DriverSet\DRIVER" scope="subtree"> <search-class class-name="Dirxml-Driver"/> <read-attr attr-name="DirXML-DriverFilter"/> </query> </input> </nds>
As mentioned above, this leads to the following error if the driver object does not have the rights to read its filter.
If no Rights are assigned to read the Filer:
<nds dtdversion="4.0" ndsversion="8.x"> <source> <product edition="Advanced" version="126.96.36.199">DirXML</product> <contact>Novell, Inc.</contact> </source> <output> <instance class-name="DirXML-Driver" event-id="0" qualified-src-dn="O=tu-darmstadt\OU=res\CN=DriverSet\CN=DRIVER" src-dn="\IDMS-DEV\tu-darmstadt\res\DriverSet\DRIVER" src-entry-id="367194"/> <status event-id="0" level="success"></status> </output> </nds> [08/22/14 07:36:49.631]:DRIVER PT:LegacyNDS: WARNING !!! No driver filter found... Driver may not start.
If the rights are assigned correctly the changelog config file is created automatically by the driver.
What I did to solve the problem when an eDIrectory to eDirectory schema mapping has to be applied for the change log configuration?
I first created a mapping policy providing a table with the attribute names to be “mapped”. This table could look like this one.
<?xmlversion="1.0"encoding="UTF-8"?><mapping-table> <col-defname="IDM"type="nocase"/> <col-defname="ManagedSystem"type="nocase"/> <row> <col>idmUserChristianName</col> <col>Given Name</col> </row> <row> <col>idmUserSurname</col> <col>CorpSurname</col> </row> </mapping-table>
Additionally I wrote an Output-Transformation policy to intercept the filter provided as an answer to the query sent by the driver during startup. This policy utilizes xpath to walk through all attribute names in the filter replacing those that can be found in the mapping policy.
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEpolicyPUBLIC"policy-builder-dtd""C:\Program Files (x86)\Novell\Designer\plugins\com.novell.idm.policybuilder_188.8.131.52404231247\DTD\dirxmlscript4.0.2.dtd"><policyxmlns:jstring="http://www.novell.com/nxsl/java/java.lang.String"><rule> <description>convert filter for changelog</description> <conditions> <and> <if-operationmode="case"op="equal">instance</if-operation> <if-class-namemode="case"op="equal">DirXML-Driver</if-class-name> <if-op-attrname="DirXML-DriverFilter"op="available"/> </and> </conditions> <actions> <do-set-local-variablename="lv.Filter"scope="policy"> <arg-node-set> <token-xml-parse> <token-base64-decode> <token-op-attrname="DirXML-DriverFilter"/> </token-base64-decode> </token-xml-parse> </arg-node-set> </do-set-local-variable> <do-for-each> <arg-node-set> <token-xpath expression="$lv.Filter/descendant::filter-attr"/> </arg-node-set> <arg-actions> <do-set-local-variable name="lvFilterAttr"notrace="true"scope="policy"> <arg-string> <token-xpath expression="$current-node/@attr-name"/> </arg-string> </do-set-local-variable> <do-set-local-variable name="lvChangeLogAttr"notrace="true"scope="policy"> <arg-string> <token-map default-value="$lvFilterAttr$"dest="ManagedSystem"src="IDM"table="ChangelogAttributeMap"> <token-local-variable name="lvFilterAttr"/> </token-map> </arg-string> </do-set-local-variable> <do-trace-message notrace="true"> <arg-string> <token-local-variable name="lvFilterAttr"/> <token-text xml:space="preserve"> : </token-text> <token-local-variable name="lvChangeLogAttr"/> </arg-string> </do-trace-message> <do-set-xml-attrexpression="$current-node"name="attr-name"notrace="true"> <arg-string> <token-local-variablename="lvChangeLogAttr"/> </arg-string> </do-set-xml-attr> </arg-actions> </do-for-each> <do-trace-message> <arg-string> <token-xml-serialize> <token-local-variablename="lv.Filter"/> </token-xml-serialize> </arg-string> </do-trace-message> <do-reformat-op-attrname="DirXML-DriverFilter"> <arg-valuetype="string"> <token-base64-encode> <token-xml-serialize> <token-local-variablename="lv.Filter"/> </token-xml-serialize> </token-base64-encode> </arg-value> </do-reformat-op-attr> </actions> </rule> </policy>
At least in one of our projects we had sometimes trouble with eDirectory coring on the connected sever under certain conditions. We found that this did not happen, if we had the custom mapping table and the above policy in place, making sure that the filter configuration file for the change log module does not contain any foreign attribute names. This behavior is still under investigation.
I hope this article could be helpful for those thinking to implement this driver.
Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment. It just worked for at least one person, and perhaps it will be useful for you too. Be sure to test in a non-production environment.