There can be a need to automatically reassign the certification items of the user in a Manager Certification to the new manager when the user's manager gets changed.
SailPoint does not handle this behavior automatically. Once the certification is created either we have to manually reassign the items to the new manager or we can use the manager transfer Lifecycle event to handle this scenario.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE IdentityTrigger PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<IdentityTrigger handler="sailpoint.api.WorkflowTriggerHandler" name="Manager transfer LifeCycle Event" type="ManagerTransfer">
<Description>Check if user is part of Manager Certification for old manager. If it is in Active or Staged phase, Reassign to new manager.</Description>
<HandlerParameters>
<Attributes>
<Map>
<entry key="workflow" value="Workflow-LifecycleEvent-ManagerTransfer"/>
</Map>
</Attributes>
</HandlerParameters>
</IdentityTrigger>
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow explicitTransitions="true" libraries="Identity" name="Workflow-LifecycleEvent-ManagerTransfer" type="IdentityLifecycle">
<Variable input="true" name="trigger">
<Description>The IdentityTrigger</Description>
</Variable>
<Variable initializer="true" name="trace">
<Description>The trace variable for the workflow.</Description>
</Variable>
<Variable input="true" name="event" transient="true">
<Description>
The IdentityChangeEvent. It can be used to build
the provisioning plan, but does not need to be
persisted with the case, so marked as transient.
</Description>
</Variable>
<Variable input="true" name="identityName">
<Description>The name of the identity.</Description>
</Variable>
<Variable name="identityDisplayName">
<Description>The display name of the identity.</Description>
<Script>
<Source>
import sailpoint.object.Identity;
Identity identityObject = context.getObjectByName(Identity.class, identityName);
if(null!=identityObject){
return identityObject.getDisplayableName();
}
return null;
</Source>
</Script>
</Variable>
<Variable name="oldManager">
<Description>
Identity name of old manager
</Description>
<Script>
<Source>
import sailpoint.object.Identity;
Identity oldManager = (null != event.getOldObject()) ? event.getOldObject().getManager() : null;
if(null!=oldManager){
return oldManager.getName();
}
return null;
</Source>
</Script>
</Variable>
<Variable name="newManager">
<Description>
Identity name of new manager
</Description>
<Script>
<Source>
import sailpoint.object.Identity;
Identity newManager = (null != event.getObject()) ? event.getObject().getManager() : null;
if(null!=newManager){
return newManager.getName();
}
return null;
</Source>
</Script>
</Variable>
<Variable name="processUser">
<Description>
Should we process the user. Yes/No
</Description>
<Script>
<Source>
if(null!=oldManager && null!=newManager && !oldManager.equals(newManager)){
return true;
}
return false;
</Source>
</Script>
</Variable>
<Description>Process a user when they change managers.</Description>
<Step icon="Start" name="Start" posX="28" posY="10">
<Transition to="Check_For_Certifications" when="processUser"/>
<Transition to="Stop" when="!processUser"/>
</Step>
<Step icon="Message" name="Check_For_Certifications">
<Description>Check if user is part of Manager Certification for old manager. If it is in Active or Staged phase, Reassign to new manager.</Description>
<Script>
<Source>
import sailpoint.object.Identity;
import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;
import sailpoint.object.Certification;
import sailpoint.object.CertificationEntity;
import sailpoint.object.CertificationItem;
import sailpoint.api.Certificationer;
import sailpoint.tools.Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
static Log logger = LogFactory.getLog("Workflow.Workflow-LifecycleEvent-ManagerTransfer");
Identity identityTargetObject = context.getObjectByName(Identity.class, identityName);
Identity identityNewManager = context.getObjectByName(Identity.class, newManager);
Identity identityObjectOldManager = context.getObjectByName(Identity.class, oldManager);
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer identityTargetObject "+identityTargetObject);
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer identityNewManager "+identityNewManager);
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer identityObjectOldManager "+identityObjectOldManager);
}
if(null!=identityObjectOldManager && null!=identityTargetObject && null!=identityNewManager){
QueryOptions qo = new QueryOptions();
List users = new ArrayList();
users.add(identityObjectOldManager.getName());
qo.addFilter(Filter.in("certifiers",users));
Iterator certifications = context.search(Certification.class, qo);
while(certifications.hasNext()){
List itemsToReassign = new ArrayList();
Certification eachCert = certifications.next();
String requester = eachCert.getCreator();
Identity requesterObject = null;
if(null!=requester){
requesterObject = context.getObjectByName(Identity.class, requester);
}
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer certificationName "+eachCert.getCertificationName());
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer Certifiers "+eachCert.getCertifiers());
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer requester "+requester);
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer requesterObject "+requesterObject);
}
if(null!= eachCert.getType()
&& null!=eachCert.getPhase()
&& eachCert.getType().equals(Certification.Type.Manager)
&& (eachCert.getPhase().equals(Certification.Phase.Active)
|| eachCert.getPhase().equals(Certification.Phase.Staged))){
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer inside Manager Active || Staged ");
}
QueryOptions qoEntity = new QueryOptions();
qoEntity.addFilter(Filter.eq("identity", identityTargetObject.getName()));
qoEntity.addFilter(Filter.eq("certification", eachCert));
Iterator entities = context.search(CertificationEntity.class, qoEntity);
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer qoEntity "+qoEntity);
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer entities "+entities);
}
while(entities.hasNext()){
CertificationEntity entity = entities.next();
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer entity TargetName "+entity.getTargetName());
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer entity type "+entity.getType());
}
List items = entity.getItems();
for(CertificationItem item: items){
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer item Id "+item.getId());
}
itemsToReassign.add(item);
}
}
Util.flushIterator(entities);
}
String newName = "Reassignment from "+eachCert.getName()+" to "+ identityNewManager.getDisplayableName();;
if(logger.isDebugEnabled()){
logger.debug("Workflow.Workflow-LifecycleEvent-ManagerTransfer itemsToReassign "+itemsToReassign);
}
String comments = "As you are the new manager for the user "+identityDisplayName+", please certify the user access.";
if(null!=requesterObject){
eachCert.bulkReassign(requesterObject, itemsToReassign, identityNewManager, newName, comments, context.getConfiguration());
}
else{
eachCert.bulkReassign(identityObjectOldManager, itemsToReassign, identityNewManager, newName, comments, context.getConfiguration());
}
context.saveObject(eachCert);
context.commitTransaction();
new Certificationer(context).refresh(eachCert);
context.decache();
}
Util.flushIterator(certifications);
}
</Source>
</Script>
<Transition to="Stop"/>
</Step>
<Step icon="Stop" name="Stop" posX="268" posY="10"/>
</Workflow>
Updated the manager of user Catherine to Aaron.Nichols. This triggered our Manager Transfer Lifecycle Event and reassigned the the user's certification items to new manager.
ok
I tried this rule on IdentityIQ 7.2 and sadly it did not work. Any chance there's a revised version that would work with 7.2?
Hi,
Won't the " new Certificationer(context).refresh(eachCert);" close the ResultSet ? Shouldn't it throw a "ResultSetClosed" exception, same goes with the commitTransaction()?
Thanks