Monday, December 6, 2021

Sailpoint IdentityIQ Database Multiplex Application Configuration

Sailpoint IdentityIQ Database Multiplex Application Configuration

APPLICATION --> ACCESS_NAME --> ACCOUNTS

Group Query : SELECT DISTINCT APPLICATION_ID,APPLICATION,ACCESS_ID,ACCESS_NAME,ACCESS_DESCRIPTION from VIS_APPLICATION order by ACCESS_NAME ASC

Account Query : SELECT IDENTIFICATION, USER_TYPE, NAME, LASTNAME, STATUS,EMAIL,APPLICATION,ACCESS_NAME FROM VIS_USER order by EMAIL ,APPLICATION,ACCESS_NAME













































JDBCBuildMap / Build Map Rule

        import java.util.Map;     
        import sailpoint.connector.*;
	import sailpoint.object.Application;
	import org.apache.commons.logging.Log;
	import org.apache.commons.logging.LogFactory;
	import sailpoint.api.SailPointContext;
	
     Map map = JDBCConnector.buildMapFromResultSet(result, schema);  
     if (schema.getObjectType().compareTo(Connector.TYPE_ACCOUNT) == 0) {                   
		String applName = (String) map.get("APPLICATION");    
		String mergeAttribute = (String) map.get("EMAIL") + "_VIS " + applName;     
		map.put( "IIQSourceApplication","VIS" + applName);     
		map.put("mergeAttribute",mergeAttribute);		
     }else if (schema.getObjectType().compareTo(Connector.TYPE_GROUP) == 0) {
		String applName = (String) map.get("APPLICATION"); 	   
		String profilemergeAttribute = (String) map.get("ACCESS_NAME") + "_VIS " + applName;   	   
		map.put( "IIQSourceApplication","VIS" + applName);     
		map.put("profilemergeAttribute",profilemergeAttribute);
    }    
    return map;

ResourceObjectCustomization/Customization Rule

        import org.apache.commons.logging.Log;
	import org.apache.commons.logging.LogFactory;
	import sailpoint.api.SailPointContext;
	import sailpoint.object.Configuration;
	import sailpoint.object.ResourceObject;
	import sailpoint.tools.GeneralException;
		
	ResourceObject resourceObject = object;	
	String APP_STATUS_ATTRIBUTE = "STATUS";
	List ACTIVE_STATUS_LIST = new ArrayList( Arrays.asList("ENABLED", "Enabled", "enabled", "ENABLE", "Enable", "enable", "ACTIVE", "Active", "active") );
	String accountStatus = null;	
	if ("account".equals(object.getObjectType())) {	
		accountStatus = object.getAttribute(APP_STATUS_ATTRIBUTE);		
		if(ACTIVE_STATUS_LIST.contains(accountStatus) ){			
			resourceObject.setAttribute("IIQDisabled", false);			
		}else{			
			resourceObject.setAttribute("IIQDisabled", true);			
		}		
	}
	return resourceObject;

Thursday, November 18, 2021

Sailpoint IdentityIQ Tomcat Upgrade

Sailpoint IdentityIQ Tomcat Upgrade (9.0.54) version

Upgrade Steps

  1. Stop  tomcat services on each node
  2. <copy the installer in tmp directory from local machine>
  3. cd /tmp
  4. cp apache-tomcat-9.0.54.zip /apps
  5. cd /apps
  6. unzip apache-tomcat-9.0.54.zip
  7. rm -rf apache-tomcat-9.0.54.zip
  8. chmod 777 -R apache-tomcat-9.0.54
  9. mv tomcat bkp_apache-tomcat-8.5.34
  10. mv apache-tomcat-9.0.54 tomcat
  11. chmod 777 -R tomcat
  12. cd /apps/bkp_apache-tomcat-8.5.34/bin
  13. cp setenv.sh /apps/tomcat/bin
  14. cd /apps/bkp_apache-tomcat-8.5.34/conf
  15. cp tomcat-users.xml server.xml /apps/tomcat/conf
  16. cp -R Catalina/ /apps/tomcat/conf
  17. cd /apps/tomcat/conf
  18. chmod 777 -R Catalina/

IIQ Application setup

  1. cd /apps/tomcat/webapps
  2. rm -rf examples docs
  3. cd /apps/bkp_apache-tomcat-8.5.34/webapps
  4. cp -R identityiq /apps/tomcat/webapps
  5. cd /apps/tomcat/webapps
  6. chmod 777 -R identityiq/

Repeat the all the above steps on each server.

Monday, November 15, 2021

Performance Tuning for Application Server Apache Tomcat for Sailpoint IdentityIQ

 Performance Tuning for Application  Server Apache Tomcat  for Sailpoint IdentityIQ

1. UI Server

Create a file with name setenv.sh inside /tomcat/bin Directory

# Begin settings to support SailPoint IdentityIQ application.
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx4096m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxGCPauseMillis=200"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC"

# Support time-out of LDAP pooled connections for 3 seconds to all LDAP servers.  
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.jndi.ldap.connect.pool.timeout=3000"  
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.jndi.ldap.connect.pool.protocol='plain ssl'"  
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.jndi.ldap.connect.pool.authentication='none simple DIGEST-MD5'"  

export CATALINA_OUT=/logs/tomcat/catalina.out
# -End- settings to support SailPoint IdentityIQ application.  

export JAVA_OPTS="$JAVA_OPTS -Dhttp.proxyHost=<proxy server>"
export JAVA_OPTS="$JAVA_OPTS -Dhttp.proxyPort=<port>"
export JAVA_OPTS="$JAVA_OPTS -Dhttp.nonProxyHosts=*.company.com\|abcd"

Comment the below line from tomcat/conf/server.xml file

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"  maxThreads="512"/>

Perform below steps for rewrite URL

Add line - <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" /> in server.xml

/apps/tomcat/conf/Catalina/localhost/rewrite.config 
RewriteCond %{HTTP_HOST}  ^abcd.*
RewriteRule ^/$ /identityiq

2. Task Server

Create a file with name setenv.sh inside /tomcat/bin Directory

# Begin settings to support SailPoint IdentityIQ application.
export CATALINA_OPTS="$CATALINA_OPTS -Xms1024m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx6144m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseParallelGC"

# Support time-out of LDAP pooled connections for 3 seconds to all LDAP servers.  
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.jndi.ldap.connect.pool.timeout=3000"  
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.jndi.ldap.connect.pool.protocol='plain ssl'"  
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.jndi.ldap.connect.pool.authentication='none simple DIGEST-MD5'"  

export CATALINA_OUT=/logs/tomcat/catalina.out
# -End- settings to support SailPoint IdentityIQ application.

export JAVA_OPTS="$JAVA_OPTS -Dhttp.proxyHost=<proxy server>"
export JAVA_OPTS="$JAVA_OPTS -Dhttp.proxyPort=<port>"
export JAVA_OPTS="$JAVA_OPTS -Dhttp.nonProxyHosts=*.company.com\|abcd"

3. All Server

Remove docs and examples directory from /apps/tomcat/webapps

Set tomcat/conf/tomcat-users.xml with proper username and password

Create Directory /logs/tomcat

Tuesday, October 19, 2021

Sailpoint IdentityIQ Database Performance Tests

Sailpoint IdentityIQ Database Performance Tests

Rule is Available in Community Site "https://community.sailpoint.com/t5/Other-Documents/IdentityIQ-Database-Performance-Tests/ta-p/78060"

Just Rule need to be Imported and can be Run using the debug Page/ Console/Rule Runner Task

2021-10-19 15:27:40,886 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - IdentityIQ Database Performance Test starting

2021-10-19 15:27:40,886 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - IdentityIQ Version: 7.3p3 6a66e78-20190718-230225

2021-10-19 15:27:40,887 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - DB Performance Test Rule version: 20190827

2021-10-19 15:27:40,887 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Executed from Host: XXXX.vishal.com

2021-10-19 15:27:40,887 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Executed on Date: 2021-10-19 15:27:40.864

