Novell Home

Converting Structured Attributes in eDirectory

Novell Cool Solutions: Feature
By Fernando Freitas

Digg This - Slashdot This

Posted: 5 Dec 2007
 

Introduction

This article provides explanations and sample policies to bi-directionally convert a structured syntax attribute to two different eDirectory formats.

Note: This document assumes you are familiar with either Policy Builder or Designer. If that is not the case, please read the documentation for them at http://www.novell.com/documentation - they are included in the current Identity Manager documentation (as of this writing, for Identity Manager 3.5.1). The policy XML provided was written using IDM 3.5.1 engine, and might not work properly on previous versions.

Background

Novell Identity Manager is capable of synchronizing data across multiple systems, however those systems sometimes have different types of syntax for the same attributes. By syntax I mean the way that the attribute is represented in the system, and its constraints.

When that happens, the team implementing IDM needs to write policies and place them in two sets. The Output Transformation Policy set converts from the Identity Vault format to the connected application format, and the Input Transformation Policy set converts from the connected application format to the Identity Vault format. This allows seamless synchronization of these attributes.

Structured attribute syntax implies an attribute in eDirectory where each value can be composed of multiple named parts. Examples would be the ACL attribute, User's Home Directory attribute, Fax Number Attribute, or even the DirXML-Associations attribute.

Verifying the eDirectory Schema

eDirectory is a directory service, and as such it stores data in an object-oriented, hierarchical format. It has a schema (definition of the object and attribute types that it can store, as well as hierarchical placements) that can be easily extended and altered as needed. Due to that flexibility, instead of providing an extensive schema listing, it is better to explain how to read and identify this schema. This can be done in several ways, but the simplest one is to go into iMonitor and see the definition for the attributes you want to synchronize.

iMonitor's documentation can be found at http://www.novell.com/documentation, under eDirectory's documentation.

PeopleSoft Driver Scenario

Due to the way we interface to PeopleSoft, multi-valued attributes always come with the "structured" syntax. If they synchronize to an attribute of the same syntax on eDirectory, that is not a problem. However, data might also come into attributes whose syntax is not structured; then we would have to account for the attribute being single-valued or multi-valued in eDirectory.

Case 1: Multi-valued (structured) attribute on PeopleSoft, single-valued in eDirectory

In this scenario, we need to collapse the attribute's values when coming from PeopleSoft into a single string, and expand it back when returning it to PeopleSoft. We will be hard-coding a delimiter that might be changed to fit the project's needs. The only critical consideration is that the data flowing cannot normally contain that delimiter; otherwise, the provided policy will misbehave.

Note: The rules below treat a single attribute. If there are two or more attributes, then more rules like those will be needed - a set for each attribute. However, because the <component> pieces of a structured attribute have fixed names, those pieces must be changed in the rules for each attribute treated, and that change goes into the Output Transformation Policy set.

In the following examples, replace the "myattribute" and "myclass" strings with the attribute and class to be converted. Also, replace the string "__" (two underscores) string with the desired delimiter.

This is the XML for the policy to be added to the Input Transformation Policy set:

<?xml version="1.0" encoding="UTF-8"?>
<policy>
  <rule>
    <description>Translate attribute syntax from structured to single-valued string</description>
    <conditions>
      <and>
        <if-class-name mode="nocase" op="equal">myclass</if-class-name>
        <if-op-attr name="myattribute" op="changing"/>
      </and>
    </conditions>
    <actions>
      <do-reformat-op-attr name="myattribute">
        <arg-value>
          <token-join delimiter="__">
            <token-xpath expression="$current-value/component/text()"/>
          </token-join>
        </arg-value>
      </do-reformat-op-attr>
    </actions>
  </rule>
</policy>

Here's the XML for the policy to be added to the Output Transformation Policy set:

<?xml version="1.0" encoding="UTF-8"?><policy>
<rule>
  <description>Translate attribute syntax from single-valued string to structured (step 1)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
    </and>
  </conditions>
  <actions>
    <do-set-local-variable name="myattribute_var" scope="policy">
      <arg-node-set>
        <token-split delimiter="__">
          <token-op-attr name="myattribute"/>
        </token-split>
      </arg-node-set>
    </do-set-local-variable>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from single-valued string to structured (add-attr)</description>
  <conditions>
    <and>
      <if-local-variable name="myattribute_var" op="available"/>
      <if-xpath op="true">add-attr[@attr-name="myattribute"]/value/text()</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-strip-op-attr name="myattribute"/>
    <do-add-dest-attr-value class-name="myclass" name="myattribute">
      <arg-value type="structured">
        <arg-component name="1ST-COMPONENT">
          <token-xpath expression="$myattribute_var[1]"/>
        </arg-component>
        <arg-component name="2ND-COMPONENT">
          <token-xpath expression="$myattribute_var[2]"/>
        </arg-component>
      </arg-value>
    </do-add-dest-attr-value>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from single-valued string to structured (modify-attr 1)</description>
  <conditions>
    <and>
      <if-local-variable name="myattribute_var" op="available"/>
      <if-xpath op="true">modify-attr[@attr-name="myattribute"]/add-value/value</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-strip-op-attr name="myattribute"/>
    <do-set-dest-attr-value class-name="myclass" name="myattribute">
      <arg-value type="structured">
        <arg-component name="1ST-COMPONENT">
          <token-xpath expression="$myattribute_var[1]"/>
        </arg-component>
        <arg-component name="2ND-COMPONENT">
          <token-xpath expression="$myattribute_var[2]"/>
        </arg-component>
      </arg-value>
    </do-set-dest-attr-value>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from single-valued string to structured (modify-attr 2)</description>
  <conditions>
    <and>
      <if-local-variable name="myattribute_var" op="available"/>
      <if-xpath op="not-true">modify-attr[@attr-name="myattribute"]/add-value/value</if-xpath>
      <if-xpath op="true">modify-attr[@attr-name="myattribute"]/remove-value/value</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-strip-op-attr name="myattribute"/>
    <do-clear-dest-attr-value class-name="myclass" name="myattribute"/>
  </actions>
</rule>
</policy>

Case 2: Multi-valued (structured) attribute on PeopleSoft; multi-valued (not structured) attribute in eDirectory

In this scenario, we need to convert the attribute's component values when coming from PeopleSoft into a list of values, and convert that list of values back into the components when returning them to PeopleSoft. Because eDirectory orders values within a multi-valued attribute using its own algorithm, its not guaranteed that the order of the attributes returning will be the same that came from PeopleSoft. If the order is required to be the same, an alternate solution would be needed (such as using a structured-type attribute in eDirectory).

Note: The rules below treat a single attribute. If there are two or more attributes, then more rules like those will be needed - a set for each attribute. However, because the <component> pieces of a structured attribute have fixed names, those pieces must be changed in the rules for each attribute treated, and that change goes into the Output Transformation Policy set.

In the following examples, replace the "myattribute" and "myclass" strings with the attribute and class to be converted. Also, replace the string "__" (two underscores) string with the desired delimiter.

Here's the XML for the policy to be added to the Input Transformation Policy set:

<?xml version="1.0" encoding="UTF-8"?><policy>
<rule>
  <description>Translate attribute syntax from structured to multi-valued string (add-attr)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="true">add-attr[@attr-name="myattribute"]/value/component</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-set-local-variable name="myattribute_var" scope="policy">
      <arg-node-set>
        <token-xpath expression='add-attr[@attr-name="myattribute"]/value/component/text()'/>
      </arg-node-set>
    </do-set-local-variable>
    <do-strip-xpath expression='add-attr[@attr-name="myattribute"]/value'/>
    <do-for-each>
      <arg-node-set>
        <token-local-variable name="myattribute_var"/>
      </arg-node-set>
      <arg-actions>
        <do-append-xml-element expression='add-attr[@attr-name="myattribute"]' name="value"/>
        <do-append-xml-text expression='add-attr[@attr-name="myattribute"]/value[count(text())=0]'>
          <arg-string>
            <token-local-variable name="current-node"/>
          </arg-string>
        </do-append-xml-text>
      </arg-actions>
    </do-for-each>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from structured to multi-valued string (modify-attr 1)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="true">modify-attr[@attr-name="myattribute"]/add-value/value/component</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-set-local-variable name="myattribute_var" scope="policy">
      <arg-node-set>
        <token-xpath expression='modify-attr[@attr-name="myattribute"]/add-value/value/component/text()'/>
      </arg-node-set>
    </do-set-local-variable>
    <do-strip-op-attr name="myattribute"/>
    <do-clear-dest-attr-value class-name="myclass" name="myattribute"/>
    <do-append-xml-element expression='modify-attr[@attr-name="myattribute"]' name="add-value"/>
    <do-for-each>
      <arg-node-set>
        <token-local-variable name="myattribute_var"/>
      </arg-node-set>
      <arg-actions>
        <do-append-xml-element expression='modify-attr[@attr-name="myattribute"]/add-value' name="value"/>
        <do-append-xml-text expression='modify-attr[@attr-name="myattribute"]/add-value/value[count(text())=0]'>
          <arg-string>
            <token-local-variable name="current-node"/>
          </arg-string>
        </do-append-xml-text>
      </arg-actions>
    </do-for-each>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from structured to multi-valued string (modify-attr 2)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="true">modify-attr[@attr-name="myattribute"]/remove-value/value/component</if-xpath>
      <if-xpath op="not-true">modify-attr[@attr-name="myattribute"]/add-value/value/component</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-strip-op-attr name="myattribute"/>
    <do-clear-dest-attr-value class-name="myclass" name="myattribute"/>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from structured to multi-valued string (instance docs)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="true">attr[@attr-name="myattribute"]/value/component</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-set-local-variable name="myattribute_var" scope="policy">
      <arg-node-set>
        <token-xpath expression='attr[@attr-name="myattribute"]/value/component/text()'/>
      </arg-node-set>
    </do-set-local-variable>
    <do-strip-xpath expression='attr[@attr-name="myattribute"]/value'/>
    <do-for-each>
      <arg-node-set>
        <token-local-variable name="myattribute_var"/>
      </arg-node-set>
      <arg-actions>
        <do-append-xml-element expression='attr[@attr-name="myattribute"]' name="value"/>
        <do-append-xml-text expression='attr[@attr-name="myattribute"]/value[count(text())=0]'>
          <arg-string>
            <token-local-variable name="current-node"/>
          </arg-string>
        </do-append-xml-text>
      </arg-actions>
    </do-for-each>
  </actions>
</rule>
</policy>

Here is the XML for the policy to be added to the Output Transformation Policy set:

<?xml version="1.0" encoding="UTF-8"?><policy>
<rule>
  <description>Translate attribute syntax from multi-valued string to structured (add-attr)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="true">add-attr[@attr-name="myattribute"]/value</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-set-local-variable name="myattribute_var" scope="policy">
      <arg-node-set>
        <token-xpath expression='add-attr[@attr-name="myattribute"]/value/text()'/>
      </arg-node-set>
    </do-set-local-variable>
    <do-strip-op-attr name="myattribute"/>
    <do-add-dest-attr-value class-name="myclass" name="myattribute">
      <arg-value type="structured">
        <arg-component name="1ST-COMPONENT">
          <token-xpath expression="$myattribute_var[1]"/>
        </arg-component>
        <arg-component name="2ND-COMPONENT">
          <token-xpath expression="$myattribute_var[2]"/>
        </arg-component>
      </arg-value>
    </do-add-dest-attr-value>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from multi-valued string to structured (modify-attr 1)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="true">modify-attr[@attr-name="myattribute"]/add-value/value</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-set-local-variable name="myattribute_var" scope="policy">
      <arg-node-set>
        <token-xpath expression='modify-attr[@attr-name="myattribute"]/add-value/value/text()'/>
      </arg-node-set>
    </do-set-local-variable>
    <do-strip-op-attr name="myattribute"/>
    <do-set-dest-attr-value class-name="myclass" name="myattribute">
      <arg-value type="structured">
        <arg-component name="1ST-COMPONENT">
          <token-xpath expression="$myattribute_var[1]"/>
        </arg-component>
        <arg-component name="2ND-COMPONENT">
          <token-xpath expression="$myattribute_var[2]"/>
        </arg-component>
      </arg-value>
    </do-set-dest-attr-value>
  </actions>
</rule>

<rule>
  <description>Translate attribute syntax from multi-valued string to structured (modify-attr 2)</description>
  <conditions>
    <and>
      <if-class-name mode="nocase" op="equal">myclass</if-class-name>
      <if-op-attr name="myattribute" op="changing"/>
      <if-xpath op="not-true">modify-attr[@attr-name="myattribute"]/add-value/value</if-xpath>
      <if-xpath op="true">modify-attr[@attr-name="myattribute"]/remove-value/value</if-xpath>
    </and>
  </conditions>
  <actions>
    <do-strip-op-attr name="myattribute"/>
    <do-clear-dest-attr-value class-name="myclass" name="myattribute"/>
  </actions>
</rule>
</policy>


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell