Remove identity's manager via workflow

We have a number of out-of-band identities that come into IIQ as joiners from our HR system, but the associate never starts work. HR doesn’t consider this a termination, but a rescinded offer. Thus there is no leaver event.

Since the identities came in through the HR system with a manager and then are pulled without ever clearing that manager, we end up with bad identities in the system that have managers, and thus get included in org charts (fed from IIQ to AD) as well certifications (just all-associate birthright stuff, but still, access is access).

While there is a larger effort to actually cleanup these identities, that project is moving very slowly due to data retention policies. In the meantime, I have created a policy violation that detects users who are termed, but still have a manager. I’m trying to figure out how to handle removing the manager attribute on the identity cube.

My approach was creating an accountRequest for the IIQ application and sending an attributeRequest along these lines:

            AttReq.setName("manager");
            AttReq.setOperation(ProvisioningPlan.Operation.Remove);
            AttReq.setValue();
            accRequest.add(AttReq);

However, I’m not sure how to set this. From what I can tell, manager appears to be a unique attribute in that it’s not a part of the <attributes> map, but it’s own object on the identity?

I’m not sure if I should be doing this on the accountRequest at all. I searched compass and Dev community, but this seems like an uncommon situation.

Rather than Remove, use “Set”, and pass a value of null.

When you use the Provisioner to make Identity updates, it doesn’t matter how they’re actually stored on the Identity itself. The Provisioner has special code to handle all of those sub-objects like Manager.

You can even do stuff that wouldn’t normally be possible, like provisioning detectedRoles (and their entitlements) directly, via the Provisioner.

1 Like

Thanks for the tip! I’m still having trouble getting it to actually remove the manager. There shouldn’t be any kind of identity refresh after the policy violation, right? The policy refresh should be enough?

I’ve tried all three of these variations:

AttReq.setName("manager");
            AttReq.setOperation(ProvisioningPlan.Operation.Set);
            AttReq.setValue(null);
            accRequest.add(AttReq);

AttReq.setName("manager");
            AttReq.setOperation(ProvisioningPlan.Operation.Set);
            AttReq.setValue("");
            accRequest.add(AttReq);

AttReq.setName("manager");
            AttReq.setOperation(ProvisioningPlan.Operation.Set);
            AttReq.setValue();
            accRequest.add(AttReq);

None of these throw any kind of errors, but none remove the managers. I’ve confirmed that the policy correctly fires for all the testing users; I can see the policy violations come through with their correct descriptions and everything. Also confirmed the rule is not disabled. But no changes to the manager attribute. No provisioningTransactions either, which I would expect from an accountRequest in a provisioningPlan (right?).

 <Script>
      <Source>
			import sailpoint.object.ProvisioningPlan;
			import sailpoint.object.ProvisioningPlan.AccountRequest;
			import sailpoint.object.ProvisioningPlan.AccountRequest.Operation;
			import sailpoint.object.ProvisioningPlan.AttributeRequest;
			import sailpoint.object.Identity;
			import sailpoint.api.IdentityService;
			import sailpoint.tools.Util;
			import sailpoint.tools.GeneralException;
			import sailpoint.object.Link;
			import sailpoint.object.Application;
			import org.apache.log4j.Logger;
        
			Logger log = Logger.getLogger("Workflow_TermedUserWithManagerPolicyViolation");

            if (log.isDebugEnabled()){
                log.debug("Building plan to remove manager");
            }
				
			Identity cubeName = wfcontext.getVariable("violationIdentity");
			if (log.isDebugEnabled()){
                log.debug("Identity cube to process: " + cubeName);
            }

			IdentityService iS = new IdentityService(context);
			
			ProvisioningPlan plan = new ProvisioningPlan();
            plan.setIdentity(cubeName);
            
            ProvisioningPlan.AccountRequest accRequest = new ProvisioningPlan.AccountRequest();
            accRequest.setApplication("IIQ");
			if (log.isDebugEnabled()){
                log.debug("Created AccountRequest object");
            }
            
            ProvisioningPlan.AttributeRequest AttReq = new ProvisioningPlan.AttributeRequest();
			if (log.isDebugEnabled()){
                log.debug("Created AttributeRequest object");
            }
            AttReq.setName("manager");
            AttReq.setOperation(ProvisioningPlan.Operation.Set);
            AttReq.setValue(null);
            accRequest.add(AttReq);
			if (log.isDebugEnabled()){
                log.debug("Added AttributeRequest to AccountRequest");
            }
			
			wfcontext.setVariable("identityName",cubeName.getName());
			
			return plan;
			
		</Source>
    </Script>

I tried doing
AttReq.setName(“Manager”)
instead of “manager” (lowercase). No difference.

It doesn’t appear that you’re ever adding your IIQ AccountRequest to the plan…

I assume you are also actually provisioning this plan, either via workflow library in a later step or manually via the Provisioner?

It’s in a policy violation business workflow, so the plan gets passed to the OOTB LCM Provisioning workflow from here.

I missed the adding the AccountRequest to the plan, but that doesn’t seem to be making a difference. I’m going to add some debugging to print out the provisioning plan right before that step ends.

Eventually got this working with the following code.

      if (log.isDebugEnabled()){
        log.debug("Building plan to remove manager");
      }

      // Get termed identity cube from the violation
      Identity cubeName = wfcontext.getVariable("violationIdentity");
      if (log.isDebugEnabled()){
        log.debug("Identity cube to process: " + cubeName);
      }

      // Create a new ProvisioningPlan for the identity
      IdentityService iS = new IdentityService(context);
      ProvisioningPlan plan = new ProvisioningPlan();
      plan.setIdentity(cubeName);
      if (log.isDebugEnabled()){
        log.debug("Created ProvisioningPlan object");
      }

      // Create a new AccountRequest on the IIQ application
      ProvisioningPlan.AccountRequest accRequest = new ProvisioningPlan.AccountRequest();
      accRequest.setApplication("IIQ");
      accRequest.setNativeIdentity(identityName);
      if (log.isDebugEnabled()){
        log.debug("Created AccountRequest object");
      }
      
      // Create a new Attribute Request to set the manager value to null
      ProvisioningPlan.AttributeRequest AttReq = new ProvisioningPlan.AttributeRequest();
      if (log.isDebugEnabled()){
        log.debug("Created AttributeRequest object");
      }
      AttReq.setName("manager");
      AttReq.setOperation(ProvisioningPlan.Operation.Set);
      AttReq.setValue(null);

      // Add the AttributeRequest to the AccountRequest, and the AccountRequest to the ProvisioningPlan
      accRequest.add(AttReq);
      plan.add(accRequest);
      if (log.isDebugEnabled()){
        log.debug("Final ProvisioningPlan: " + plan.toMap());
      }

      wfcontext.setVariable("identityName",cubeName.getName());
      return plan;
1 Like

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