2021-10-19 15:27:40,887 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Populating 1k, 4k, 8k data set HashMaps for 1000 records...

2021-10-19 15:28:16,134 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Data set HashMaps populated.

2021-10-19 15:28:16,135 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Testing 1k data set...

2021-10-19 15:28:19,814 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Completed 1k data set.

2021-10-19 15:28:19,815 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Testing 4k data set...

2021-10-19 15:28:26,533 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Completed 4k data set.

2021-10-19 15:28:26,534 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Testing 8k data set...

2021-10-19 15:28:36,435 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Completed 8k data set.

2021-10-19 15:28:36,466 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Meter Summary:

Meter Generate-IIQDB-Test-DataSets: 1 calls, 35246 milliseconds, 35246 minimum, 35246 maximum, 35246 average, top five [35246]

Meter IIQDB-Test-DataSet-1k-All: 1 calls, 3663 milliseconds, 3663 minimum, 3663 maximum, 3663 average, top five [3663]

Meter IIQDB-Test-DataSet-1k-Item: 1000 calls, 3647 milliseconds, 1 minimum, 343 maximum, 3 average, top five [343,95,63,14,13]

Meter IIQDB-Test-DataSet-4k-All: 1 calls, 6718 milliseconds, 6718 minimum, 6718 maximum, 6718 average, top five [6718]

Meter IIQDB-Test-DataSet-4k-Item: 1000 calls, 6694 milliseconds, 4 minimum, 82 maximum, 6 average, top five [82,76,67,25,22]

Meter IIQDB-Test-DataSet-8k-All: 1 calls, 9901 milliseconds, 9901 minimum, 9901 maximum, 9901 average, top five [9901]

Meter IIQDB-Test-DataSet-8k-Item: 1000 calls, 9882 milliseconds, 7 minimum, 126 maximum, 9 average, top five [126,109,70,31,30]

Meter getConnection: 0 calls, 0 milliseconds, -1 minimum, 0 maximum, 0 average, top five ]



2021-10-19 15:28:36,467 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Cleaning up test objects in the database...

2021-10-19 15:28:52,430 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - Completed cleanup of DB Performance Test records: 15960 milliseconds.


2021-10-19 15:28:52,431 DEBUG http-nio-8080-exec-2 com.sailpoint.IIQDBPerformanceTest:? - IdentityIQ Database Performance Test done

Above is the Output from the IIQ Logs , based on the Sailpoint Recommendation if the values lies below set Database and IIQ connectivity is good

1k - 9 milliseconds

4k - 17 milliseconds

8k - 20 milliseconds

 

Tuesday, October 12, 2021

Sailpoint IdentityIQ Group Aggregation Refresh Rule

Sailpoint IdentityIQ Group Aggregation Refresh Rule/GroupAggregationRefresh is used to set the value for the Entitlement from Target to the Entitlement Catalogue . Code is modified to take care of the update scenario also. 

	import sailpoint.object.ResourceObject;
	import sailpoint.object.ManagedAttribute;
	import sailpoint.object.Identity;

	int TIME_DIFFERENCE = 300000; // Five minutes
	
	Date modifiedDate = accountGroup.getModified();
	Date createdDate = accountGroup.getCreated();
	boolean entitlementCreated = false;
	
	if(createdDate!=null){
		
		if(modifiedDate != null){
			
			long difference = modifiedDate.getTime() - createdDate.getTime();
			if(difference <= TIME_DIFFERENCE){			
				entitlementCreated = true;				
			}
		} else {			
			entitlementCreated = true;
		}	
	} else {
	}
	if(entitlementCreated){
		Map descMap = new HashMap();
		String descriptionValue = accountGroup.getAttribute("description");
		
		if(null != descriptionValue)
			descMap.put("en_US",descriptionValue);
		else
			descMap.put("en_US","");
		accountGroup.setAttribute("sysDescriptions",descMap);	
	}
	
	Map descMap = new HashMap();
	String descriptionValue = accountGroup.getAttribute("description");
	
	if(null != descriptionValue)
		descMap.put("en_US",descriptionValue);
	else
		descMap.put("en_US","");
	
	accountGroup.setAttribute("sysDescriptions",descMap);
	String displayName = accountGroup.getAttribute("description");
	accountGroup.setDisplayName(displayName);

	return accountGroup;

