Novell Home

IDM Rule Programming Techniques for Pseudo Select Statement Emulation

Novell Cool Solutions: AppNote
By Justin Birt

Digg This - Slashdot This

Posted: 12 Sep 2007
 

Introduction
A Rule Programming Conundrum
The "Replace All" Verb Action
Further Application
Conclusion

Introduction

Prior to IDM version 3.5, conditional testing in IDM rules was primitive. Rules within policies comprised of a condition followed by an action. If you were required to apply multiple conditional tests on an attribute and perform different actions depending on the outcome - as would be possible with a select statement, for example - then you had to code this using multiple rules.

With the release of IDM v3.5, Novell has introduced the IF-THEN-ELSE and Map verb tokens that greatly improve the conditional handling when constructing rules.

For those IDM users that have yet to upgrade to IDM v3.5, or those up-to-date users who just wish to add another useful construct to their rule-coding arsenal, this document details a powerful technique that uses the Replace-All action and regular expressions to construct complex conditional statements within a single rule.

A Rule Programming Conundrum

Consider the scenario where you have an environment with tens of thousands of users. You want to store the user objects hierarchically in eDirectory, based on an alphabetical grouping by surname to make things a bit more manageable, as shown in the illustration below.

Figure 1 -

Traditionally, you might approach this in IDM by including six explicit rules in the Placement policy, one for each alphabetical grouping. One of these rules for the ABCD grouping is shown below. In the condition or "if" section of the rule I have a regular expression that tests if the first character of the Surname attribute is either A, B ,C, or D.

Figure 2 -

As XML, it will look like this:

  <rule>
    <description>Example Rule</description>
        <conditions>
           <and>
               <if-op-attr mode="regex" name="Surname" op="equal">[ABCD]{1}.*</if-op-attr>
           </and>
        </conditions>
        <actions>
            <do-set-op-dest-dn>
                <arg-dn>
                    <token-text xml:space="preserve">\USERS\ABCD\</token-text>
	     <token-op-attr name="CN"/>
               </arg-dn>
            </do-set-op-dest-dn>
        </actions>
    </rule>

If this condition is met, then the rule will be selected and the action will construct the operation destination DN as shown, placing the user object in an OU called ABCD.

This works very well. By creating a further five rules in the Placement policy to cover the other alphabetical groupings, user object placement in the other OUs is achieved.

But wouldn't it be great if you could condense this down to just one rule!

The "Replace All" Verb Action

This section examines the use of the "Replace All" verb action to construct a pseudo "select statement." This statement provides multiple conditional tests and different actions, depending on the result of this conditional block.

Example Rule

The Replace All verb action allows the conditional test of a passed string parameter. If the test is true, the string can be affected in some way. If the test is false then the original passed parameter is returned unaffected.

In the example shown below, I have re-written the rule shown in the previous section.

Figure 3 -

You can see that there is no condition statement in the normal Condition Group. What is occurring now is the regular expression test - to see if the first character of the Surname attribute is either A, B, C or D - is within the Replace All token.

  <rule>
    <description>Example Rule</description>
        <conditions>
            <and/>
        </conditions>
        <actions>
            <do-set-op-dest-dn>
                <arg-dn>
                    <token-text xml:space="preserve">\USERS\</token-text>
                <token-replace-all regex="[ABCD]{1}.*" replace-with="ABCD">
	        <token-op-attr name="Surname"/>
	    </token-replace-all>
	    <token-op-attr name="CN"/>
               </arg-dn>
            </do-set-op-dest-dn>
        </actions>
    </rule>

So if this rule was applied to the creation of a user John Doe (Joe Bloggs for us in the UK), then the Operation Destination DN would be:

\USERS\ABCD\jdoe

This is because the Replace All token would substitute the text of the Surname attribute with 'ABCD' as the regular expression [ABCD]{1}.* It returns true in this example.

This is just what we want. But what about a user 'Barry Greggs'? In that case, the rule would set the Operation Destination DN to:

\USERS\Greggs\bgreggs

As the first character of the Surname would not be either A, B, C or D then the regular expression returns false and as such the Replace All token does not operate but passes the value of the Operation Attribute Surname child token unaffected.

This is a promising start, but we fell at the first hurdle!

Fear not, we haven't finished yet. In the first example, you'll remember I mentioned that you had to create a separate rule for each alphabetical group to achieve the required outcome. The same is true with our pseudo "select statement" using the Replace All verb token.

We are going to leverage the fact that a Replace All token can be a child of another Replace All token. The illustration below and the XML code segment that follows show the full set of Replace All token statement required for our example.

