ProvisioningPlan not removing capabilities

Which IIQ version are you inquiring about?

8.3

I’m creating a provisioning plan that removes capabilities, but they are not being removed:

<!DOCTYPE ProvisioningPlan PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<ProvisioningPlan>
  <AccountRequest application="IIQ" nativeIdentity="bac66a80-165f-4d77-a6fb-1f81cf36acdb" op="Modify">
    <AttributeRequest name="capabilities" op="Remove" value="AlertAdministrator"/>
    <AttributeRequest name="capabilities" op="Remove" value="Application_SME"/>
    <AttributeRequest name="capabilities" op="Remove" value="capabiltytest"/>
  </AccountRequest>
  <Attributes>
    <Map>
      <entry key="identityRequestId" value="0000023762"/>
      <entry key="requester" value="admin"/>
      <entry key="source" value="RapidSetup"/>
    </Map>
  </Attributes>
  <Requesters>
    <Reference class="sailpoint.object.Identity" id="28ec05305d7ad73d015d7ad7b30f0022" name="admin"/>
  </Requesters>
</ProvisioningPlan>

Here is the code:

          Identity id = plan.getIdentity();
          List capabilities = id.getCapabilities();

          if (capabilities != null) 
          {
            log.debug("Removing Capabilities found: " + capabilities.size());

            if (!capabilities.isEmpty()) {
              AccountRequest request = new AccountRequest(AccountRequest.Operation.Modify, "IIQ", null, id.getName());
              List capabilityNames = new ArrayList();
              for (Capability capability : identity.getCapabilities()) {
                request.add(new AttributeRequest("capabilities", ProvisioningPlan.Operation.Remove, capability.getName()));
                log.debug("Removing: " + capability.getName());
              }
              request.add(new AttributeRequest("capabilities", ProvisioningPlan.Operation.Remove, capabilityNames));
              plan.add(request);
            }
          }

provisioning plan with op="Remove" won’t update the Identity’s capabilities because IIQ doesn’t treat them as account entitlements ,they’re managed directly on the Identity.

Hi @AJGibson76 here is a snippet that shows removing the capabilities, you can adjust it as needed.

Identity id = context.getObjectByName(Identity.class, “User123”);
List cap = id.getCapabilities();
if(cap !=null && !cap.isEmpty()) {
for (Capability c :cap) {

  id.remove(c);

}
}
context.saveObject(id);
context.commitTransaction();

Hi @AJGibson76

Capabilities in SailPoint IIQ are not entitlements – they are attributes stored directly on the Identity object.
Because of this, a ProvisioningPlan with op="Remove" will not update/remove them in IIQ.

To remove capabilities, we need to update the Identity object directly. The below code you can try and adjust in your workflow or any adhoc rule based on your requirement.

import sailpoint.object.Identity;

// Get identity
Identity identity = context.getObjectByName(Identity.class, "jdoe");

if (identity != null) {
    // Remove all capabilities
    identity.setCapabilities(null);

    // OR remove a specific one
    // identity.remove("<capabilityObject>");

    context.saveObject(identity);
    context.commitTransaction();
    log.debug("Capabilities updated for: " + identity.getName());
}

  • identity.setCapabilities(null) → It clears all capabilities
4 Likes

I tried this:

        Identity id = plan.getIdentity();
        List capabilities = id.getCapabilities();

        if (id.getCapabilities() != null) 
        {
          log.debug("Removing Capabilities found: " + capabilities.size());
          log.debug("Removing Capabilities: " + capabilities.toString());

            for (Capability cap : capabilities) 
            {
              log.debug("Removing Capability: " + cap.getName());
              id.remove(cap);
              context.saveObject(id);
              context.commitTransaction();
              log.debug("Removed Capability: " + cap.getName());
            }
        }

and I ended up getting a weird error:

