There are several posts in Compass mentioning the ways of removing AttributeAssignments. I don't argue that they can't do the job, however I think it still worth it taking a holistic view of how IdentityIQ actually handles AttributeAssignments removal. Hopefully, this would help you gain more clarity.
First, AttributeAssignments are added to an identity when entitlements were requested as part of an access request. The screenshot attached show I have requested three AD groups for Angela Bell.
Once the request was fulfilled, I can see the three AttributeAssignments like this in Debug for Angela's identity.
<Preferences>
<Map>
<entry key="attributeAssignments">
<value>
<List>
<AttributeAssignment applicationId="4028bd03607fde5101607fe38c1e0008" applicationName="ClementAD" assigner="spadmin" assignmentId="d26d7be3768440c0a97d3f892cea6481" name="memberOf" nativeIdentity="CN=Angela.Bell,OU=ClemUsers,DC=iiqtest,DC=local" source="LCM" type="Entitlement" value="CN=group153,OU=SampleGroups,DC=iiqtest,DC=local"/>
<AttributeAssignment applicationId="4028bd03607fde5101607fe38c1e0008" applicationName="ClementAD" assigner="spadmin" assignmentId="45f9ad7b93ae48fc8a7c08c832113beb" name="memberOf" nativeIdentity="CN=Angela.Bell,OU=ClemUsers,DC=iiqtest,DC=local" source="LCM" type="Entitlement" value="CN=group1137,OU=SampleGroups,DC=iiqtest,DC=local"/>
<AttributeAssignment applicationId="4028bd03607fde5101607fe38c1e0008" applicationName="ClementAD" assigner="spadmin" assignmentId="71fcc1b08a4b4e6ba7bbd8089c36643b" name="memberOf" nativeIdentity="CN=Angela.Bell,OU=ClemUsers,DC=iiqtest,DC=local" source="LCM" type="Entitlement" value="CN=group16,OU=SampleGroups,DC=iiqtest,DC=local"/>
</List>
</value>
</entry>
</Map>
</Preferences>
When we try to deprovision Angela's AD account in IdentityIQ either in Manage Accounts on UI or by having a delete account provisioning plan in a rule or workflow such as:
AccountRequest accountRequest = new AccountRequest();
accountRequest.setApplication("ClementAD");
accountRequest.setNativeIdentity("CN=Angela.Bell,OU=ClemUsers,DC=iiqtest,DC=local");
accountRequest.setOp(sailpoint.object.ProvisioningPlan.ObjectOperation.Delete);
During provisioning, sailpoint.provisioning.IIQEvaluator has the method processAttributeAssignments(ProvisioningPlan plan) to automatically clean up AttributeAssignments. We don't need to do any clean up here.
Or if provisioning were not for a delete account operation, for example, a disable operation instead, adding assignment == true to AttrbuteRequest is needed to clean up AttributeAssignments. Please see:
Re: How to remove attributeAssignments by leaver workflow?
Lastly, if AD account were deleted directly in AD, AttributeAssignments don't automatically get cleaned up. They remain in the identity cube. Next time when a refresh task is run and with the option of Provision Assignments turned on, IdentityIQ will try to reprovision the AD account because it can no longer find it. That's why we call the AttributeAssignment sticky. If that's the case in your environment, this is the sample code to show you how AttributeAssignments removal is done in processAttributeAssignments() and you can use it in an one-time bulk clean up rule.
import sailpoint.api.ObjectUtil;
import sailpoint.object.Identity;
Identity identity = ObjectUtil.lockObject(context, Identity.class, "Angela.Bell",PersistenceManager.LOCK_TYPE_PERSISTENT, Util.uuid(), ObjectUtil.DEFAULT_LOCK_TIMEOUT);
try {
List attributeAssignments = identity.getAttributeAssignments();
if(attributeAssignments != null && !attributeAssignments.isEmpty()){
Iterator aaIt = attributeAssignments.iterator();
while(aaIt.hasNext()) {
aaIt.remove();
context.saveObject(identity);
}
}
} catch (Exception e) {
//Log any errors encountered during saving the object
} finally {
//this will commit if it's a persistent lock
context.unlockObject(identity);
}
Good luck and happy coding!
Why this rule is not working as expected ?
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="Rule_attributeAssignments">
<Signature>
<Inputs>
<Argument name="config">
<Description>
Taskdefinition configuration object
</Description>
</Argument>
</Inputs>
</Signature>
<Source>
import sailpoint.api.ObjectUtil;
import sailpoint.object.Identity;
Identity identity = ObjectUtil.lockObject(context, Identity.class, "AEMERSON",PersistenceManager.LOCK_TYPE_PERSISTENT, Util.uuid(), ObjectUtil.DEFAULT_LOCK_TIMEOUT);
try {
List attributeAssignments = identity.getAttributeAssignments();
if(attributeAssignments != null && !attributeAssignments.isEmpty()){
Iterator aaIt = attributeAssignments.iterator();
while(aaIt.hasNext()) {
aaIt.remove();
context.saveObject(identity);
}
}
} catch (Exception e) {
//Log any errors encountered during saving the object
} finally {
//this will commit if it's a persistent lock
context.unlockObject(identity);
}
</Source>
</Rule>