Native Change Detection-if someone adds a user to one of the group directly in AD, IIQ has to detect that and remove the added group membership

Which IIQ version are you inquiring about?

[SailPoint IIQ 8.3]

Share all details about your problem, including any error messages you may have received.

[if someone adds a user to one of the group directly in AD, IIQ has to detect that and remove the added group membership. How can we achieved it in IIQ? What will be the configurations and IIQ objects we need to achieve it?]

  1. Enable Native Change Detection option from App configuration. Based on your requirement you can choose “Entitlement” or “User Defined”.

  2. Create Life cycle event with “Native Change” event type and configure other option based on your requirement. (Ex: Update workflow to create a provisioning plan to revert the changes. In your case you can create a plan to remove a user from the group)

  1. Now Run full Account Aggregation to see the native change events on cube.

  2. Finally Run Identity Refresh task with “Process Events” enabled. This will trigger Native Change type event workflow.

1 Like

Hello @vedeepak , Thank you for reply. I am done all the setup as per your reply. Now I am trying with the workflow but not getting result for removing group membership. I am shareing the workflow.
import sailpoint.object.;
import sailpoint.api.
;

    System.out.println("***** Starting Group Removal Workflow Step *****");

    // Create a provisioning plan
    ProvisioningPlan plan = new ProvisioningPlan();
    plan.setIdentity(newIdentity);

    System.out.println(" Identity: " + newIdentity.getName());
    System.out.println(" Entitlement (group to remove): " + entitlement);
    System.out.println(" Application: " + applicationName);

    // Create the AccountRequest
    ProvisioningPlan.AccountRequest accountRequest = new ProvisioningPlan.AccountRequest();
    accountRequest.setApplication(applicationName);
    accountRequest.setOperation(ProvisioningPlan.AccountRequest.Operation.Remove);
    accountRequest.setNativeIdentity(newIdentity.getName());  

    // Create the EntitlementRequest to remove the group
    ProvisioningPlan.AttributeRequest entitlementRequest = new ProvisioningPlan.AttributeRequest(
    "memberOf", 
    ProvisioningPlan.Operation.Remove, 
    entitlement
    );

    // Add the entitlement to the account request
    accountRequest.add(entitlementRequest);
    plan.add(accountRequest);

    
    wfcontext.setVariable("plan", plan);

 
    System.out.println(plan.toXml());

    return plan;

you need compile and execute the plan to reflect the changes.

provisioningProject = provisioningPlan.compile();
provisioningProject.execute();

Hello @vedeepak , I have tried but not getting the expected result.

<?xml version='1.0' encoding='UTF-8'?> The name of the user whose group membership was changed natively The name of the application where the group membership was added (e.g., Active Directory) import sailpoint.object.Identity; import sailpoint.object.Link; import java.util.List;
    Identity identity = context.getObjectByName(Identity.class, identityName);
    if (identity != null) {
    List links = identity.getLinks();
    for (Link link : links) {
    if (applicationName.equals(link.getApplicationName())) {
    Object entitlement = link.getAttribute("entitlement");
    return entitlement;
    }
    }
    }
    return null;
  </Source>
</Script>
import sailpoint.object.*; import sailpoint.api.*;
    System.out.println("***** Starting Group Removal Workflow Step *****");

    if (identity == null || entitlement == null || applicationName == null) {
    System.out.println("Missing required variable(s). Workflow exiting.");
    return null;
    }

    // Create a provisioning plan
    ProvisioningPlan plan = new ProvisioningPlan();
    plan.setIdentity(identity);

    System.out.println(" Identity: " + identity.getName());
    System.out.println(" Entitlement (group to remove): " + entitlement);
    System.out.println(" Application: " + applicationName);

    // Create the AccountRequest
    ProvisioningPlan.AccountRequest accountRequest = new ProvisioningPlan.AccountRequest();
    accountRequest.setApplication(applicationName);
    accountRequest.setOperation(ProvisioningPlan.AccountRequest.Operation.Modify);
    accountRequest.setNativeIdentity(identity.getName());

    // Create the EntitlementRequest to remove the group
    ProvisioningPlan.AttributeRequest entitlementRequest = new ProvisioningPlan.AttributeRequest(
    "memberOf",
    ProvisioningPlan.Operation.Remove,
    entitlement
    );

    // Add the entitlement to the account request
    accountRequest.add(entitlementRequest);
    plan.add(accountRequest);

    // Set the plan as a workflow variable
    wfcontext.setVariable("plan", plan);

    System.out.println(plan.toXml());

    return plan;
  </Source>
