Walking through the IDM 4 Google Apps Driver - Part 3


With the release of NetIQ Identity Manager 4.0 Support Pack 1 (aka IDM 4.01) some bug fixes, and a few new features were added.

Specifically three partner provided drivers were included, an RSA Driver, a Blackboard driver, and a Google Apps driver.

I discussed some of the new features and bugs fixed in IDM 4.01 in this series of articles:

I have been working on a series of articles walking through driver configurations, policy by policy to try and understand what the driver is doing, under the covers.

You can see more of these walk throughs on a Wiki page I maintain to keep them all together: Detailed driver walk through collection.

For this series of articles I would like to start looking at the Google Apps driver in IDM 4.01, that is provided by Consensus Consulting.

In the first article in the series I worked my way through the Subscriber Event transform and half way through the Matching Policy set.

In the second article in the series I worked my way through the rest of the Matching Policy set.

In this article let's work through the Creation policy set.

The Creation Policy set is where the driver makes some decisions as to whether we have enough information to create.

This policy set has 5 policy objects.

Generally a Create rule looks for required attributes, or perhaps calculates needed attribute data. Otherwise it stops the event till more information is available. You can see this in more common drivers, like the Active Directory one, where a user is created in eDirectory in one event, but does not yet have a Full Name attribute, which Active Directory would like to use for the display name. So the first event is kicked out. Then the admin goes back and adds a Full Name attribute. (This was true in earlier configurations, later ones calculate it from Given Name and Surname). Then the event comes through as a modify, converts to a synthetic add, all the data is pulled, and now we see there is no password set yet (nspmDistributionPassword is the attribute of interest) so then the event might be vetoed again until a password change event comes on its own, at which point that would again become a synthetic add and finally get past the Create policy and move on.


For a Contact we need to provide Given Name, Surname, and Internet EMail Address. This rule uses the Veto if operational attribute not available. This is a nice short cut token, since it is so common to use it in the Creation policy set.

You could have an IF THEN test for if the operational attribute is not available (not changing, since changing would be true if just an attribute is being removed or added, though that is not really a concern in the add event example), and then if true, use a Veto() token. Thus this single token is a nice short cut to save code. I can think of many more such short cuts I would not mind seeing added to the product, but I understand that there needs to be a balance struck between too many short cuts and not enough.


For a Group there is an extra test for the Entitlement again. Which is interesting as the Event Transform and Match rule should have cancelled this already. Although I suppose we could have require Entitlement set and not Match on Entitlement set and get to this case.

Finally the group requires a CN, which is mapped to Google's Name attribute/

Then some source attributes are written back to the group in eDirectory.

An Auxillairy class of DirXML-GAGroupAux is added, and then the DirXML-GAGroupEmailAddress attribute is populated with Source Name @ the GCV for the domain.

And then they do something I have not tried before, that I even had to go read the help on the token they use! They do a set default attribute value token. This is an interesting token. It is sort of a set it in both directions kind of thing.

That is, if you set a default attribute, it only works on an add event, in which case the attribute and value will be added to the current event in the channel. But there is a write-back option, which if true will write the same attribute and value back to the source as well. Neat, I had never actually used this token before. What is a smidgen odd is that they set write-back to false, so it does not write it back to the source, in which case it should be indistinguishable from an add destination attribute token call. So I am not sure what value is added by this choice.

Anyway the attribute is Permission and the value comes from a GCV named gcv.NOVLGGLEGRPS.DefaultVisibility which is defined in the Group Settings GCV object as:
<definition critical-change="false" display-name="Default visibility for Google Groups" hide="false" item-separator="|" multi-line="true" name="gcv.NOVLGGLEGRPS.DefaultVisibility" type="enum">
<description>Owner, Member, Domain, Anyone</description>
<enum-choice display-name="Owner Only">Owner</enum-choice>
<enum-choice display-name="Members Only">Member</enum-choice>
<enum-choice display-name="Domain Users Only">Domain</enum-choice>
<enum-choice display-name="Anyone-Internet Enabled">Anyone</enum-choice>

