Ensuring DN Uniqueness moving AD Accounts using AC_NewParent

Hi all,

We are currently doing some AD OU moves using a ConnectorAfterModify rule, which we’re aware isn’t a recommended practice over using a beforeProvisioning rule. What I have been unable to find so far is how people are managing to handle uniqueness checks for these rules, as the documentation doesn’t provide any.

Is there anyone out there utilizing AD OU moves using AC_NewParent that also has a uniqueness check? I’d love some help with this.

1 Like

Great question and honestly I’ve never had a client do a uniqueness check and instead opted for just moving the account by changing the OU. I’ve also never heard of a client with collisions doing this, but it’s definitely possible.

I think the other question is - “What does the error condition look like if you can detect it?” You’re already in provisioning so it’s hard to “fail gracefully” at this point.

Hi @mcheek

We are using Before Provisioning Rule for this Purpose.

If you don’t want to use BP Rule then

  1. may be we can build some uniqueness around cn attribute in AD.
  2. It is better to use Connector Before Modify Rule, if you use Connector After Modify Rule it will fail if duplicate found rite. You can use PowerShell script to query AD for uniqueness.

Looking forward for the working solution here without cloud Rules.


We are currently using a connector after modify rule to move the accounts to the other OU. The powershell script it runs handle the uniqueness check and currently appends a number to the end of the CN if there’s a conflict

The reason I wanted to move to using the cloud rule like the article (and support) recommends is sometimes IdN “loses track” of the account after the move and an identity refresh happens. If there hasn’t been an aggregation since the account moved, the role calculation will try and provision access, creating a new account in the process.

In a recent implementation, my team started with the SailPoint Services Standard Before Provisioning Rule and updated the “moveADAccount” method to add a uniqueness check that just adds incrementing numbers to the CN:

    public void moveADAccount(Identity identity, AccountRequest accountRequest, Object value) {
        log.debug("Enter MoveADAccount: " + value);
        if(accountRequest == null) {
            log.error("MoveADAccount: Invalid Arguments: accountRequest is null");
        if(value instanceof String) {
            log.debug("MoveADAccount: value is a string, send through replace");
            String newOU = replaceIdentityValue(identity, accountRequest, (String) value);
            log.info("MoveADAccount: replaced new value: " + newOU);
            String currentNativeIdentity = accountRequest.getNativeIdentity();
            if(currentNativeIdentity == null) {
                log.error("moveADAccount: Invalid State: Current Native Identity is null");
            if(newOU == null || "".equals(newOU)) {
                log.error("moveADAccount: Invalid Arguments: newOU is null");
            int indexOfCurrentOU = currentNativeIdentity.indexOf(newOU);
            if(indexOfCurrentOU > 0 && !currentNativeIdentity.substring(0, indexOfCurrentOU).contains("OU=")) {
                log.info("moveADAccount: Account already lives in OU");
            //TODO: Uniqueness checks and serialization
			//************    Customer SPECIFIC CODE - BEGIN    ************
			//apply unique check and collision logic for CN
			String appName = accountRequest.getApplicationName();
			String origCN = currentNativeIdentity.substring(3, (currentNativeIdentity.indexOf(",")));
			String baseCN = origCN.replaceAll("\\\\d","");
			String newCN = baseCN;
			String newDN;

			log.info("Customer standard BP Rule: starting Customer custom code to handle CN collision for application: " + appName);
			boolean userExists = true;
			int maxUniqueCheck = 20;   //run thru 20 iterations which is probably overkill
			int i;
			for (i=1; i < maxUniqueCheck; i++){
				log.info("Customer standard BP Rule: check for uniquenss of CN value in new OU: " + newCN);
				newDN = "CN=".concat(newCN).concat(",").concat(newOU); 
				if(!(idn.accountExistsByNativeIdentity(appName, newDN))) {
					log.info("Customer standard BP Rule: CN is unique in new OU, now need to determine if it is necessary to call AC_NewName");
					userExists = false;
				newCN = baseCN.concat(String.valueOf(i));
				log.error("Customer standard BP Rule: moveADAccount: Unique CN could not be derived");
			if (!origCN.equals(newCN)) {
				newCN = "CN=".concat(newCN);
				log.info("Customer standard BP Rule: AC_NewName will be executed using: " + newCN); 
				accountRequest.add(new AttributeRequest("AC_NewName", ProvisioningPlan.Operation.Set, newCN));
				log.info("Customer standard BP Rule: adding AttributeRequest to execute AC_NewName, resulting DN will be: " + newDN);
			//************    Customer SPECIFIC CODE - END    **************
            accountRequest.add(new AttributeRequest("AC_NewParent", ProvisioningPlan.Operation.Set, newOU));
            log.error("MoveADAccount: value is not a string or is null: " + value);
        log.debug("Exit MoveADAccount");

Thanks, Kevin! Very much appreciate the example

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.