Most probably your entitlements are marked as sticky within the identity causing the refresh to reprovision the entitlement again.
Adding this statement while creating the new attribute request will make the removal as permanent
Attributes attrs = new Attributes();
attrs.put("assignment", true);
AttributeRequest attributeRequest = new AttributeRequest(attribute, ProvisioningPlan.Operation.Remove, entitlementValue);
attributeRequest.setArgs(attrs);
However I don’t see the creation of new attribute request in your code. I would suggest you run the sticky entitlement removal task before the refresh of Identity Cubes.
Task Definition XML:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE TaskDefinition PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<TaskDefinition name="Task-StickyEntRemoval" resultAction="Rename" subType="task_item_type_generic" type="Generic">
<Attributes>
<Map>
<entry key="TaskDefinition.runLengthAverage"/>
<entry key="TaskDefinition.runLengthTotal"/>
<entry key="TaskDefinition.runs"/>
<entry key="TaskSchedule.host"/>
<entry key="deleteStickEnt" value="false"/>
<entry key="ruleName" value="Rule-StickyEntRemoval"/>
<entry key="taskCompletionEmailNotify" value="Disabled"/>
<entry key="taskCompletionEmailRecipients"/>
<entry key="taskCompletionEmailTemplate"/>
</Map>
</Attributes>
<Description>A task is used to remove Sticky Entitlements and Disconnected Attribute Assignments from the Identities.</Description>
<Owner>
<Reference class="sailpoint.object.Identity" name="spadmin"/>
</Owner>
<Parent>
<Reference class="sailpoint.object.TaskDefinition" name="Run Rule"/>
</Parent>
<Signature>
<Inputs>
<Argument helpKey="When this is checked, sticky entitlements will be deleted along with Attribute Assignments. Else task result will only show the stick entitlements present in OneAccess" name="deleteStickEnt" type="boolean">
<Prompt>Delete the Sticky Entitlements</Prompt>
</Argument>
<Argument helpKey="When this is checked, the task will only run on the specific identity" name="identityValue" type="string">
<Prompt>Identity Distinguished Name</Prompt>
</Argument>
</Inputs>
<Returns>
<Argument name="attrAssignRemovalCount" type="string">
<Prompt>Total attributeAssignments removed</Prompt>
</Argument>
<Argument name="attrAssignIdList" type="string">
<Prompt>Identities name with AttributeAssignment</Prompt>
</Argument>
<Argument name="idenEntRemovalCount" type="string">
<Prompt>Total sticky entitlements removed</Prompt>
</Argument>
<Argument name="totalIE" type="int">
<Prompt>Total number of sticky entitlements</Prompt>
</Argument>
<Argument name="idenEntList" type="string">
<Prompt>Sticky entitlements</Prompt>
</Argument>
</Returns>
</Signature>
</TaskDefinition>
Rule Object:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="Rule-StickyEntRemoval">
<Source><![CDATA[
import java.util.Iterator;
import java.util.List;
import sailpoint.api.ObjectUtil;
import sailpoint.api.PersistenceManager.LockParameters;
import sailpoint.api.Terminator;
import sailpoint.object.AttributeAssignment;
import sailpoint.object.Filter;
import sailpoint.object.Identity;
import sailpoint.object.IdentityEntitlement;
import sailpoint.object.QueryOptions;
import sailpoint.object.TaskResult;
import sailpoint.tools.GeneralException;
import sailpoint.tools.Message;
import sailpoint.tools.Util;
if(void==taskResult || null == taskResult || config == null){
return ;
}
int attrAssignRemovalCount=0;
int idenEntRemovalCount = 0;
int totalIE=0;
boolean isDelete = Util.otob(config.get("deleteStickEnt"));
String identityValue = Util.otoa(config.get("identityValue"));
List attrAssignIdList = new ArrayList();
List idenEntList = new ArrayList();
Iterator itr = null;
Iterator aaIt = null;
String RESULT = "Success";
private void getAttrAssignmentsId(IdentityEntitlement idenEnt) throws GeneralException{
Identity id = null;
try{
id = idenEnt.getIdentity();
if(id!=null){
List attributeAssignmentList = id.getAttributeAssignments();
if(!Util.isEmpty(attributeAssignmentList)){
aaIt = attributeAssignmentList.iterator();
while(aaIt.hasNext()) {
AttributeAssignment attAssign = aaIt.next();
if(Util.isNotNullOrEmpty(idenEnt.getAssignmentId()) && Util.isNotNullOrEmpty(attAssign.getAssignmentId()) && attAssign.getAssignmentId().equalsIgnoreCase(idenEnt.getAssignmentId())){
attrAssignIdList.add(id.getName());
}
}
}
}
}
catch (GeneralException genExp) {
log.error("GeneralException in Rule-TaskRule-StickyEntRemoval :: getAttrAssignmentsId : "+genExp);
throw new GeneralException(genExp);
}
finally{
if(aaIt!=null){
Util.flushIterator(aaIt);
}
}
}
private void removeAttrAssignment(IdentityEntitlement idenEnt) throws GeneralException{
Identity id = null;
try{
id = ObjectUtil.lockIfNecessary(context,idenEnt.getIdentity().getName());
if(id!=null){
List attributeAssignmentList = id.getAttributeAssignments();
if(!Util.isEmpty(attributeAssignmentList)){
aaIt = attributeAssignmentList.iterator();
while(aaIt.hasNext()) {
AttributeAssignment attAssign = aaIt.next();
if(Util.isNotNullOrEmpty(idenEnt.getAssignmentId()) && Util.isNotNullOrEmpty(attAssign.getAssignmentId()) && attAssign.getAssignmentId().equalsIgnoreCase(idenEnt.getAssignmentId())){
aaIt.remove();
attrAssignIdList.add(id.getName());
attrAssignRemovalCount++;
}
}
context.saveObject(id);
}
}
}
catch (GeneralException genExp) {
if(id!=null){
ObjectUtil.unlockIdentity(context, id);
}
log.error("GeneralException in Rule-TaskRule-StickyEntRemoval :: removeAttrAssignment : "+genExp);
throw new GeneralException(genExp);
}
finally{
if(id!=null){
ObjectUtil.unlockIdentity(context, id);
}
if(aaIt!=null){
Util.flushIterator(aaIt);
}
}
}
//Rule starts here
try {
QueryOptions qo = new QueryOptions();
qo.setCloneResults(true);
qo.setDistinct(true);
if(Util.isNotNullOrEmpty(identityValue)){
qo.addFilter(Filter.ignoreCase(Filter.eq("nativeIdentity",identityValue)));
}
qo.addFilter(Filter.ignoreCase(Filter.eq("aggregationState","disconnected")));
itr = context.search(IdentityEntitlement.class,qo);
while(itr.hasNext()){
IdentityEntitlement idenEnt = itr.next();
if(isDelete){
context.startTransaction();
removeAttrAssignment(idenEnt);
Terminator terminator = new Terminator(context);
terminator.deleteObject(idenEnt);
context.commitTransaction();
idenEntRemovalCount++;
}
else{
getAttrAssignmentsId(idenEnt);
}
if(totalIE<100){
idenEntList.add(" [ "+idenEnt.getValue()+" ] ");
}
totalIE++;
}
if(!isDelete){
taskResult.addMessage(new Message(Message.Type.Info,"No records were deleted", null));
}
} catch (GeneralException genExp) {
context.rollbackTransaction();
taskResult.addMessage(new Message(Message.Type.Error, "GeneralException occurred: "+genExp.getMessage(), null));
RESULT = "Fail";
} finally {
try{
if(itr!=null){
Util.flushIterator(itr);
}
context.decache();
}catch(GeneralException exp){
log.error("GeneralException in Rule-TaskRule-StickyEntRemoval : "+exp);
taskResult.addMessage(new Message(Message.Type.Error, "GeneralException occurred: "+exp.getMessage(), null));
RESULT = "Fail";
}
}
if(totalIE>100){
taskResult.addMessage(new Message(Message.Type.Info,"Task Result will only display 100 entitlements", null));
}
taskResult.put("attrAssignRemovalCount",attrAssignRemovalCount);
taskResult.put("attrAssignIdList",attrAssignIdList);
taskResult.put("idenEntRemovalCount",idenEntRemovalCount);
taskResult.put("totalIE",totalIE);
taskResult.put("idenEntList",idenEntList);
return RESULT;
]]></Source>
</Rule>
Let me know if this works.
Regards,
Balaji