Monday, October 4, 2021

Sailpoint Identity IQ SQL Query to get the Users Details for Identity Having Multiple Account in same Application

 SQL Query to get the Users Having multiple Account in Same Application 

Select count(*) ,
SPT_APPLICATION.NAME AS APPLICATION_NAME ,
SPT_IDENTITY.name AS IDENTITY_NAME , 
SPT_IDENTITY.ID AS IDENTITY_ID , 
SPT_APPLICATION.ID AS APPLICATION_ID
from SPT_LINK , SPT_IDENTITY , SPT_APPLICATION 
where 
SPT_IDENTITY.ID=SPT_LINK.IDENTITY_ID and
SPT_APPLICATION.ID=SPT_LINK.APPLICATION and SPT_IDENTITY.CORRELATED=1 and SPT_APPLICATION.NAME not in ('Active Directory Corp') --and SPT_IDENTITY.NAME like 'VKEJRIWAL' group by SPT_IDENTITY.name , SPT_APPLICATION.NAME ,SPT_IDENTITY.ID , SPT_APPLICATION.ID HAVING COUNT(*)>1 order by SPT_APPLICATION.NAME ,SPT_IDENTITY.name

Query to get the Status of above Account

SELECT SPT_LINK.NATIVE_IDENTITY ,VIS_TEMP.APPLICATION_NAME,EXP_TEMP.IDENTITY_NAME,
SPT_LINK.DISPLAY_NAME ,EXP_TEMP.IDENTITY_ID,EXP_TEMP.APPLICATION_ID,
EXTRACT(xmltype(ATTRIBUTES),'/Attributes/Map/entry[@key=''IIQDisabled'']/value') AS STATUS
from SPT_LINK , VIS_TEMP
where SPT_LINK.IDENTITY_ID=VIS_TEMP.IDENTITY_ID
and SPT_LINK.APPLICATION=VIS_TEMP.APPLICATION_ID
--and  EXP_TEMP.IDENTITY_NAME like 'VKEJRIWAL'

 SQL Query to get Entitlement tied to above Accounts 

Select 
VIS_TEMP.APPLICATION_NAME,
VIS_TEMP.IDENTITY_NAME,
SPT_IDENTITY_ENTITLEMENT.NATIVE_IDENTITY,
SPT_IDENTITY_ENTITLEMENT.DISPLAY_NAME,
VIS_TEMP.IDENTITY_ID ,
SPT_MANAGED_ATTRIBUTE.VALUE,

from SPT_IDENTITY_ENTITLEMENT,VIS_TEMP,SPT_MANAGED_ATTRIBUTE, SPT_APPLICATION
where
SPT_IDENTITY_ENTITLEMENT.IDENTITY_ID=VIS_TEMP.IDENTITY_ID
and SPT_MANAGED_ATTRIBUTE.VALUE=SPT_IDENTITY_ENTITLEMENT.VALUE
and SPT_MANAGED_ATTRIBUTE.APPLICATION=SPT_IDENTITY_ENTITLEMENT.APPLICATION
and SPT_APPLICATION.ID=SPT_MANAGED_ATTRIBUTE.APPLICATION
and SPT_APPLICATION.ID=SPT_IDENTITY_ENTITLEMENT.APPLICATION
and SPT_APPLICATION.NAME=VIS_TEMP.APPLICATION_NAME

order by VIS_TEMP.IDENTITY_NAME,VIS_TEMP.APPLICATION_NAME

Friday, September 10, 2021

Creating a Request using RequestManager API in Sailpoint IdentityIQ

Creating a Request using RequestManager and Request Object , Here in below Example i have created a plan and then used the same plan to Generate the Request using RequestManager.