Figure 4 -

<rule>

<description>Example Rule</description>

<conditions>
    <and/>
</conditions>

<actions>
    <do-set-op-dest-dn>
        <arg-dn>
            <token-text xml:space="preserve">\USERS\</token-text>
                <token-replace-all regex="[UVWXYZ]{1}.*" replace-with="UVWXYZ">
                    <token-replace-all regex="[QRST]{1}.*" replace-with="QRST">
                        <token-replace-all regex="[MNOP]{1}.*" replace-with="MNOP">
                            <token-replace-all regex="[IJKL]{1}.*" replace-with="IJKL">
                               <token-replace-all regex="[EFGH]{1}.*" replace-with="EFGH">
                                    <token-replace-all regex="[ABCD]{1}.*" replace-with="ABCD">
                                        <token-op-attr name="Surname"/>
                                    </token-replace-all>
                                </token-replace-all>
                            </token-replace-all>
                        </token-replace-all>
                    </token-replace-all>
                </token-replace-all>
                <token-text xml:space="preserve">\</token-text>
                    <token-op-attr name="CN"/>
            </arg-dn>
        </do-set-op-dest-dn>
    </actions>
</rule>

The structure of the expression in the Designer Argument Builder, as shown below.

Figure 5 -

Now let's examine what happens with our user Barry Greggs.

The Operation Attribute Surname is passed to the first Replace All token and is tested to see whether the first character is A, B, C, or D. The regular expression in this token will return "false," so the value of Surname will pass unaffected to the parent token.

Here, the test is to see whether the first character is E, F, G or H. The regular expression in this case will, of course, return "true." The Replace All token will substitute 'EFGH' and pass this string the the next parent token.

As the EFGH value is passed up the remaining Replace All tokens, their respective regular expressions will return "false," meaning that no further changes are affected.

The Operation Destination DN attribute is correctly set to:

\USERS\EFGH\bgreggs

Thus, one rule in the Placement policy can create the hierarchical placement of user objects, based on the alphabetical order of the first character of the Surname attribute.

Weaknesses

Although this technique allows the construction of powerful conditional blocks within a single IDM rule, it has weaknesses.

Unlike a true select statement block, there is no break statement in each case definition. The token is passed through each case block effectively. When applying this technique yourself, ensure that values presented can satisfy only one of the conditions you define.

There is no default statement to catch any values that do not meet any of your defined conditions. Therefore, you must make sure that values you present can satisfy one condition.

Further Application

This document has given an application of this technique to illustrate its function. Let's examine some other areas where it might be applied.

Office Location

I have seen examples where the workforceID attribute of User objects contained a code letter indicating the specific office where a user worked. Users at specific offices were administered locally and were therefore placed in a location OU. The names of these OUs in the eDirectory tree were verbose, such as New York or London, but the identifier in the workforceID attribute was, for example, 'L' representing 'London'. So a user's workforceID might be L12345678.

Now IDM v3.5 users will see that we are straying into Map territory here, but for a limited number of values this techniques can again be useful.

The XML for a rule to solve our location problem is shown below:

<rule>
    <description>Example</description>
        <conditions>
             <and/>
        </conditions>
        <actions>
            <do-set-op-dest-dn>
               <arg-dn>
                   <token-text xml:space="preserve">\EMEA\</token-text>
                       <token-replace-all regex="[L]{1}" replace-with="LONDON">
                           <token-replace-all regex="[P]{1}" replace-with="PARIS">
                               <token-replace-all regex="[R]{1}" replace-with="ROME">
                                   <token-substring length="1">
                                        <token-op-attr name="workforceID"/>
                                   </token-substring>
                               </token-replace-all>
                           </token-replace-all>
                       </token-replace-all>
                      <token-text xml:space="preserve">\USERS\</token-text>
                      <token-op-attr name="CN"/>
               </arg-dn>
            </do-set-op-dest-dn>
        </actions>
</rule>

Here we strip the first character of our workforceID attribute and pass it into our Replace All conditional block. We decode the single character to be the full name that corresponds to the directory OU names when constructing or destination DN attribute. We have effectively mapped L to LONDON, P to PARIS, and R to ROME, and used this information to help construct the destination DN of our user objects.

Conclusion

It can be seen that by using Rule tokens that are available in IDM prior to v3.5, it is possible to construct within a single rule some advanced conditional processing that would normally be achieved by configuring a sequence of rules.

Enjoy!


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

© 2014 Novell