2025-09-23 10:16:49,597 DEBUG Thread-208 CIBC_Rapid_Setup_Leaver:-1 - Entering Remove Capabilities Step
2025-09-23 10:16:49,598 DEBUG Thread-208 CIBC_Rapid_Setup_Leaver:-1 - Removing Capabilities found: 1
2025-09-23 10:16:49,598 DEBUG Thread-208 CIBC_Rapid_Setup_Leaver:-1 - Removing Capabilities: [sailpoint.object.Capability@7e54a91b[id=28ec05305d7ab722015d7abb320a00e9,name=capabiltytest]]
2025-09-23 10:16:49,601 DEBUG Thread-208 CIBC_Rapid_Setup_Leaver:-1 - Removing Capability: capabiltytest
2025-09-23 10:16:49,648 DEBUG Thread-208 CIBC_Rapid_Setup_Leaver:-1 - Removed Capability: capabiltytest
2025-09-23 10:16:49,648 ERROR Thread-208 org.apache.bsf.BSFManager:451 - Exception:
java.security.PrivilegedActionException: null
        at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_51]
        at org.apache.bsf.BSFManager.eval(BSFManager.java:442) [bsf.jar:?]
        at sailpoint.server.BSFRuleRunner.runScript(BSFRuleRunner.java:347) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.server.InternalContext.runScript(InternalContext.java:1296) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.server.ScriptletEvaluator.doScript(ScriptletEvaluator.java:263) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.server.ScriptletEvaluator.evalSource(ScriptletEvaluator.java:71) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.evalSource(Workflower.java:5932) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.advanceStep(Workflower.java:5171) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.advance(Workflower.java:4558) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.startCase(Workflower.java:3144) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.launchInner(Workflower.java:2813) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.launch(Workflower.java:2666) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.api.Workflower.launch(Workflower.java:2500) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.request.WorkflowRequestExecutor.execute(WorkflowRequestExecutor.java:177) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
        at sailpoint.request.RequestHandler.run(RequestHandler.java:163) [identityiq.jar:8.3p3 Build d5deab2519b-20230629-092050]
Caused by: org.apache.bsf.BSFException: BeanShell script error: bsh.EvalError: Sourced file: inline evaluation of: ``import org.apache.log4j.Logger;          import sailpoint.object.Capability;     . . . '' unknown error: null : at Line: 12 : in file: inline evaluation of: ``import org.apache.log4j.Logger;          import sailpoint.object.Capability;     . . . '' : if ( id .getCapabilities ( ) != null ) {
 BSF info: script at line: 0 column: columnNo

The code executes, and then I get an error about id.getCapabilities() not being decypherable AFTER the code is complete. If I remove the null check, the code works (unless capabilities is null). If I have multiple capabilities, only the first is removed. A try block resulted in the error being on the try. I tried setCapabilities(null) and that errored as well. Any thoughts?

@AJGibson76 In this code , you are doing a commitTransaction in a for loop that is not recommended. In this case, only the first object will get removed and gives you a null pointer after that. Instead use the below code.

        Identity id = plan.getIdentity();
        List capabilities = id.getCapabilities();

        if (id.getCapabilities() != null) 
        {
          log.debug("Removing Capabilities found: " + capabilities.size());
          log.debug("Removing Capabilities: " + capabilities.toString());

            for (Capability cap : capabilities) 
            {
              log.debug("Removing Capability: " + cap.getName());
              id.remove(cap);
              context.saveObject(id);
              log.debug("Removed Capability: " + cap.getName());
            }
          context.commitTransaction();
        }
2 Likes

So the commit makes the list null? If so, why am I not getting a null pointer error? I’m getting the message I normally get when the code can not be parsed. Also, I get the error even when there is only one object in the list (I get the for loop accesses it?)

At id.gatcapalblities can you check for list empty and then check

commitTransaction() method is not recommended to use in a loop. Use only saveObject(id) method inside the for loop.

Once your loop ends, then do the commitTransaction().

Read this article to have some more idea about not to use commitTransaction in any kind of looping statements.

https://community.sailpoint.com/t5/IdentityIQ-Articles/IdentityIQ-8-0-and-commitTransaction-while-using-an-iterator/ta-p/143225

1 Like

The reason this is not work is because you are looping over a list and removing items from that list at the same time.

You can’t do that in java.

I understand that intension of this code is to remove ALL capabilities, is that so?

To do that you can just

identity.getCapabilities().clear();
context.saveObject(identity);
context.commitTransaction();

If you only want to remove some of the capabilities you need to get the list of their names and run something like this:

for(String capabilityName : capabilitiesName) {
  Capability capability = context.getObjectByName(Capability.class, apabilityName);
  if (capability != null) {
    identity.remove(capability);
  }
}
context.saveObject(identity);
context.commitTransaction();

The original code was:

List capabilities = id.getCapabilities()
if (capabilities != null) {
for(Capability cap : capabilities) {

setCapabilities(null) works inside a try a block, so I’m good now, thank you.

1 Like

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