public void createSnowAppRequestObject(SailPointContext context,String identityName,String operation){

		try {
			Date currentDate = new Date();
			String flow = null;
			String caseName = null;
			ProvisioningPlan plan = new ProvisioningPlan();
	
			switch(operation.toUpperCase()){
				case "DISABLE":
					//Plan to disable Account
					plan = buildPlanForDisableSnowApps(context,identityName, operation);
					caseName = "VIS Disable ServiceNow Integrated Applications Event: " + identityName;
					flow = "UserDisableSnow";
					break;
				case "DELETE":
					//Plan to delete Account
					plan = buildPlanForDisableSnowApps(context,identityName, operation);
					caseName = "VIS Delete ServiceNow Integrated Applications Event: " + identityName;
					flow = "UserDeleteSnow";
					break;
				case "TERMINATE":
					//Plan to remove all the underlying Access & Disable Account
					plan = buildPlanForTerminateSnowApps(context,identityName);
					caseName = "VIS Terminate ServiceNow Integrated Applications Event: " + identityName;
					flow = "UserTerminateSnow";
					break;
				default:
					break;
			}
			if(plan != null && !plan.isEmpty() && plan.getAccountRequests() != null ){
				
				String workflowName = "LCM Provisioning";
				Workflow workflow = context.getObject(Workflow.class, workflowName);

				//Creating attributes to be used in Request Object
				Attributes requestArguments = new Attributes();
				requestArguments.put(sailpoint.workflow.StandardWorkflowHandler.ARG_REQUEST_DEFINITION, sailpoint.request.WorkflowRequestExecutor.DEFINITION_NAME);
				requestArguments.put(sailpoint.workflow.StandardWorkflowHandler.ARG_WORKFLOW, workflowName);
				requestArguments.put(sailpoint.workflow.StandardWorkflowHandler.ARG_REQUEST_NAME, caseName);
				requestArguments.put("requestName", caseName);

				Attributes workflowArguments = new Attributes();
				workflowArguments.put("identityName", identityName);
				workflowArguments.put("notificationScheme", "none");
				workflowArguments.put("approvalScheme", "none");
				workflowArguments.put("flow", flow);
				workflowArguments.put("plan", plan);
				workflowArguments.put("workflow", workflow.getId());
				requestArguments.putAll(workflowArguments);

				//Creating Request object for kicking off another workflow.
				Request requestObject = new Request();
				RequestDefinition requestDefinition = context.getObject(RequestDefinition.class,"Workflow Request");
				requestObject.setDefinition(requestDefinition);
				requestObject.setEventDate(currentDate);
				requestObject.setName(caseName);
				requestObject.setAttributes(requestDefinition, requestArguments);
				System.out.println("Request Object " + requestObject.toXml());

				RequestManager.addRequest(context, requestObject);
			}else{
			}
		} catch (Exception exception){
		}
	}	
   public ProvisioningPlan buildPlanForDisableSnowApps(SailPointContext context,String identityName, String operation) throws GeneralException{
		
		Identity identity = (Identity)getObject(context,identityName,Identity.class);		
		ProvisioningPlan plan = new ProvisioningPlan();		
		Filter filter = null;
		List objectPropertiesToFetch = new ArrayList();
		
		Map objectPropertiesFetched = new HashMap();
		objectPropertiesToFetch.add("type");
		objectPropertiesToFetch.add("toDisable");
		
		String VIS_SNOW_APPLICATION_TYPE = "DelimitedFile";
		
		//Iterate through identity links to create a disable/delete account request for the same
		if (identity != null) {
			List<Link> links = identity.getLinks();
			if (links != null && !links.isEmpty()) {				
				plan.setIdentity(identity);
				plan.setNativeIdentity(identity.getName());				
				String applicationName = null;
				AccountRequest accountRequest = null;		
				for (Link link : links) {				  
					applicationName = link.getApplicationName();				
					filter = Filter.eq("name", applicationName);	
					objectPropertiesFetched = getObjectProperties(context,Application.class, filter, objectPropertiesToFetch);
					if ( VIS_SNOW_APPLICATION_TYPE.equalsIgnoreCase((String)objectPropertiesFetched.get("type")) && "true".equalsIgnoreCase((String)objectPropertiesFetched.get("toDisable"))){			
						accountRequest = new AccountRequest();
						accountRequest.setNativeIdentity(link.getNativeIdentity());
						accountRequest.setApplication(applicationName);
						
						if("Delete".equalsIgnoreCase(operation)){							
							accountRequest.setOperation(ProvisioningPlan.AccountRequest.Operation.Delete); 							
						}else if("Disable".equalsIgnoreCase(operation)){							
							accountRequest.setOperation(ProvisioningPlan.AccountRequest.Operation.Disable); 							
						}					
						
						plan.add(accountRequest);						
					}
				}
			}
		}		
		return plan;
	}	
   public ProvisioningPlan buildPlanForTerminateSnowApps(SailPointContext context,String identityName) throws GeneralException{
		
		Identity identity = (Identity)getObject(context,identityName, Identity.class);
		
		ProvisioningPlan plan = new ProvisioningPlan();
		List accountRequestList = new ArrayList();
		List<Object> entitlementValuesList = new ArrayList();
		Application application = null;
		Filter filter = null;	
		Map objectPropertiesFetched = new HashMap();
		
		List objectPropertiesToFetch = new ArrayList();
		objectPropertiesToFetch.add("type");
		objectPropertiesToFetch.add("toDisable");
		
		String VIS_SNOW_APPLICATION_TYPE = "DelimitedFile";
		
		if (identity != null) {
			List<Link> links = identity.getLinks();
			if (links != null && !links.isEmpty()) {
				plan.setIdentity(identity);
				plan.setNativeIdentity(identity.getName());				
				plan.setIdentity(identity);
				plan.setNativeIdentity(identity.getName());
				
				String applicationName = null;
				AccountRequest accountRequestDisable = null;
				AccountRequest accountRequestModify = null;				
				AttributeRequest attributeRequest = null;
				String entitlementAttribute = null;
				
				for (Link link : links) {				  
					applicationName = link.getApplicationName(); 
					filter = Filter.eq("name", applicationName);	
					objectPropertiesFetched = getObjectProperties(context,Application.class, filter, objectPropertiesToFetch);					
					if("true".equalsIgnoreCase((String) objectPropertiesFetched.get("toDisable")) && VIS_SNOW_APPLICATION_TYPE.equalsIgnoreCase((String) objectPropertiesFetched.get("type"))){						
						application = (Application)getObject(context,applicationName, Application.class);						
						if(!application.getEntitlementAttributeNames().isEmpty() && application.getEntitlementAttributeNames() != null){							
							 entitlementAttribute = application.getEntitlementAttributeNames().get(0);							
							if( link.getAttribute(entitlementAttribute) instanceof String ){								
								entitlementValuesList = Arrays.asList( link.getAttribute(entitlementAttribute) );								
							}else if( link.getAttribute(entitlementAttribute) instanceof List ){								
								entitlementValuesList = (List) link.getAttribute(entitlementAttribute);
							}
						}
						
						accountRequestDisable = new AccountRequest();
						accountRequestDisable.setNativeIdentity(link.getNativeIdentity());
						accountRequestDisable.setApplication(applicationName);
						accountRequestDisable.setOperation(ProvisioningPlan.AccountRequest.Operation.Disable);	
							
						accountRequestModify = new AccountRequest();
						accountRequestModify.setNativeIdentity(link.getNativeIdentity());
						accountRequestModify.setApplication(applicationName);			
						accountRequestModify.setOperation(ProvisioningPlan.AccountRequest.Operation.Modify);
						
						for( Object entitlementName : Util.safeIterable(entitlementValuesList) ){							
							attributeRequest = new AttributeRequest(entitlementAttribute,ProvisioningPlan.Operation.Remove,entitlementName);
							attributeRequest.put("assignment","true");						
							accountRequestModify.add(attributeRequest);
						}						
						plan.add(accountRequestModify);						
						plan.add(accountRequestDisable);
					}
				}
			}
		}
		System.out.println(" Plan : " + plan.toXml());
		return plan;
	}
   
    public Object getObject(SailPointContext context,String objectName , Class objectClass) throws GeneralException {
	String filterString = "name == \""+objectName+"\"";
	Filter filter = Filter.compile( filterString );
	Object object = context.getUniqueObject( objectClass ,filter);
	return object; 
    }
   
	public Map getObjectProperties(SailPointContext context,java.lang.Class objectType, Filter searchFilter, List propertiesToFetch) throws GeneralException{
	Object[] objectProperties;
	Map propertiesMap = new HashMap();
	QueryOptions queryOptions = new QueryOptions();
	queryOptions.addFilter(searchFilter);
	Iterator iterator = context.search(objectType, queryOptions, propertiesToFetch);
	if(iterator.hasNext()){
		objectProperties = (Object[]) iterator.next();
		if (objectProperties != null ){
			propertiesMap = propertyArrayToMap(objectProperties, propertiesToFetch);
		}       
	} 
	Util.flushIterator(iterator);
	return propertiesMap; 
	}

	public Map propertyArrayToMap( Object[] objectProperties, List propertiesToFetch){
		Map propertiesMap = new HashMap();
		Iterator nameIterator = propertiesToFetch.iterator();
		for(Object value : objectProperties) {
			propertiesMap.put(nameIterator.next(), value);
		}
		Util.flushIterator(nameIterator);
		return propertiesMap;
	}
   

