Inside Activate
Identity & Access Manager
Checking Active Directory Field Uniqueness During Create User
11 min
when creating users in environments with multiple active directory domains or forests, it is often necessary to ensure that key directory attributes are unique across all target directories this article describes an approach for validating and generating unique values during the create user process in activate please note the script examples provided may need tweaking to work on later versions of activate, they are provided as is as guides or inspiration overview in multi domain or multi forest environments, user creation can fail or cause conflicts if attributes such as login names or email addresses already exist elsewhere to prevent this, activate can be configured to validate uniqueness across multiple directories before the user is created this approach collects multiple ou references across domains and forests uses a precreate script to build a directory collection calls custom utility methods to validate uniqueness automatically generates the next available value when conflicts are detected scenario this approach is suitable when users may be created in different domains or forests a single naming standard is enforced across the organisation attributes must be unique beyond the target ou the validation ous do not need to match the final user placement they are used solely for checking existing objects high level process configure ou references for each domain or forest to be checked collect those ous during the precreate phase pass the ou collection into custom utility methods validate uniqueness for common identity attributes configure ou references add a userou parameter to the create user task configure this parameter with ou references for every domain or forest that must be checked for existing users collect ous in the precreate script in the precreate script, load all configured userou values into a collection that can be passed to utility methods // load all ous to check foreach (parameter parameter in job task getlocalparameters("userou")) { oureference ouref = parameter valueobject as oureference; if (ouref != null && ouref ou != null) ous add(ouref ou); } generate a unique login name to generate a unique samaccountname across multiple domains, a namegenerator can be combined with a custom validation method public static string getnextuniqueloginname(job j, string loginname, provisioningdirectorycollection ous) { j logaudit("getnextuniqueloginname {0}", loginname); namegenerator g = new namegenerator(loginname, namegenerator validcharacters loginname); string result = null; for (int i = 0; i < 100; i++) { string s = g getnextusername(j) replace(" ", ""); j logtrace("s {0}", s); if (checkloginname(j, dsutilities escapefilterelement(s), ous)) continue; result = s; break; } if (result == null) throw new exception("unable to generate unique name"); return result; } this method iterates through generated values until a unique login name is found across all configured ous generate a unique upn and email address user principal name, email address, and alias values can be generated and validated together to ensure global uniqueness public static void getnextuniqueupnandmailname( job j, string emailupnexpression, string samaccountname, oudirectoryentry userou, provisioningdirectorycollection ous, out string email, out string upn, out string alias) { namegenerator e = new namegenerator(emailupnexpression, namegenerator validcharacters email); int i = 0; while (true) { i++; if (i > 20) throw new exception("unable to generate unique email or upn name"); string emailgen = e getuniqueupnandmailaddress(j, j arguments root, userou, null); if (isuniqueacrossdomains(j, samaccountname, emailgen, emailgen, ous)) { upn = emailgen; email = emailgen; alias = samaccountname; break; } } } validate uniqueness across domains each generated value is validated against every configured ou to ensure no conflicts exist public static bool isuniqueacrossdomains( job j, string samaccountname, string emailaddress, string upn, provisioningdirectorycollection ous) { foreach (oudirectoryentry outocheck in ous) { if (!isunique(j, samaccountname, emailaddress, upn, outocheck)) return false; } return true; } the underlying checks validate the following attributes samaccountname mailnickname mail userprincipalname proxyaddresses (smtp and sip) targetaddress import the utility class to make the utility methods available during user creation, import the class at the top of the precreate script //@import=//resources/custom/utilities/userutilities example namegenerator expressions the following examples show namegenerator expressions commonly used with this approach login name expression \<loginname>#data/lastname 6|data/firstname 1|{#}loginname> user principal name expression \<userprincipalname>#{data/firstname}\ an|" "|{data/lastname}\ an|{#}|"@%=/data/roles/type/defaultemaildomain%"userprincipalname> these expressions can be adjusted to align with organisational naming standards and domain structures