</Script>
<Transition to="End"/>
This is the workflow xml & using this I hit the account aggregation followed by refresh identity cube task (both task is successful) but the entitlement which I have added directly in AD server is not removed(It is showing in IIQ).

After creating your plan, you can transition to below step by passing “plan” as an input argument and refer LCM Provisioning workflow. Below code is just your reference.

 <Step condition="script:( plan != null )" icon="Task" name="Provision Native Change Reversal" posX="881" posY="20">
    <Arg name="identityName" value="ref:identityName"/>
    <Arg name="identityDisplayName" value="ref:identityDisplayName"/>
    <Arg name="optimisticProvisioning" value="ref:optimisticProvisioning"/>
    <Arg name="plan" value="ref:plan"/>
    <Arg name="policyScheme" value="none"/>
    <Arg name="workItemPriority" value="ref:workItemPriority"/>
    <Arg name="approvalScheme" value="none"/>
    <Arg name="source" value="ref:source"/>
    <Arg name="requireViolationReviewComments" value="false"/>
    <Arg name="allowRequestsWithViolations" value="true"/>
    <Arg name="enableRetryRequest" value="false"/>
    <Arg name="launcher" value="ref:launcher"/>
    <Arg name="doRefresh" value="true"/>
    <Arg name="trace" value="ref:trace"/>
    <Return name="project" to="project"/>
    <WorkflowRef>
      <Reference class="sailpoint.object.Workflow" id="" name="LCM Provisioning"/>
    </WorkflowRef>
    <Transition to="end"/>
  </Step>

Hello @vedeepak , I have tried with this but not working. I tried few other thing in workflow still not working(entitlement is not removing). Sharing the workflow.
Initializing variable: trace
→ true
Starting workflow Group_Native_Change_Workflow
Variable initialized with launch input: launcher = Scheduler
Variable initialized with launch input: identityName = Shailaja.M
Initializing variable: applicationName
→ null
Initializing variable: identity
→ sailpoint.object.Identity@1332680e[id=ac140a02954b152681954c3279fc0238,name=Shailaja.M]
Initializing variable: entitlement
→ CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com
Initializing variable: nativeIdentity
→ null
Initial case variables:

<?xml version='1.0' encoding='UTF-8'?> CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com Normal User Account CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com top person organizationalPerson user

Starting step Start
Ending step Start
Starting step End
Ending step End
Ending workflow Group_Native_Change_Workflow
Initializing variable: trace
→ true
Starting workflow Group_Native_Change_Workflow
Variable initialized with launch input: launcher = Scheduler
Variable initialized with launch input: identityName = Shailaja.M
Initializing variable: applicationName
→ null
Initializing variable: identity
→ sailpoint.object.Identity@6215ffbd[id=ac140a02954b152681954c3279fc0238,name=Shailaja.M]
Initializing variable: entitlement
→ CN=Engineering-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com
Initial case variables:

<?xml version='1.0' encoding='UTF-8'?> CN=Engineering-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=Engineering-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com Normal User Account CN=Engineering-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com top person organizationalPerson user

Starting step Start
Ending step Start
Starting step End
Ending step End
Ending workflow Group_Native_Change_Workflow
Initializing variable: trace
→ true
Starting workflow Group_Native_Change_Workflow
Variable initialized with launch input: launcher = Scheduler
Variable initialized with launch input: identityName = Tanushri.G
Initializing variable: applicationName
→ null
Initializing variable: identity
→ sailpoint.object.Identity@4e3def95[id=ac140a0295641db781956539144101c4,name=Tanushri.G]
Initializing variable: entitlement
→ CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com
Initial case variables:

<?xml version='1.0' encoding='UTF-8'?> CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=joiner-contractors,OU=Groups,OU=Chetan,DC=test,DC=com Normal User Account CN=HR-Dept,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com CN=joiner-contractors,OU=Groups,OU=Chetan,DC=test,DC=com top person organizationalPerson user

Starting step Start
Ending step Start
Starting step End
Ending step End
Ending workflow Group_Native_Change_Workflow

There is a OOTB native workflow example Lifecycle Event - Manager Approval for all native changes . Please refer this workflow and make changes or else share your custom native change workflow by removing/ masking important information.

Hello @vedeepak , shareing the workflow with static entitlement value.
It is working (remove entitlement) for only static value. The requirement is like need to remove the entitlement form user which is recently added in AD sever directly.