However, all the GCV's in this GCV object are set to hidden, (look for hide="true" in the XML view to find these). Including this one, so as a heads up, it defaults to Domain! Just because it is hidden does not mean it is not set and usable, it is just not visible in the iManager or Designer user interfaces.

Anyway, the key thing to take away from this, is that to change this is a bit of a pain, is non-obvious, and I think I will report this as a bug on the driver. This one should be visible by default. The reason the GCV's are all hidden is because they are set up for Entitlement support for Groups, and it looks like the configuration they are using is not yet finished and ready to support Entitlements for Groups. The dead giveaway? The default view of this GCV object shows a <header> tag, that says:
Entitlement GCV's are for future versions and are not supported at this time.


This is the Org Unit create rule, as the name implies, and like all the rest scopes itself to the Organizational Unit, and checks for just the OU attribute, which is the naming attribute of an Organizational Unit, which is mapped to Name in Google.


Now we get to what should be the interesting rules, the User case. As always, scope it to the User class, then come a couple of rules:

  • User Create Rule when Using Google Account EntitlementThis rule checks the GCV that requires an Entitlement. Then if it the entitlement is not available it vetoes again.

    For each entitlement, it uses the ECMA call to es:getEntParamField() to get the user name out of it. (Note is it the user name, not the full email that is in the entitlement value).

    Using that value, it sets the CN (using the default attribute token, no write back again, still not sure why) and then the source attribute Internet EMail Address, and builds the email based on the name sent in and @ the GCV for the domain.

    Then if there is no Surname or Given Name it vetos, and if we got this far, it skips the rest of the policy using a Break() token. Which is interesting because the last rule is called "GroupMembership entitlement: Signal the need to check group entitlements after the add" which implies that you would likely need to run this rule, even in the user entitlement case. If this is correct I wonder why? I wonder if it is related to the GCV for Group Entitlements showing that they are not yet supported. Perhaps when they are, an update to the User package will be required to fix this.

  • User Create RuleThis is a simple create policy rule. Veto if the Surname or Given Name is missing in the event document. Then like in the Entitlement case set the CN in Google and email address in eDirectory based on the Source Name of the object. Again a set default attribute token with write-back set to false is used for CN and I wonder why.

    GroupMembership entitlement: Signal the need to check group entitlements after the add

    If the GCV's to support Group Entitlements are enabled and there is a Group entitlement, then we cannot add the user to the group yet, since they do not exist in Google Apps. So in the Input Transform we will have a rule that when we get an <add-association> event after successfully adding a user and there is the operation property check-group-entitlements which is set here, that it will do the work.

    You can see this in the Active Directory driver as well if you are interested. Look in the Input Transform for a policy called NOPVLADCFG-itp-SubscriberUserAdd for how the Active Directory driver does its trick.


This rule is kind of clever. If there is a no password available, often in Create rule the driver would veto until the password is set. However this rule starts by breaking if there is an existing password, and if not, generating one to be used in Google.

There is a GCV that controls whether a password is randomly generated, and as discussed in the first article, this is why they made their own Password GCV package for this driver, as it adds a couple of GCVs to handle these cases.

If their GCV is set to random, then they generate a random password. Interestingly enough, they do not use the Generate Password() token, instead they have their own approach. Generate Password is a fun token. You point it at a Password Policy, and it reads the requirements and generates a random password that matches. I had a client who was not using passwords in a connected system and wanted them hugely randomized so we set up a Password Policy that applied to no objects, that required 15 characters minimum of all 4 possible cases (Upper case, lower case, numeric, special character) and was size limited from 60 to 200 characters. This generated a horribly ugly random password.

