Share all details about your problem, including any error messages you may have received.
We’re trying to prevent situations where someone ends up certifying themselves — specifically when a certification work item is forwarded and results in self-certification.
We attempted to use the option: “Check self certification on manual work item forward”, but we found a case that bypasses this check:
If an identity has a Forwarding User specified, the option is ignored.
What have you selected for the Self Certification Options for your certification. Not allowing self certification for all certifiers can ensure that users who are not system admin are not able to certify themselves. You will have to manage those certifications using Self Certification violation owner configured.
The problem is not in the certification itself. Is after the we activate the certification:
When we try to certify the workItem created by the certification:
If we have the “Check self certification on manual work item forward” option selected on the IdentityIQ Settings - Work Items then if we try to forward for the user being certified, we get the message: Cannot complete operation because cannot certify him/herself.
But if we forward to an identity which has a Forward User set, we can bypass the option. As in we can send a certification for the user being certified.
We came across the same situation and resolved it by using a Self-Certification Forwarding Rule. This ensures that when forwarding would result in self-certification, the work item is reassigned to another valid certifier (or a defined fallback).
Here’s the rule we used, and it worked for us:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule created="" id="" language="beanshell" modified="" name="Self Certifier Forwarding rule V1" significantModified="" type="FallbackWorkItemForward">
<Description>A rule used to pick a fallback owner for a work item in case current owner will cause self-certification.</Description>
<Signature returnType="Object">
<Inputs>
<Argument name="log" type="org.apache.commons.logging.Log">
<Description>
The log object associated with the SailPointContext.
</Description>
</Argument>
<Argument name="context" type="sailpoint.api.SailPointContext">
<Description>
A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
</Description>
</Argument>
<Argument name="item" type="WorkItem">
<Description>The WorkItem being opened. Note that the not all of the WorkItem arguments may be set.</Description>
</Argument>
<Argument name="owner" type="Identity">
<Description>The Identity that currently owns the work item.</Description>
</Argument>
<Argument name="creator" type="String">
<Description>The name of identity that created the certification belonging to the work item.</Description>
</Argument>
<Argument name="certifiers" type="List<String>">
<Description>A list of certifier names for the certification belonging to the work item.</Description>
</Argument>
<Argument name="name" type="String">
<Description>The name of the certification belonging to the work item. It may be null if certification is not created yet.</Description>
</Argument>
<Argument name="type" type="Certification.Type">
<Description>The type of the certification belonging to the work item.</Description>
</Argument>
</Inputs>
<Returns>
<Argument name="newOwner">
<Description>An Identity that should own the work item. Alternatively, this can be a String that is the name or id of the Identity.</Description>
</Argument>
</Returns>
</Signature>
<Source>
import sailpoint.object.Certification;
import sailpoint.object.Identity;
String approver = null;
Identity newUser = context.getObjectByName(Identity.class, "spadmin");
if (name != null && item.getCertification() != null) {
Certification cert = context.getObjectById(Certification.class, item.getCertification());
if (cert != null) {
approver = cert.getOwner();
}
}
if (approver == null || approver.equals(owner.getName())) {
for (String certifier : certifiers) {
if (!certifier.equals(owner.getName())) {
return certifier;
}
}
}
return newUser;
</Source>
</Rule>
This way, the work item never loops back to the same person for certification.
We tried using this type of rule, but encountered a different issue. When a work item includes a self-certification, all the associated CertificationEntities are forwarded — not just the one that is self-certifying.
It makes sense, as it affects the whole WorkItem.
Any idea how to achieve this only for the self-certifying Entity? Like what happens in the Certifications themselves.
Currently I’m trying to make a workaround. I made the “FallbackWorkItemForward” rule so that it will loops through the different Entities, find those which are self certifying, and these are reassigned. The remaining ones are send to the original owner.
The behavior you described is consistent with how SailPoint handles WorkItems forwarding affects all associated CertificationEntities. Your workaround with the FallbackWorkItemForward rule seems like a reasonable approach to isolate self-certifying entities while keeping the rest with the original owner.