Walking through the Banner Driver - Part 5

In part 1 of this series I started explaining the driver configuration for the Ellucian Banner driver.

In part 2 of this series I started looking at the Global Configuration Variable values.

In part 3 of this series I finished going through the GCVs and other settings.

In part 4 of this series I started working through the Input Transform.

In this article I will continue working through the Input Transform, since this is a mostly Publisher Channel driver.

The policy we are working on is named NOVLBNNRUSER-pub-itp_GenerateUsername and I had discussed previously how it allows a GCV to specify either an attribute name, or a value in the format f1m0l* (One character of first name, zero characters of middle name, and the remaining characters of last name for the name.

They first checked to see if the value of the GCV was the name of an operation attribute. Thus very elegantly allowing one GCV to provide two totally different classes of info. If the op attr exists, (which f2m0l6 never would for 2 chars of first name, zero middle, and 6 last is defined as) then use it, if not start doing some processing.

This is done by first parsing the GCV to know the number of characters from each set to use. There are three instances like this:

<do-set-local-variable name="lv_firstNameCharacters" scope="policy">
<token-replace-all regex="\*" replace-with="128">
<token-xpath expression='substring(substring-after($gcv.NOVLBNNRUSER.pubCNFormat,"f"),1,1)'/>

That says, substring the value of the GCV gcv.NOVLBNNRUSER.pubCNFormat after the 'f' character, one character long. (First substring-after the f, then use the substring to only take the first character.) Thus in the case of 'f7m0l1' the value after the 'f' is '7m0l1' and the first character of that value is 7.

Also, if there is a asterisk (*, Asterix is a Gaul from the cartoons) replace it with 128. Note that the asterisk is escaped with a backslash since the Replace All token is a Regular Expression based interpreter.

Do this to get the first, middle, and last name lengths.

Then get the first, middle, and last name operation attributes into variables appropriately named. (lv_firstName and so on).

Then build each piece of the name with something like:

<do-set-local-variable name="lv_firstNamePiece" scope="policy">
<token-xpath expression="substring($lv_firstName,1,$lv_firstNameCharacters)"/>

That means, lv_firstNamePiece will be the substring of the lv_firstName value, starting at position 1 (Count is from 1 I guess, not 0) the lv_firstNameCharacters number of characters.

Do that for middle and last name as well, then finally put it all together.

<do-set-local-variable name="lv_cnToUse" scope="policy">
<token-replace-first regex="f[*\d] " replace-with="$lv_firstNamePiece$">
<token-replace-first regex="m[*\d] " replace-with="$lv_middleNamePiece$">
<token-replace-first regex="l[*\d] " replace-with="$lv_lastNamePiece$">
<token-global-variable name="gcv.NOVLBNNRUSER.pubCNFormat"/>

So what the heck are they doing here? Why are they doing it? Why not just simply concatenate the pieces together?

Well they are even more clever! They allow for reordering of the parts. I.e. All my examples so far have been f1m1l6 style. But of course, you might want last name first. I which case a format string of 'l6f1m1' would work too. Or any order. Thus the clever aspect of what they do. They replace the f1 or l1 or m1 with the first, last, or middle name components, already substringed.

Very clever. I like it. I had not considered this approach before, but it is very elegant.

Too dissect this, the replace all's focus on the pubCNFormat GCV value (The one of 'f1m1l6' format). Then they execute the same basic replace all token three times. The basic approach is the same in all three, just with differing single character codes (f, m, or l) and then the appropriate matching variable.

<token-replace-first regex="l[*\d] " replace-with="$lv_lastNamePiece$">

So this looks for the Regular Expression "l[*\d]" which means, the literal character l, then a set of either the character * or a digit (\d is character class shorthand for digits). Thus the 'l' followed by a digit or asterisk will be replaced with the lb_lastNamePiece variable value.

Same is done for first and last. Thus regardless of the ordering in the config string, so long as you only use a single character as your counter (1-9 only) then it works. Very clever.

Now if you wanted to use 10 characters from the first, last, or middle (which is sized to 6 chars I think in eDir) then you are just plain out of luck. But if you did, you are kind of nutty anyway, with such long usernames. What do you do for the short named folk among you anyway?

I have to say, I have not enjoyed reading a policy quite as much as that one in a while. It is just full of fun neat ideas, so very clever. Well done!


This is the standard Novell provided Password Synchronization package policy, if you have the GCV set to email on failed password changes, this handles it.

That wraps up the Input transform, and now on to the rest of the Publisher channel.

The Event Transformation is empty, which is itself interesting. No need to handle renames, moves, or the like, coming out of Banner I guess. That makes sense.

Now is as good a time as any to look at the Schema Map and filter.

There is a single Schema Map object included:


Here we get the UDCIdentity object class (table?) from Banner mapped to the User object class. There is not very much here of interest other than to note some of the funnier mappings. Generational Qualifier (things like III (The third) or Jr) is mapped to Affix.

Also there seems to be a set of address related attributes that perhaps behave like structured attributes? homeCity in eDirectory gets mapped to PrimaryAddress:Municipality and then homeState is mapped to PrimaryAddress:Region. There is a similar notation where S is mapped to CampusAddress:Region. I would be curious to see what happens under the covers in this shim to understand what is happening there.

Otherwise not much else to see. They did not create a DirXML-bnrXXXXXX set of object classes, rather they map the Banner data to attributes that already exist (Like homeCity, homeState, S, SA, as noted above) or else they created udcXXXXXX classes, like udCGender, udcInstitutionalRoles, or udcTaxId.

I know in the case of learning systems, that there is actually a standard for an LDAP schema to describe course enrollments. The IMS Global standard body has come up with the Learning Information Systems (LIS) standard that you can read about: http://www.imsglobal.org/lis/

A fairly large number of products support it now. Oracle's add on to PeopleSoft, SAIP will export its data in this format. As will Banner via the BEIS, but not through this driver. Many learning systems will then consume the info to manage course enrollments.

Thus it may be that this udcXXXXX schema approach is a concession to the standards approach, but I may be giving them too much credit.

Next up, matching!

Matching Policy Set:

There is only one policy object.


There is a single rule, Match on GCV attribute, whose name says it all. The comment notes that there is a GCV that has the name of the matching attribute, so pick something Banner sends, and is usefully unique (udcIdentifier? udcTaxID?) and specify so that matches can be made.

Create Policy Set:

There are two policy objects here.

  • NOVLBNNRUSER-pub-cp_UserCreate

  • NOVLBNNRUSER-pub-cp_UserPasswordCreation


This test for the class user, and then does the Veto if Operational Attribute is not available token for three attributes. Given Name, Surname, and CN.

What is interesting is that I was pretty sure I was told that the Banner shim, translating the BEIS SPML document to XDS always gets the full user object in each event. Can you enter a user in Banner without a Given Name or Surname? If neither, I imagine the very clever name generation rule I enjoyed reviewing would probably return an empty but present CN. I am not sure if this is really ever needed but perhaps there is an edge case where it can help.


There are four rules here.

  • Break if not a User object or NSPM distribution password available

  • Generate Random Password if no Distribution Password available and GCV is set to random

  • Set initial password value from attribute if no Distribution Password available and GCV is set to attribute

  • Generate Password from Universal Password Policy if no Distribution Password available and GCV is set to universal

Basically these four rules handle the password generation cases that the GCV's select from the option list.

Break if not a User object or NSPM distribution password available.

First off, make sure it is a User, even though no other object classes in the filter. Then make sure the nspmDistributionPassword is not yet available (I.e. Set earlier?), and finally, if the GCV gcv.NOVLBNNRPSWD.InitialPassword is set to None, then break. In these cases there is no need to generate a password. I am pretty sure from looking through this that the Banner system does not maintain a password, nor does it send it in any events, so the need to generate them on user creates is important.

Generate Random Password if no Distribution Password available and GCV is set to random

If the GCV gcv.NOVLBNNRPSWD.InitialPassword is set to random, then an ECMA function, es:createPassword4 is called to run the password generator function provided by the Lib-AJC ECMA library.

The full function call is:
es:createPassword4(($gcv.NOVLBNNRPSWD.RandomPasswordNumberOfLetters   $gcv.NOVLBNNRPSWD.RandomPasswordNumberOfNumbers), $gcv.NOVLBNNRPSWD.RandomPasswordNumberOfLetters, $gcv.NOVLBNNRPSWD.RandomPasswordNumberOfNumbers)

That is, use the 4th version of the password generator ECMA (there are many in the library, different approaches over time for different use cases), and you tell it the sum of the random number of letters and random number count, then the random letter count, then the random number count. That is, total number of characters desired, then how many should be letters, and how many numbers.

What is interesting is they set destination password with this value, not the nspmDistributionPassword attribute.

Set initial password value from attribute if no Distribution Password available and GCV is set to attribute

If the setting GCV has been selected as 'attribute' then the value of that attribute is the password. Thus you could set the password as their Social Security number (udcTaxID) or perhaps as their student number? Whatever makes sense for your institution.

Generate Password from Universal Password Policy if no Distribution Password available and GCV is set to universal

The final option is if the control GCV is set to the value 'universal', in which case it looks at the Password Policy specified in the GCV gcv.NOVLBNNRPSWD.initialPasswordPolicy and uses that as the target of the Generate Password token.

Do take care, with the latest releases of eDirectory and IDM (eDir 8.8.8 and IDM 4.02) if you use this setting, in the choices you make in the password policy. NMAS which actually implements this call, (or put another way, this token calls an NMAS function) has an issue if there is no user in the context of the call (or the user does not yet exist, like our case) if the Password Policy requires Uniqueness or excludes attribute values. The issue is that history of course is dependant on the specific user as are attribute values.

It is very common to exclude Given Name, Surname, CN, and other such naming attributes from being allowed in a password. But if there is no target user to Generate the password for there is no way to evaluate the History, nor the attribute values. Now it seems like the proper thing to do here would to treat them as empty values, and thus no work to do and move on. Alas what actually happens is that NMAS throws an error and you get no password generated.

Therefore, in the password policy you target this against remember to avoid the user specific settings.

That about wraps up this policy and this policy set as well. Stay tuned for the next article where I will start on the Publisher Placement policy set.


How To-Best Practice
Comment List