Here they use the approach of:
es:createPassword4(($gcv.NOVLGGLEPSWD.RandomPasswordNumberOfLetters   $gcv.NOVLGGLEPSWD.RandomPasswordNumberOfNumbers), $gcv.NOVLGGLEPSWD.RandomPasswordNumberOfLetters, $gcv.NOVLGGLEPSWD.RandomPasswordNumberOfNumbers)

This function is also part of the lib-AJC ECMA library. (Advanced Java Class, rewritten in ECMA Script).

Basically you pass in the length, number of letters you want, and number of digits.
* Create an alphanumeric password.
* @param {String} passwordLength length of the password
* @param {Number} numOfAlphabets count of characters in the password
* @param {Number} numOfDigits count of digits in the password
* @type String
* @return a string in the format: <PRE>1AB2C3D</PRE>
function createPassword4(passwordLength, numOfAlphabets, numOfDigits)
var characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var digits = "0123456789";

if(passwordLength < (numOfAlphabets numOfDigits))
throw new Error(pwdExceptionMessage);

var password = [];

var charLength = characters.length;
var digitLength = digits.length;

var pwdArrayIndex = 0;
var index = 0;

for(var i = 0; i < numOfAlphabets; i )
pwdArrayIndex = Math.round(Math.random()*(passwordLength - 1));
} while(password[pwdArrayIndex]);

index = Math.round(Math.random()*(charLength - 1));
password[pwdArrayIndex] = characters.charAt(index);

for(var i = 0; i < numOfDigits; i )
pwdArrayIndex = Math.round(Math.random()*(passwordLength - 1));
} while (password[pwdArrayIndex]);

index = Math.round(Math.random()*(digitLength - 1));
password[pwdArrayIndex] = digits.charAt(index);

for(var i = 0; i < passwordLength; i )
index = Math.round(Math.random()*(digitLength charLength - 1));

if(index < charLength)
password[i] = characters.charAt(index);
password[i] = digits.charAt(index - charLength);

return password.join("");

If I read this right, it has minor error checking that the length is not shorter than the numbers you requested (letters and numbers) added up.

Then loops the number of times you requested and selects a random letter than a random digit and if there are still more required values, it picks a random number between 0 and 35 (10 numbers 26 characters, counting from 0) and starts adding which ever that represents.

It probably is just as easy to use a Generate Password() token call, since that actually has better fidelity and control, but this works equally randomly.

Next up is a rule for when the password generation mode is not random and is instead the value 'attribute'. In that case, there is a GCV that has the attribute name, and the value of the attribute is read and used.

Then they do something clever by testing the variable value, and making sure it is long enough. Now I would have done this with a XPATH of string-length($lv_defaultDPWAttributeValue) > 5 but they chose to use Regular expressions to validate it instead.

They do an if local variable is equal, but switch the equality type from case insensitive (the default) to regular expression. There are some fun equality tests available (and poorly documented) like Source DN, which I was told means it uses DN (distinguished name) semantics to compare. I am trying to track down more details on that, article no doubt to follow.

The Regular Expression they use is six periods. A period means match any character. But only one. Thus to match any value at all we usually use . (dot plus) or .* (dot star) where the plus sign means one to unlimited characters, and the dot star means zero to unlimited times. But here with six dots it means match 6 characters. Thus if true, it is long enough, in which case the password is set in the event document to that value. If it is not long enough then they take the value, append a padding character that came from a GCV called gcv.NOVLGGLEPSWD.initialPasswordPadCharacter seven times, and then substring the whole kit and kaboodle to six characters. This way they are sure they have a long enough basic password.

It does seem a tiny bit contrived, but it should work without any issues. I love that about Identity Manager. There are so many ways to skin the cat.

That completes the Creation Policy Set, now on to the Placement Policy set. Next article we move on to the Placement Policy Set where the driver decides where the object is going in the target system. Of course, some systems are flat and have no structure, but other connected systems have all sorts of placement objects. Looks like Google supports both models, flat or structured, so that should be a fun set of rules to look through.


How To-Best Practice
Comment List