The name of the application where the group membership was added (e.g., Active Directory)








import sailpoint.object.Identity;
import sailpoint.object.Link;
import java.util.List;

    String applicationName = "ACTIVE-DIRETORY-APPLICATION";
    String targetEntitlement = "CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com";  

    Identity identity = context.getObjectByName(Identity.class, identityName);

    if (identity != null) {
    List links = identity.getLinks();

    for (Link link : links) {
    if (applicationName.equals(link.getApplicationName())) {
    Object memberOfAttr = link.getAttribute("memberOf");

    if (memberOfAttr instanceof List) {
    List memberOfList = (List) memberOfAttr;

    for (Object group : memberOfList) {
    if (targetEntitlement.equals(group)) {
    System.out.println("Matched entitlement: " + group);
    return group;
    }
    }
    } else {
    if (targetEntitlement.equals(memberOfAttr)) {
    return memberOfAttr;
    }
    }
    }
    }
    }

    return null;

  </Source>
</Script>
import sailpoint.object.*; import sailpoint.api.*; import sailpoint.tools.GeneralException;
    System.out.println("***** Starting Group Removal Workflow Step *****");

    applicationName = "ACTIVE-DIRETORY-APPLICATION";

    if (identity == null || entitlement == null || applicationName == null) {
    System.out.println("Missing required variable(s). Workflow exiting.");
    return null;
    }

    ProvisioningPlan plan = new ProvisioningPlan();
    plan.setIdentity(identity);

    ProvisioningPlan.AccountRequest accountRequest = new ProvisioningPlan.AccountRequest();
    accountRequest.setApplication(applicationName);
    accountRequest.setOperation(ProvisioningPlan.AccountRequest.Operation.Modify);
    accountRequest.setNativeIdentity("CN=" + identityName + ",OU=FID_Account,OU=FID_DATA,DC=test,DC=com");

    ProvisioningPlan.AttributeRequest entitlementRequest = new ProvisioningPlan.AttributeRequest();
    entitlementRequest.setName("memberOf");
    entitlementRequest.setValue("CN=Accounting,OU=FID_Groups,OU=FID_DATA,DC=test,DC=com");     
    entitlementRequest.setOp(ProvisioningPlan.Operation.Remove);

    accountRequest.add(entitlementRequest);
    plan.add(accountRequest);

    wfcontext.setVariable("plan", plan);

    System.out.println("Provisioning plan created, submitting to Provisioner...");

    // Submit the plan to the Provisioner
    Provisioner provisioner = new Provisioner(context);
    ProvisioningResult result = provisioner.execute(plan);

    System.out.println("Provisioning result: " + result);

    return result;
  </Source>
</Script>
<Transition to="End"/>

Hi @Shalaka_Gawande ,

You should retrieve the entitlement from the NativeChangeEvent. Please refer the code blelow.


List groupList = new ArrayList();
List ncds = event.getNativeChanges();

if (ncds != null && !ncds.isEmpty()) {
    for (NativeChangeDetection ncd : ncds) {
        if ("ACTIVE-DIRECTORY-APPLICATION".equalsIgnoreCase(ncd.getApplicationName())) {
            List diffs = ncd.getDifferences();
            if (diffs != null @and !diffs.isEmpty()) {
                for (Difference diff : diffs) {
                    if ("memberOf".equals(diff.getAttribute())) {
                        List addedGroups = diff.getAddedValues();
                        if (addedGroups != null @and !addedGroups.isEmpty()) {
                            groupList.addAll(addedGroups);
                        }
                    }
                }
            }
        }
    }
}

ProvisioningPlan plan = new ProvisioningPlan();
plan.setIdentity(identity);

if (!groupList.isEmpty()) {
    ProvisioningPlan.AccountRequest accReq = new ProvisioningPlan.AccountRequest(
        ProvisioningPlan.AccountRequest.Operation.Modify,
        "ACTIVE-DIRECTORY-APPLICATION",
        null,
        identity.getName()
    );
    for (String group : groupList) {
        ProvisioningPlan.AttributeRequest attrReq = new ProvisioningPlan.AttributeRequest(
            "memberOf",
            ProvisioningPlan.Operation.Remove,
            group
        );
        accReq.add(attrReq);
    }
    plan.add(accReq);
}
   Provisioner provisioner = new Provisioner(context);
   provisioner.execute(plan);
   


1 Like

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