Custom Target Certification Creation using Script with custom emails

Hello Everyone,

I am trying to create target certification using script by adding one single user w.r.t one application. I don’t see any runtime issues but certification is not creating as per the script.

Ex: Created certification definition in run rule using API by cloning the existing certification definition and added one user (whom to certify), added certifier & added entitlement filter as single application by including additional entitlements (ex: Application as : Active Directory) → After running the rule certification has to create for Active Directory application but I see apart from AD other applications are coming in certification review. Anyone can help is my script correct or any other way to create. Please refer attached images of script & output

I also want to know can we customize certification notifications (initial,remidenr & escaltions) requirement is to send notifications to few certifiers not all on the trigger of certification.
Help on this makes easy to implement.

Thanks,

Ashritha.

Hi @AshrithaGampa,

I’ve encountered a similar situation before but haven’t had the time to debug it thoroughly. If possible, could you please share the rule file here? I can take a look and test it out for you.

Kindly make sure you remove any sensitive information such as passwords/links before sharing the code.

Thanks!

Hi @zeel_sinojia ,

Attaching my entire rule here for your reference to know what I did.

Added entitlement criteria as an application but still I can’t see those access in the generated certification view page

try {
String identityName = “XYZ”;
String certifierName = “CertifierName”;

Map entityFilterMap = new HashMap();
List listOfMapsEntity = new ArrayList();
Map entitlementFilterMap = new HashMap();
List listOfMapsEntitlements = new ArrayList();
CertificationDefinition template = null;
CertificationDefinition certDefinition = null;

  if(identityName!=null && certifierName!= null) {
    String certName = "Custom Target Cert for " + identityName;
    DateFormat dateformat = new SimpleDateFormat(“MM-dd-yyyy HH:mm:ss”);
    Date date = new Date();
    String certificationName = certName + “-” + dateformat.format(date);

template = context.getObjectByName(CertificationDefinition.class,
“Targeted Certification [13/8/25 1:40 PM]”);

CertificationDefinition certDefinition = (CertificationDefinition) XMLObjectFactory.getInstance()
.cloneWithoutId(template, (XMLReferenceResolver) context);
Identity ownerIdentity = context.getObjectByName(Identity.class, “spadmin”);

    String currentTime = java.time.LocalTime.now().toString();
    entityFilterMap.put(“operation”, “Equals”);
    entityFilterMap.put(“property”, “name”);
    entityFilterMap.put(“value”, identityName);
    listOfMapsEntity.add(entityFilterMap); //identity to certify
    
    
    entitlementFilterMap.put(“operation”, “Equals”);
    entitlementFilterMap.put(“property”, “application”);
    entitlementFilterMap.put(“value”, “Active Directory Application”);
    listOfMapsEntitlements.add(entitlementFilterMap);

certDefinition.setEntitlementFilterValues(listOfMapsEntitlements);
certDefinition.setEntitlementFilter(Filter.eq(“application.name”, “Active Directory Application”));
certDefinition.setEntitlementGranularity(EntitlementGranularity.Value);
certDefinition.setCertifyAccounts(false);
certDefinition.setIncludeRoles(false);
certDefinition.setIncludeAdditionalEntitlements(true);
certDefinition.setIncludeEntitlementsGrantedByRoles(true);
certDefinition.setIncludePolicyViolations(false);
certDefinition.setIncludeTargetPermissions(true);
certDefinition.setCertifyEmptyAccounts(true);
certDefinition.setType(Type.Focused);
certDefinition.setEntityFilterValues(listOfMapsEntity);
certDefinition.setEntityFilter(Filter.eq(“name”, identityName));
certDefinition.setEntitySelectionType(“Filter”);
certDefinition.setAttribute(“owners”, ownerIdentity);
certDefinition.setAttribute(“identities”, identityName);

certDefinition.setName(certName + " - " + currentTime);
certDefinition.setAllowItemDelegation(true);
// certDefinition.setAllowAccountRevocation(true);
// certDefinition.setSuppressInitialNotification(true);
certDefinition.setDelegationForwardingDisabled(false);
certDefinition.setCertificationOwner(ownerIdentity);
certDefinition.setOwner(ownerIdentity);
certDefinition.setCertifierName(certifierName);
certDefinition.setCertifierSelectionType(CertificationDefinition.CertifierSelectionType.Manual);
certDefinition.setNameTemplate(certificationName);
certDefinition.setCertificationNameTemplate(certName + " - ${fullDate}“);
certDefinition.setShortNameTemplate(certName + " - ${fullDate}”);
certDefinition.setStagingEnabled(false);
certDefinition.setBackupCertifierName(“IIQADMIN”);
certDefinition.setProcessRevokesImmediately(false);

    context.saveObject(certDefinition);
    context.commitTransaction();

CertificationSchedule certSchedule = new CertificationSchedule(context, ownerIdentity,
certDefinition);
certSchedule.setRunNow(true);
CertificationScheduler scheduler = new CertificationScheduler(context);
TaskSchedule taskSchedule = scheduler.saveSchedule(certSchedule, false);
System.out.println(“:SCHEDULED CERTIFICATION:::::”);
}
}
catch (Exception e) {
e.printStackTrace();
System.out.println(
“Below exception occurred during generation of access review for identity”);
System.out.println(e.getMessage());
}
}

As per above code it has to show XYZ user Active Directory access in the certification

entity page but instead of that it is showing other accounts that were linked to xyz user.

Thanks,

Ashritha.

Hey @AshrithaGampa, thanks for your patience.

I was able to trigger the certification and the filters were applied correctly. The issue seems to occur when I run the task manually. When I schedule the task for 1 minute in the future (effectively immediate), the certification triggers with the filters.

I also noticed that when I trigger the certification immediately instead of scheduling it, a new certification definition is created and used instead of the one I created from the template. That might be the root cause of what I was seeing. To compare, you could try both:

  • Schedule the task 1 minute ahead (this worked for me).
  • Run the task manually to see if it reproduces the issue or uses a different definition.

Let me know if this works for you. Attaching the code below.

HTH.

For context, followed the recommendations from this thread: Call certification event template in rule - #6 by Remold

import sailpoint.api.SailPointContext;
import sailpoint.object.CertificationDefinition;
import sailpoint.object.Filter;
import sailpoint.object.TaskSchedule;
import sailpoint.tools.GeneralException;
import sailpoint.tools.xml.XMLObjectFactory;
import sailpoint.tools.xml.XMLReferenceResolver;
 
import java.text.SimpleDateFormat;
import java.util.*;
 
// ==============================
// Constants
// ==============================
 
private static String TARGET_IDENTITY_NAME = "<TARGET_IDENTITY_NAME>";
private static String CERTIFIER_IDENTITY_NAME = "<CERTIFIER_IDENTITY_NAME>";
private static String TARGET_APPLICATION_NAME = "<TARGET_APPLICATION_NAME>";
private static String LAUNCHER_IDENTITY_NAME = "<LAUNCHER_IDENTITY_NAME>";
private static String CERTIFICATION_DEFINITION_TEMPLATE_NAME = "<CERTIFICATION_DEFINITION_TEMPLATE_NAME>";
 
// ==============================
// Certification Initialization
// ==============================
 
public CertificationDefinition initializeCertification(CertificationDefinition template,
                                                       String newCertificationName,
                                                       Date date) throws GeneralException {
 
    // Clone certificate from existing template
    XMLObjectFactory instance = XMLObjectFactory.getInstance();
    CertificationDefinition certificationDefinition =
            (CertificationDefinition) instance.cloneWithoutId(template, (XMLReferenceResolver) context);
 
    // Metadata
    certificationDefinition.setCreated(date);
    certificationDefinition.setModified(date);
    certificationDefinition.setName(newCertificationName);
    certificationDefinition.setShortName(newCertificationName);
    certificationDefinition.setNameTemplate(newCertificationName);
    certificationDefinition.setShortNameTemplate(newCertificationName);
 
    // Certifier
    certificationDefinition.setCertifierName(CERTIFIER_IDENTITY_NAME);
 
    // Filters
    certificationDefinition.setEntityFilterValues(Collections.singletonList(createFilter("name", TARGET_IDENTITY_NAME)));
    certificationDefinition.setEntityFilter(Filter.eq("name", TARGET_IDENTITY_NAME));
 
    certificationDefinition.setEntitlementFilterValues(Collections.singletonList(createFilter("application", TARGET_APPLICATION_NAME)));
    certificationDefinition.setEntitlementFilter(Filter.eq("application.name", TARGET_APPLICATION_NAME));
 
    // Save changes
    context.saveObject(certificationDefinition);
    context.commitTransaction();
    context.attach(certificationDefinition);
 
    return certificationDefinition;
}
 
// ==============================
// Certification Scheduling
// ==============================
 
public void scheduleCertification(String certId, String name) throws Exception {
 
    TaskSchedule taskSchedule = new TaskSchedule();
    taskSchedule.setName(name);
    taskSchedule.setLauncher(LAUNCHER_IDENTITY_NAME);
    taskSchedule.setArgument("certificationDefinitionId", certId);
    taskSchedule.setArgument("executor", "Certification Manager");
    taskSchedule.setArgument("resultName", name);
 
    // Set schedule time (example: +1 minutes from now)
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.MINUTE, 1);
 
    String cronExpression = String.format("%d %d %d %d %d %s %d",
            cal.get(Calendar.SECOND),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.MONTH) + 1,
			"?",
            cal.get(Calendar.YEAR));
 
    taskSchedule.setCronExpressions(Collections.singletonList(cronExpression));
 
    context.saveObject(taskSchedule);
}
 
// ==============================
// Certification Triggering
// ==============================
 
public String triggerCertification() {
 
    try {
        String currentDateTime = new SimpleDateFormat("MM/yyyy/dd HH:mm:ss z")
                .format(Calendar.getInstance().getTime());
 
        String newCertificationName = "Rule Run Certification - " + TARGET_IDENTITY_NAME + " [" + currentDateTime + "]";
 
        CertificationDefinition template = context.getObject(CertificationDefinition.class, CERTIFICATION_DEFINITION_TEMPLATE_NAME);
 
        CertificationDefinition newCert = initializeCertification(template, newCertificationName,
                new Date());
 
        scheduleCertification(newCertificationName, "sched-" + newCertificationName);
 
    } catch (Exception e) {
        e.printStackTrace();
    }
 
    return "Completed";
}
 
// ==============================
// Utility Methods
// ==============================
 
private Map createFilter(String property, String value) {
    Map filter = new HashMap();
    filter.put("operation", "Equals");
    filter.put("property", property);
    filter.put("value", value);
    return filter;
}

new return triggerCertification();