How to set a dynamic description for the end user in advanced policy

Hi All,

I have developed a advanced policy. I need to set the dynamic description for the end user. How can achieve that.

in rule I have set as policyViolation.setDescription(description); but not displaying.

Note : Please advise, how to overwrite summary from our dynamic description?

Hi @Venu1010

Check the below code for your requirement.

import sailpoint.object.Policy;
import sailpoint.object.PolicyViolation;
import sailpoint.object.Identity;
import sailpoint.object.Bundle;
import sailpoint.object.Application;
import sailpoint.object.Custom;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Set; // Imported but not used, can be removed if not needed elsewhere

/**
 * Helper function to convert a list of objects (expected to be Bundles) to a list of their names (Strings).
 * Handles cases where assigned roles might already be Strings.
 */
public List<String> getRoleNames(List<?> roles) {
    List<String> roleNames = new ArrayList<>();
    if (roles != null) {
        for (Object roleObj : roles) {
            if (roleObj instanceof Bundle) {
                Bundle role = (Bundle) roleObj;
                if (role != null && role.getName() != null) {
                    roleNames.add(role.getName());
                }
            } else if (roleObj instanceof String) { // Handle if roles are already Strings
                roleNames.add((String) roleObj);
            } else {
                // Log if an unexpected object type is found
                log.debug("getRoleNames: Encountered unexpected object type in roles list: " + (roleObj != null ? roleObj.getClass().getName() : "null"));
            }
        }
    }
    return roleNames;
}

log.debug("Inside Policy Violation rule: SLF_Rule_Policy_Violation_Generic_OneRoleAtATime_AppName.");

PolicyViolation policyViolation = null;
StringBuilder violationMessage = new StringBuilder();

// Get the optimistic identity (what the user *will* have)
Identity expectedIdentity = identity;

// Get the current identity from the database for comparison
Identity oldIdentity = context.getObjectByName(Identity.class, identity.getName());
if (oldIdentity == null) {
    log.error("Policy Rule: Could not retrieve old identity for " + identity.getName() + ". Aborting policy check.");
    return null; // Cannot proceed without the old identity
}

// Convert Bundle lists to List<String> of role names
List<String> allRoles = getRoleNames(expectedIdentity.getAssignedRoles());
List<String> existingRoles = getRoleNames(oldIdentity.getAssignedRoles());

// Determine newly requested roles by removing existing roles from the optimistic roles
List<String> newlyRequestedRoles = new ArrayList<>(allRoles);
// Remove existing roles from the optimistic list to get only the NEW ones
if (existingRoles != null) {
    newlyRequestedRoles.removeAll(existingRoles);
}

log.debug("Newly requested roles: " + newlyRequestedRoles);
log.debug("Existing roles: " + existingRoles);

Map<String, List<String>> roleMap = new HashMap<>(); // Use generics for better type safety
Custom OneRoleAtATimeCustomObject = context.getObjectByName(Custom.class, "SLF - Custom - OneRoleAtATime");

if (OneRoleAtATimeCustomObject != null) {
    Object configObj = OneRoleAtATimeCustomObject.get("OneRoleAtATime_Applications_Config");
    if (configObj instanceof Map) {
        // Safe cast to Map<String, List<String>>
        roleMap = (Map<String, List<String>>) configObj;
        log.debug("Custom object 'SLF - Custom - OneRoleAtATime' config loaded. Entries: " + roleMap.size());
    } else {
        log.error("Policy Rule: Custom object 'SLF - Custom - OneRoleAtATime' attribute 'OneRoleAtATime_Applications_Config' is not a Map. Actual type: " + (configObj != null ? configObj.getClass().getName() : "null"));
        return null; // Exit if configuration is malformed
    }
} else {
    log.error("Policy Rule: Custom object 'SLF - Custom - OneRoleAtATime' not found. Policy cannot be evaluated.");
    return null; // Exit if configuration object is missing
}

boolean violationDetected = false; // Flag to indicate if any violation was found

// Iterate through the application configurations from the Custom object
for (Map.Entry<String, List<String>> entry : roleMap.entrySet()) {
    String applicationName = entry.getKey();
    List<String> configuredRolesForApp = entry.getValue(); // Roles configured for this specific application

    List<String> matchingNewlyRequestedRoles = new ArrayList<>();
    List<String> matchingExistingRoles = new ArrayList<>();

    // Find NEWLY REQUESTED roles that match this app's configuration
    for (String singleConfiguredRole : configuredRolesForApp) {
        if (newlyRequestedRoles.contains(singleConfiguredRole)) {
            matchingNewlyRequestedRoles.add(singleConfiguredRole);
        }
    }

    // Find EXISTING roles that match this app's configuration
    for (String singleConfiguredRole : configuredRolesForApp) {
        if (existingRoles.contains(singleConfiguredRole)) {
            matchingExistingRoles.add(singleConfiguredRole);
        }
    }

    // --- VIOLATION TYPE 1: Multiple NEW roles requested for the same application ---
    if (matchingNewlyRequestedRoles.size() > 1) {
        violationDetected = true;
        if (violationMessage.length() > 0) {
            violationMessage.append("\n"); // Add a newline for multiple violation messages
        }
        violationMessage.append("Policy Violation for application: '").append(applicationName).append("'. ");
        violationMessage.append("You have requested multiple NEW roles (");
        violationMessage.append(String.join(", ", matchingNewlyRequestedRoles));
        violationMessage.append(") for this application. Please request only one role at a time.");
        log.debug("Violation: Multiple new roles requested for app '" + applicationName + "': " + matchingNewlyRequestedRoles);
    }

    // --- VIOLATION TYPE 2: Requesting any NEW role when existing configured roles are present ---
    // This applies if any NEW role was requested for this app
    // AND if the user already has any configured role for this app.
    if (!matchingNewlyRequestedRoles.isEmpty() && !matchingExistingRoles.isEmpty()) {
        violationDetected = true;
        if (violationMessage.length() > 0) {
            violationMessage.append("\n");
        }
        violationMessage.append("Policy Violation for application: '").append(applicationName).append("'. ");
        violationMessage.append("You have requested new roles (");
        violationMessage.append(String.join(", ", matchingNewlyRequestedRoles));
        violationMessage.append(") while already having existing roles (");
        violationMessage.append(String.join(", ", matchingExistingRoles));
        violationMessage.append(") for this application. Please remove existing roles before requesting new ones, or request a modification if allowed.");
        log.debug("Violation: New roles requested while existing roles present for app '" + applicationName + "'. New: " + matchingNewlyRequestedRoles + ", Existing: " + matchingExistingRoles);
    }
    // You might also want a policy that says: "You can NEVER have more than one configured role for this app AT ALL"
    // If so, you'd combine newlyRequestedRoles + existingRoles for the app and check if size > 1.
    // That's a different policy logic. This implements the "don't request new if existing" specifically.
}

// Create the PolicyViolation object ONLY if a violation was detected
if (violationDetected) {
    policyViolation = new PolicyViolation();
    policyViolation.setActive(true);
    policyViolation.setIdentity(expectedIdentity);
    policyViolation.setPolicy(policy);
    // Set the constraint if you want the violation to be linked to a specific constraint within the policy
    // policyViolation.setConstraint(constraint);
    policyViolation.setDescription(violationMessage.toString()); // Set the accumulated dynamic description
    policyViolation.setStatus(sailpoint.object.PolicyViolation.Status.Open);
    log.debug("Final Policy Violation description: " + policyViolation.getDescription());
} else {
    log.debug("No policy violations detected for identity " + identity.getName());
}

return policyViolation;
1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.