Provisioning Random sAMAccountName Value

Sometimes the customer requirements are very interesting, such as generating random attribute values. In this case I will show you how midPoint can generate random sAMAccountName attribute value for Microsoft Active Directory (AD) account provisioning.

Although you can let the Active Directory to generate sAMAccountName just by omitting any value when creating a new account, the generated values are very strange, for example: $123483748502-5678. Could midPoint generate anything smarter such as “jsm12345” for “John Smith” user? With random suffix (12345) for collission?

Certainly!

We need two configuration settings in the resource (AD):

  1. sAMAccountName attribute schema handling section (to build the required string)
  2. iteration configuration (to generate the random suffix)

Let’s start with the attribute. First, define the naming convention:

  • use first letter from the Given Name attribute
  • use two first letters from the Family Name attribute
  • never update the value (even if the user name(s) change)
  • append 5 random digits

You may (and should) ask, what if the user’s Given/Family name value is shorter than the number of characters specified? Good question, we should be aware of this possibility even if in my own country (Slovakia) such names are very, very rade. So let’s re-define the conditions as:

  • use up to one character from the beginning of the Given Name attribute
  • use up to two characters from the beginning of the Family Name attribute
  • never update the value (even if the user name(s) change)
  • append 5 random digits

Now we are all set, let’s go. The attribute is defined in the resource schemaHandling:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<schemaHandling>
    <objectType>
        <kind>account</kind>
        <intent>default</intent>
        <displayName>Default Account</displayName>
        <default>true</default>
        <objectClass>ri:AccountObjectClass</objectClass>
. . .
        <attribute>
            <ref>ri:sAMAccountName</ref>
            <displayName>Login name</displayName>
            <matchingRule>mr:stringIgnoreCase</matchingRule>
            <outbound>
                <strength>weak</strength><!-- Do NOT update the value -->
                <source>
                    <path>$user/givenName</path>
                </source>
                <source>
                    <path>$user/familyName</path>
                </source>
                <expression>
                    <script>
                        <code>
                        tmpFamilyName = basic.norm(basic.stringify(familyName))
                        tmpGivenName  = basic.norm(basic.stringify(givenName))
                        familyNameUpToNCharacters = tmpFamilyName?.substring(0, Math.min(tmpFamilyName?.length(), 2));
                        givenNameUpToNCharacters = tmpGivenName?.substring(0, Math.min(tmpGivenName?.length(), 1));
                        return givenNameUpToNCharacters + familyNameUpToNCharacters + iterationToken
                        </code>
                    </script>
                </expression>
            </outbound>
        </attribute>
. . .
    </objectType>
</schemaHandling>

Now this was very simple, just by using midPoint samples and perhaps Google for the “up to N characters” hack (just as I did).

The second step is the configuration of the iterator. You can read about it here and here. The thing to know is: the iterator does not have to be sequential. It can be defined using any possible expression. So let’s try to generate 5-digit random integer number (00000-99999) here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<iteration>
    <maxIterations>99999</maxIterations>
    <tokenExpression>
        <script>
            <code><!-- Always generate random number suffix! -->
            rnd = new Random().nextInt(99999) + 1
            return sprintf("{1acb01afcc33953bed28d92be9d735e579722d77ac7936fdfc467b8d28505288}05d", rnd)
            </code>
        </script>
    </tokenExpression>
    <postIterationCondition>
        <variable>
            <name>login</name>
            <path>$shadow/attributes/ri:sAMAccountName</path>
        </variable>
        <script>
            <code>
            tmpUniqueLogin = midpoint.isUniqueAccountValue(resource, shadow, 'sAMAccountName', login)
            return tmpUniqueLogin
            </code>
        </script>
    </postIterationCondition>
</iteration>

From now on, midPoint will generate the sAMAccountName attribute for any new (notice the strength:weak) AD accounts similar to our “jsm12345″ example and it will make sure the value is unique.

Leave a Reply

Your email address will not be published.