Plan (Termination Scenario) and Request Object Details 

Plan
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE ProvisioningPlan PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<ProvisioningPlan nativeIdentity="VKEJ">
  <AccountRequest application="Revenue Process Management" nativeIdentity="VKEJ" op="Modify">
    <AttributeRequest name="EntitlementName" op="Remove" value="Admin">
      <Attributes>
        <Map>
          <entry key="assignment" value="true"/>
        </Map>
      </Attributes>
    </AttributeRequest>
    <AttributeRequest name="EntitlementName" op="Remove" value="Super Read only">
      <Attributes>
        <Map>
          <entry key="assignment" value="true"/>
        </Map>
      </Attributes>
    </AttributeRequest>
  </AccountRequest>
  <AccountRequest application="Revenue Process Management" nativeIdentity="VKEJ" op="Disable"/>
</ProvisioningPlan>


Request 
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Request PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Request name="VIS Terminate ServiceNow Integrated Applications Event: VKEJ" nextLaunch="1631314916907">
  <Attributes>
    <Map>
      <entry key="approvalScheme" value="none"/>
      <entry key="flow" value="UserTerminateSnow"/>
      <entry key="identityName" value="VKEJ"/>
      <entry key="notificationScheme" value="none"/>
      <entry key="plan">
        <value>
          <ProvisioningPlan nativeIdentity="VKEJ">
            <AccountRequest application="Revenue Process Management" nativeIdentity="VKEJ" op="Modify">
              <AttributeRequest name="EntitlementName" op="Remove" value="Admin">
                <Attributes>
                  <Map>
                    <entry key="assignment" value="true"/>
                  </Map>
                </Attributes>
              </AttributeRequest>
              <AttributeRequest name="EntitlementName" op="Remove" value="Super Read only">
                <Attributes>
                  <Map>
                    <entry key="assignment" value="true"/>
                  </Map>
                </Attributes>
              </AttributeRequest>
            </AccountRequest>
            <AccountRequest application="Revenue Process Management" nativeIdentity="VKEJ" op="Disable"/>
          </ProvisioningPlan>
        </value>
      </entry>
      <entry key="requestDefinition" value="Workflow Request"/>
      <entry key="requestName" value="VIS Terminate ServiceNow Integrated Applications Event: VKEJ"/>
      <entry key="workflow" value="8a88b862734df7fc01734df888580351"/>
    </Map>
  </Attributes>
  <Definition>
    <Reference class="sailpoint.object.RequestDefinition" id="8a88b862734df7fc01734df83e4b0175" name="Workflow Request"/>
  </Definition>
</Request>