Showing posts with label Rule. Show all posts
Showing posts with label Rule. Show all posts

Thursday, February 10, 2022

Sailpoint IdentityIQ Loopback Connector Configuration

Loopback Connector is used to manage the Workgroup & Capability of Sailpoint. This Connector is part of the SSF Framework.

Below Configuration is done to manage the WG which start with  "VIS"

  • Ignore non correlated identities = true
  • Ignore identities with no entitlements = true
  • Identity filter = Workgroups.name.startsWith("VIS")

Account Customization Rule

List workgroupList = (List)object.getAttribute("workgroups.name");
List updatedWorkgroupList=new ArrayList();
if(!workgroupList.isEmpty()){
  for(String workgroupName:workgroupList){  
  if(workgroupName.startsWith("VIS")){
	updatedWorkgroupList.add(workgroupName);
  }  
 }
  if(!updatedWorkgroupList.isEmpty()){
	object.setAttribute("workgroups.name",updatedWorkgroupList);
	return object;
	}else{
	return null;
	}
}else{
return null;
}

 WorkGroup Customization Rule

import sailpoint.object.ManagedAttribute;
import java.util.Map;
import java.util.HashMap;
String workGroupName = (String) object.getAttribute("name");
if (workGroupName.startsWith("VIS")){
	object.put("privileged","Yes");
	object.setDisplayName(object.getAttribute("name"));
    object.setAttribute("description",(String)object.getAttribute("description"));
return object ;
}

Tuesday, October 12, 2021

Sailpoint IdentityIQ Group Aggregation Refresh Rule

Sailpoint IdentityIQ Group Aggregation Refresh Rule/GroupAggregationRefresh is used to set the value for the Entitlement from Target to the Entitlement Catalogue . Code is modified to take care of the update scenario also. 

	import sailpoint.object.ResourceObject;
	import sailpoint.object.ManagedAttribute;
	import sailpoint.object.Identity;

	int TIME_DIFFERENCE = 300000; // Five minutes
	
	Date modifiedDate = accountGroup.getModified();
	Date createdDate = accountGroup.getCreated();
	boolean entitlementCreated = false;
	
	if(createdDate!=null){
		
		if(modifiedDate != null){
			
			long difference = modifiedDate.getTime() - createdDate.getTime();
			if(difference <= TIME_DIFFERENCE){			
				entitlementCreated = true;				
			}
		} else {			
			entitlementCreated = true;
		}	
	} else {
	}
	if(entitlementCreated){
		Map descMap = new HashMap();
		String descriptionValue = accountGroup.getAttribute("description");
		
		if(null != descriptionValue)
			descMap.put("en_US",descriptionValue);
		else
			descMap.put("en_US","");
		accountGroup.setAttribute("sysDescriptions",descMap);	
	}
	
	Map descMap = new HashMap();
	String descriptionValue = accountGroup.getAttribute("description");
	
	if(null != descriptionValue)
		descMap.put("en_US",descriptionValue);
	else
		descMap.put("en_US","");
	
	accountGroup.setAttribute("sysDescriptions",descMap);
	String displayName = accountGroup.getAttribute("description");
	accountGroup.setDisplayName(displayName);

	return accountGroup;

Sunday, August 1, 2021

Listing Objects in Namespace at Runtime in Sailpoint IdentityIQ

 Listing Objects in Namespace at Runtime in Sailpoint IdentityIQ

import org.apache.log4j.Logger;
import org.apache.log4j.Level;

Logger log = Logger.getLogger("sailpoint.services.bshdemo");
log.setLevel(Level.DEBUG);
log.debug("Listing Variables passed to Beanshell namespace:");

// BeanShell has a "this.variables" array that we can access.

for (int i = 0 ; i < this.variables.length ; i++) {
   String varName = this.variables[i];

   Object varValue = null;
   try {
      if ("transient".equals(varName)) {
         varValue = "[reserved word]";
      } else {
         varValue = eval(varName);
      } 
   } catch (Exception ex) {
      varValue = "[eval exception]";
   }

   String varClass = "void";
   if ((void != varValue) && (null != varValue)) {
      varClass = varValue.getClass().getSimpleName();
   }

   if (void == varValue) {
       log.debug(varName + " = void");
   } else if (null == varValue) {
       log.debug(varName + " = null");
   } else {
       log.debug(varName + ": " + varClass + " = " + varValue);
   }
}
return;

Sailpoint IdentityIQ PolicyViolation WorkFlow

 PolicyViolation WorkFlow , This WF is used to modify the violation object , This will remove the violation object and will remove if anything is added through LCM .

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow explicitTransitions="true" handler="sailpoint.api.StandardWorkflowHandler" name="VIS Detective SOD Policy Violation Workflow" type="PolicyViolation">
  <Variable input="true" name="approvalObject">
    <Description>PolicyViolation to process.  Note that we use approvalObject for
      consistency with other workflows, but the violation has already
      been persisted.  Calling the commit or rollback actions will 
      have no effect.</Description>
  </Variable>
  <Variable input="true" name="approver">
    <Description>The user to receive the work item, normally the owner of the policy.</Description>
    <Script>
      <Source>
	  import sailpoint.object.Identity;
      
	  Identity newOwner= approvalObject.getOwner();
	  return newOwner.getName();
      </Source>
    </Script>
  </Variable>
  <Variable input="true" name="violator">
    <Description>The identity that has the violation.</Description>
  </Variable>
  <Variable name="approved">
    <Description>Internal variable automatically set logically true an Approval
      process completes with no rejects.
	</Description>
  </Variable>
  <Variable name="action">
    <Description>Variable that may be set in the approval page to determine 
      the action to take on this violation.  We handle violation approvals
      differently than most work items.  There is no &amp;quot;reject&amp;quot; there
      is a selection of an action (mitigate, remediate, delete, ignroe) 
      followed by buttons that always post approval.</Description>
  </Variable>
  <Variable name="expiration">
    <Description>Variable that must be set to a Date (or the String representation
      of a Date) in order to use the &amp;quot;mitigate&amp;quot; action.  This will
      be tested in the call:mitigate handler and logged if it is invalid.
      You may wish to have the worklfow do it&amp;#39;s own validation.</Description>
  </Variable>
  <Variable name="comments">
    <Description>Variable that may be set to comments to be included with
      a mitigation or remediation.</Description>
  </Variable>
  <Variable name="remediatables">
    <Description>Variable that may be set to a list of things that can
      be selected for remediation.  Currently this will only
      be set for Role SOD violations.</Description>
  </Variable>
  <Variable name="remediations">
    <Description>Variable holding the remediatables selected in the work item.</Description>
  </Variable>
  <RuleLibraries>
    <Reference class="sailpoint.object.Rule" name="Rule Library"/>
  </RuleLibraries>
  <Step icon="Default" name="Logs" posX="98" posY="126">
    <Arg value="ref:remediatables"/>
    <Script>
      <Source>
		import java.util.Map;
		import java.util.Date;
		import java.util.List;
		import java.util.HashMap;
		import java.util.ArrayList;
		import sailpoint.tools.Util;
		import sailpoint.object.Filter;	
		import sailpoint.api.ObjectUtil;		
		import java.text.ParseException;
		import java.text.SimpleDateFormat;
		import sailpoint.object.Identity;
		import sailpoint.object.QueryOptions;
		import sailpoint.api.SailPointContext;
		import sailpoint.object.EmailOptions;
		import sailpoint.object.EmailTemplate;
		import sailpoint.object.PolicyViolation;
		import sailpoint.object.ManagedAttribute;	
		import org.apache.commons.logging.Log;
		import sailpoint.tools.GeneralException;
		import sailpoint.object.IdentityEntitlement;
		import org.apache.commons.logging.LogFactory;
		import sailpoint.object.IdentitySelector.MatchTerm;

		Log logger = LogFactory.getLog("vis.workflow.visDetectiveSODPolicyViolationWorkflow");
        
		public boolean checkIfThroughLCM(String applicationName, String identityName, String entitlementName) {
			boolean wasThroughLCM = false;
		 
			StringBuilder result = new StringBuilder();
			String sDate1 = "06/05/2021";
			   
			Date date = new SimpleDateFormat("MM/dd/yyyy").parse(sDate1);
			result.append("date [").append(date).append("]\n");
			Filter dateCheckFilter = Filter.gt("created", date);

			logger.debug(" new Date dt : "+ sDate1 + " new date : " + result);
			QueryOptions  qo = new QueryOptions();

			qo.addFilter(Filter.and(Filter.eq("source","Aggregation"),Filter.eq("application.name",applicationName), Filter.eq("identity.name",identityName),Filter.eq("value",entitlementName),dateCheckFilter));
			List identityEntitlements = context.getObjects(IdentityEntitlement.class, qo);
			logger.debug("identityEntitlements :: " + identityEntitlements);
			if(identityEntitlements.size() > 0) {
				return true;
			}else {
				return false;
			}
		}
		public Map getEntitlementDetails(String entitlementValue, String applicationName) {
			QueryOptions qo = new QueryOptions();
			qo.addFilter(Filter.and(Filter.eq("value", entitlementValue)  ,   Filter.eq("application.name", applicationName)));
			Map entDetailsMap = new HashMap();
			List managedAttributes = context.getObjects(ManagedAttribute.class, qo);
			if(managedAttributes != null &amp;&amp; managedAttributes.size() > 0) {
				ManagedAttribute managedAttribute = managedAttributes.get(0);
				entDetailsMap.put("LogiplexName", managedAttribute.getAttribute("logiplexAppName"));
				entDetailsMap.put("EntitlementDescription", managedAttribute.getDescriptions().get("en_US") );
			}
			return entDetailsMap;
		}	


		//Main code starts here
		
		logger.debug("Startes Main code here");

		String piiMarkerGroup = "<<Left Group>>";
		String notificationTemplateForPolicyViolation = "VIS Policy Violation Notification Template";
		Identity violationOnwer   = approvalObject.getOwner();
		EmailTemplate violationTemplate = context.getObjectByName(EmailTemplate.class,notificationTemplateForPolicyViolation );
		Map emailVariables = new HashMap();
		String ownerEmails=   Util.listToCsv(ObjectUtil.getEffectiveEmails(context,violationOnwer));
		List entitlementsTobeAddedToViolation = new ArrayList();
		List PIIEntitlementsToBeAddedToViolation = new ArrayList();
        
		if (approvalObject != null &amp;&amp; approvalObject.getArgument("ViolatingEntitlements") != null) { 
			
			Identity identityWithViolation = approvalObject.getIdentity();
			
			String firstName = identityWithViolation.getFirstname();
			String lastName = identityWithViolation.getLastname();
			String lanId = identityWithViolation.getAttribute("lanId");
			String identityName = identityWithViolation.getAttribute("displayName");

			emailVariables.put("firstName", firstName);
			emailVariables.put("lastName", lastName);
			emailVariables.put("lanId", lanId);
			emailVariables.put("identityName", identityName);

			for (int i = 0; i &lt; approvalObject.getArgument("ViolatingEntitlements").size(); i++) {
				sailpoint.object.IdentitySelector.MatchTerm entitlementViolatingAtTop = approvalObject.getArgument("ViolatingEntitlements").get(i);
				if (entitlementViolatingAtTop != null) {       
					String applicationNameForViolatingEntitlement = "";
					String entitlementValueForViolatingEntitlement = "";
					String accountNameForViolatingEntitlement="";

					if(entitlementViolatingAtTop.getApplication() != null ){
						applicationNameForViolatingEntitlement = entitlementViolatingAtTop.getApplication().getName();
						accountNameForViolatingEntitlement= getAccountNmae(identityWithViolation, entitlementViolatingAtTop.getApplication());                                   
					}
					if(entitlementViolatingAtTop.getValue() != null) {
						entitlementValueForViolatingEntitlement = entitlementViolatingAtTop.getValue();
					}

					if(entitlementValueForViolatingEntitlement.equalsIgnoreCase(piiMarkerGroup)) {
						PIIEntitlementsToBeAddedToViolation.add(entitlementViolatingAtTop);
					}else {      
						boolean checkThruLCMmethodResult = checkIfThroughLCM(applicationNameForViolatingEntitlement, identityWithViolation.getName(), entitlementValueForViolatingEntitlement) ;      
						logger.debug("CheckThruLCMmethodResult::  " + checkThruLCMmethodResult );      
						if( checkThruLCMmethodResult == true ) {
							entitlementsTobeAddedToViolation.add(entitlementViolatingAtTop);     
							Map entDetails = getEntitlementDetails(entitlementValueForViolatingEntitlement, applicationNameForViolatingEntitlement);
				
							auditDetectiveSOD( "Violation Detected","Aggregation",lanId,entDetails.get("LogiplexName"),entitlementValueForViolatingEntitlement,accountNameForViolatingEntitlement,approvalObject,"Aggregation",lanId );  
				
							emailVariables.put("entitltmentName",entitlementValueForViolatingEntitlement);
							emailVariables.put("entitltmentDesc",entDetails.get("EntitlementDescription"));
			   
							if(violationTemplate!= null){
								logger.debug("Violation temp loop");
								Identity policyViolationApproverObject   = approvalObject.getOwner();							
								if(null!=policyViolationApproverObject &amp;&amp; ( Util.listToCsv(ObjectUtil.getEffectiveEmails(context,policyViolationApproverObject)) != null)){
									approverEmails =  Util.listToCsv(ObjectUtil.getEffectiveEmails(context,policyViolationApproverObject));		
									EmailOptions ops = new EmailOptions(approverEmails, emailVariables);            
									try {
										context.sendEmailNotification(violationTemplate, ops);
									}catch(Exception e){ 
										log.error("Could not send email to GS team as : " + e);
									}
									logger.debug("Email Sent ");
								}
							}
						}
					}
				}
			}  
		}		
		if(entitlementsTobeAddedToViolation != null &amp;&amp; entitlementsTobeAddedToViolation.size() >0){         
			entitlementsTobeAddedToViolation.addAll(PIIEntitlementsToBeAddedToViolation) ;
			approvalObject.setArgument("ViolatingEntitlements",entitlementsTobeAddedToViolation );
			context.saveObject(approvalObject);
			context.commitTransaction();
			logger.debug("OBJECT persisted");
        }else{
			context.removeObject(approvalObject);
			context.commitTransaction();
			logger.debug("OBJECT DELETED");
        }
		
		logger.debug("End of workflow Step");
      </Source>
    </Script>
    <Transition to="End"/>
  </Step>
  <Step icon="Stop" name="End" posX="160" posY="126"/>
  <Step icon="Start" name="Start" posX="28" posY="10">
    <Transition to="Logs"/>
  </Step>
</Workflow>

Saturday, July 17, 2021

Sailpoint IdentityIQ - Policy Violation Rule

 Policy Violation Rule (This rule is used to format a PolicyViolation object)

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="VIS Policy Violation Rule" type="Violation">
  <Description>This rule is used to format a PolicyViolation object.</Description>
  <Signature returnType="PolicyViolation">
    <Inputs>
      <Argument name="log">
        <Description>
          The log object associated with the SailPointContext.
        </Description>
      </Argument>
      <Argument name="context">
        <Description>
          A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
        </Description>
      </Argument>
      <Argument name="identity">
        <Description>
          The Identity in violation.
        </Description>
      </Argument>
      <Argument name="policy">
        <Description>
          The Policy being violated.
        </Description>
      </Argument>
      <Argument name="constraint">
        <Description>
          The Constraint being violated.
        </Description>
      </Argument>
      <Argument name="violation">
        <Description>
          The PolicyViolation object.
        </Description>
      </Argument>
      <Argument name="state">
        <Description>
          A Map containing state information.
        </Description>
      </Argument>
    </Inputs>
    <Returns>
      <Argument name="violation">
        <Description>
          The formatted PolicyViolation object.
        </Description>
      </Argument>
    </Returns>
  </Signature>
  <Source>
  import java.util.List;
  import sailpoint.api.PolicyUtil;
  import sailpoint.api.PolicyUtil.EntitlementSummary;
  import sailpoint.api.PolicyUtil.RoleSummary;
  import sailpoint.api.PolicyUtil.ApplicationSummary;
  import sailpoint.api.PolicyUtil.ItemSummary;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import sailpoint.object.Attributes;
  import sailpoint.object.Filter;
  import sailpoint.object.ManagedAttribute;
  import sailpoint.object.QueryOptions;

  public ManagedAttribute getOriginalEntitlementObject(String entitlementDNValue, String appName) {

    customLog.debug("Entering getOriginalEntitlementObject : "+entitlementDNValue+" : "+appName);

    ManagedAttribute managedAttribute = null;
    Filter filterValue = Filter.eq("value",entitlementDNValue);
    Filter filterAppType =Filter.eq("application.name",appName);
    Filter filterAndCond = Filter.and(filterValue,filterAppType);
    QueryOptions qo = new QueryOptions();
    qo.add(filterAndCond);
    List entitlements = context.getObjects(ManagedAttribute.class,qo);
    customLog.debug("Entering getOriginalEntitlementObject : size is" +entitlements.size());
    if(entitlements.size()&gt; 0){
      for(ManagedAttribute entitlement : entitlements){                                            
        managedAttribute = entitlement;
      }
    }
    customLog.debug("Exiting getOriginalEntitlementObject: "+managedAttribute);
    return managedAttribute;
  }

  private summarizeApp(StringBuilder b, ApplicationSummary app) {
    List atts = app.attributes;
    if (atts != null &amp;&amp; atts.size() &gt; 0) {

      customLog.debug("app.name: "+ app.name);
      b.append(" account on: ["+app.name);
      //b.append(": ");
      for (int i = 0 ; i &lt; atts.size() ; i++) {
        ItemSummary as = atts.get(i);
        if (i &gt; 0) b.append(" ");
        // b.append(as.name);
        customLog.debug("as.name: "+ as.name);
        // b.append("=");
        List values = as.values;
        customLog.debug("as.values: "+ as.values);
        if (values == null) {
          b.append("null");
        }
        else if (values.size() &gt; 1) {
          // this will bracket it with []
          b.append(" with entitlements as: '");
          for(int j=0;j &lt; values.size() ; j++){
            ManagedAttribute managedAttribute = getOriginalEntitlementObject(values.get(j).toString(),app.name);
            b.append(managedAttribute.getDisplayName());
            b.append(", ");
          }
          b.append("'");
          //  b.append(values.toString());
        }
        else if(values.size() == 1){
          b.append(" with entitlements as: '");
          //  b.append("'");
          // b.append(values.get(0).toString());
          // b.append("'");
          ManagedAttribute managedAttribute = getOriginalEntitlementObject(values.get(0).toString(),app.name);
          b.append("'");
          customLog.debug("summarizeApp: "+ managedAttribute.getDisplayName());
          b.append(managedAttribute.getDisplayName());
          b.append("'");
        }
        b.append("]");
      }

    }

    List perms = app.permissions;
    if (perms != null &amp;&amp; perms.size() &gt; 0) {
      for (int i = 0 ; i &lt; perms.size() ; i++) {
        ItemSummary ps = perms.get(i);

        b.append(app.name);
        b.append(": ");

        List values = ps.values;
        if (values == null) {
          b.append("none");
        }
        else if (values.size() &gt; 1) {
          // this will bracket it with []
          b.append(values.toString());
        }
        else {
          b.append("'");
          b.append(values.get(i).toString());
          b.append("'");
        }

        b.append(" on ");
        b.append(ps.name);
        b.append(" ");
      }
    }
  }

  private summarizeRole(StringBuilder b, RoleSummary role) {
    if (role.name != null) {
      b.append("Role: ");
      b.append(role.name);
      b.append(" ");
    }
    List apps = role.applications;
    if (apps != null) {
      for (int i = 0 ; i &lt; apps.size() ; i++)
        summarizeApp(b, apps.get(i));
    }
  }

  private summarizeRoles(StringBuilder b, List roles) {
    if (roles != null) {
      for (int i = 0 ; i &lt; roles.size() ; i++) {
        summarizeRole(b, roles.get(i));
      }
    }
  }

  private static Log customLog = LogFactory.getLog("vis.rule.visViolation");
  customLog.debug("Entering Policy Volidation Rule for: "+ identity.getStringAttribute("name"))
	
  EntitlementSummary summary =PolicyUtil.summarizeViolationEntitlements(context, identity,violation, null);

  if (summary != null) {
      StringBuilder b = new StringBuilder();
      summarizeRoles(b, summary.left);
      b.append("--- conflicts with --- ");
      summarizeRoles(b, summary.right);
      violation.setDescription(b.toString());
  }
  </Source>
</Rule>

Saturday, July 3, 2021

Sailpoint IdentityIQ - Rule - PostIterate

 Rule  - PostIterate

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="EXP Post Iterate Rule" type="PostIterate">
  <Description>
	This rule is called after the connector processes the data in a file.
	This rule archives the data file to the archive folder with the file name appended with the latest timestamp.   
  </Description>
  <Signature returnType="void">
    <Inputs>
      <Argument name="log">
        <Description>
          The log object associated with the SailPointContext.
        </Description>
      </Argument>
      <Argument name="context">
        <Description>
          A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
        </Description>
      </Argument>
      <Argument name="application">
        <Description>
          Application being iterated.
        </Description>
      </Argument>
      <Argument name="schema">
        <Description>
          Schema requested during iteration.
        </Description>
      </Argument>
      <Argument name="stats">
        <Description>
            A map of the stats for the current file that was just iterated Contains keys:
				fileName : (String) filename of the file about to be processed
				absolutePath : (String) absolute filename
				length : (Long) length in bytes
				lastModified : (Long) last time the file was updated Java GMT
				columnNames : (List) column names that were used during the iteration
				objectsIterated : (Long) total number of objects iterated during this run
        </Description>
      </Argument>
    </Inputs>
  </Signature>
  <Source>
	
	    import java.io.File;
		import java.text.SimpleDateFormat;
		import java.util.Date;

	   public boolean archiveFile(String path, String fileName, String extension){

		boolean success = true;
		Date date = new Date();
		String timeStamp = new SimpleDateFormat("MM-dd-yyyy_HH:mm:ss").format(date);

		String archivePath = path+"/archive";
		File archiveFolder = new File(archivePath);

		String oldFileName = path+"/"+fileName+extension;
		File oldFile = new File(oldFileName);
		if (!archiveFolder.exists()){
			success = archiveFolder.mkdir();
		}
		if(success){
			File newFile = new File(archiveFolder+"/"+fileName+"_"+timeStamp+extension);
			success = oldFile.renameTo(newFile);
		}
		return success;
	}
	
	System.out.println("Entering Post Iterate Rule");
	
	String absolutePath = stats.get("absolutePath");
	String fileName = stats.get("fileName");
	String fileNameWithoutExtension = fileName.substring(0,fileName.indexOf("."));
	String extension = fileName.substring(fileName.indexOf("."),fileName.length());
	String filePath = absolutePath.replace("/"+fileName, "");
		
		System.out.println("filePath : "+filePath);
		System.out.println("fileNameWithoutExtension : "+fileNameWithoutExtension);
		System.out.println("extension : "+extension);
	
	boolean success = archiveFile(filePath, fileNameWithoutExtension, extension);	
	System.out.println("Exiting Post Iterate Rule");	
  
  </Source>
</Rule>

Tuesday, June 8, 2021

Rule - ManagerCorrelation Example

 ManagerCorrelation Sample Rule for Sailpoint IdentityIQ

import java.util.Map;
import java.util.HashMap;
import sailpoint.object.Identity;
import sailpoint.object.Filter;
import sailpoint.object.QueryOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


Map map = new HashMap();
String value = (String) link.getAttribute("supemployeeNumber");

    //If supervisorId is not null, then proceed to validate if an identity exists in IIQ with the same employeeNumber.
if (value != null) {
	QueryOptions queryOptions = new QueryOptions();
	queryOptions.add(Filter.eq("employeeNumber", value));
	Iterator iterator = context.search(Identity.class, queryOptions);

	//If an identity exists in IIQ with the same employeeNumber, proceed to return the manager.
	if (iterator.hasNext()) {
		map.put("identity", (Identity) iterator.next());
		return map;
	}
}

     //Return null explicitly in case valid manager is not found.
Identity identity = link.getIdentity();
if (identity.getManager() != null) {
	identity.setManager(null);
	context.saveObject(identity);
}
return null;

Friday, October 9, 2020

Sailpoint Identity IQ CertificationAutomaticClosing Rule

We have seen many time to send the Expiry Notification , when the Access Review is Expired , ie no action is taken CertificationAutomaticClosingRule can be used to send the notification , here is the sample code for using this Rule. 

  import sailpoint.object.Identity;
  import sailpoint.object.EmailOptions;
  import sailpoint.object.EmailTemplate;  
  import sailpoint.object.Certification;
  import org.apache.commons.logging.Log;
  import sailpoint.object.SignOffHistory;
  import org.apache.commons.logging.LogFactory;

  System.out.println("Entering Certification Auto closing rule.");

  List toAddresses = Arrays.asList("");

  List certifiers = certification.getCertifiers();
  Identity certifier = context.getObjectByName(Identity.class,certifiers.get(0).toString());
  System.out.println("certifier : " + certifier);

  if(null != certifier){
    toAddresses = Arrays.asList(certifier.getEmail());
    System.out.println("toAddresses : " + toAddresses);
  }

  String tplName = "Certification Expired Notification";
  EmailTemplate template = context.getObjectByName(EmailTemplate.class, tplName);
  if (null == template) {  
    System.out.println("Could not find email template [ " + tplName + "]");
    return;
  }

  Map args = new HashMap();  
  args.put("certification", certification);
  args.put("ownerName", certifier.getDisplayName());

  System.out.println("certification : " + certification);
  System.out.println("ownerName : " + certifier.getDisplayName());

  certification.addSignOffHistory((Identity)context.getObjectByName(Identity.class, "spadmin"));
  
  //Send Notifciation of Expiry
  
  System.out.println("Exiting Certification Auto closing rule");
  return ;  

Sailpoint Identity IQ CertificationSignOffApprover Rule

We have seen many time to send the Completion Notification , when the Access Review is completed CertificationSignOffApprover Rule can be used to send the notification , here is the sample code for using this Rule. 

  import java.util.Map;
  import java.util.List;
  import java.util.Arrays;
  import sailpoint.object.Identity;
  import sailpoint.api.SailPointContext;
  import sailpoint.object.Certification;
  import sailpoint.object.EmailOptions;
  import sailpoint.object.EmailTemplate; 
  import sailpoint.object.SignOffHistory; 
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;

  System.out.println("Entering Certification Sign Off Rule.");


  List signOffList=certification.getSignOffHistory();
  System.out.println("signOffList : " + signOffList);


  for(SignOffHistory signOffHistory:signOffList){
    if(signOffHistory.getSignerName().equalsIgnoreCase("spadmin")){      
      System.out.println("signOffHistory.getSignerName() : " + signOffHistory.getSignerName());
      return null;
    }
  }

  Date activationDate = certification.getActivated();
  System.out.println("activationDate : " + activationDate);

  if (activationDate != null) {

    List certifiers = certification.getCertifiers();
    Identity certifier = context.getObjectByName(Identity.class,certifiers.get(0).toString());
    System.out.println("certifier : " + certifier);

    List toAddresses = Arrays.asList("");
    if (null != certifier) {
      toAddresses = Arrays.asList(certifier.getEmail());
    }

    String tplName = "Certification Completion Notification";
    EmailTemplate template = context.getObjectByName(EmailTemplate.class, tplName);
    if (null == template) {
      System.out.println("Could not find email template [ " + tplName + "]");
      return null;
    }

    Map args = new HashMap();
    args.put("certification", certification);
    args.put("ownerName", certifier.getDisplayName());

    //Send Notifciation of completion 
	
  }
  System.out.println("Exiting Certification Sign Off Rule");

  return null;

Thursday, August 20, 2020

Sailpoint IdentityIQ Export Object using Sailpoint API

All Sailpoint IdentityIQ Object can be exported using the API also , hear is the example of the code which is used to export all the Bundle object present in the instance.

Generally we use the console to export the sailpoint identityIQ object 

checkout <class name> <object name or ID> <file> [-clean [=id,created…]]

Similar thing can be done using the API also, below is the sample source code 

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import sailpoint.api.SailPointContext;
import sailpoint.api.SailPointFactory;
import sailpoint.object.Bundle;
import sailpoint.object.Filter;
import sailpoint.object.QueryOptions;
import sailpoint.server.ExportVisitor;
import sailpoint.server.Exporter.Cleaner;
import sailpoint.spring.SpringStarter;
import sailpoint.tools.GeneralException;
import sailpoint.tools.Util;
		
               List propertiesToClean = new ArrayList();
		propertiesToClean.add("id");
		propertiesToClean.add("created");
		propertiesToClean.add("modified");
		Cleaner cleaner = new Cleaner(propertiesToClean);
		
		
		try {
			List<Bundle> roles = context.getObjects(Bundle.class);
			System.out.println(roles);
			  for (Bundle bun : roles){
			    try{
			    	if(null !=bun.getType() && bun.getType().equalsIgnoreCase("business")){
						//new ExportVisitor(context).visit(bun);
						String xml = bun.toXml();
						System.out.println("raw xml" + xml);
					if (propertiesToClean != null){
						xml = cleaner.clean(xml);
						System.out.println("clean xml" + xml);
					}
					Util.writeFile("C://Temp//"+bun.getName()+".xml", xml);		    	
			    	}
			    }catch (GeneralException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}			
			  }
		} catch (GeneralException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				SailPointFactory.releaseContext(context);
			} catch (GeneralException e) {
				e.printStackTrace();
			}
		}
		
	}



Saturday, March 28, 2020

Sailpoint Identity IIQ Complex Correlation Rule


Here I have written a Complex Correlation Rule which can be used for the Application where the AccountIdentitfier from the Application matches any of the multiple identity Attribute such as the name, email,employee Number , Since the Correlation is the Case sensitive so most of the scenario we see the issue with the correlation config or the default correlation doesn't work.


<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="Application Correlation Rule" type="Correlation">
  <Description>
 Rule to correlate accounts to identities based on lanId.
  </Description>
  <Signature returnType="Map">
    <Inputs>
      <Argument name="log">
        <Description>
          The log object associated with the SailPointContext.
        </Description>
      </Argument>
      <Argument name="context">
        <Description>
          A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
        </Description>
      </Argument>
      <Argument name="environment" type="Map">
        <Description>
          Arguments passed to the aggregation task.
        </Description>
      </Argument>
      <Argument name="application">
        <Description>
          Application being aggregated.
        </Description>
      </Argument>
      <Argument name="account">
        <Description>
          A sailpoint.object.ResourceObject returned from the
          collector.
        </Description>
      </Argument>
      <Argument name="link">
        <Description>
          Existing link to this account.
        </Description>
      </Argument>
    </Inputs>
    <Returns>
      <Argument name="identityName">
        <Description>
          The name of an Identity object.
        </Description>
      </Argument>
      <Argument name="identity">
        <Description>
          A fully resolved Identity object if the rule wants
          to do its own queries to locate the identity.
        </Description>
      </Argument>
      <Argument name="identityAttributeName">
        <Description>
          The name of the extended attribute that can be used
          to locate an existing identity.
        </Description>
      </Argument>
      <Argument name="identityAttributeValue">
        <Description>
          The value of the named extended attribute that can be used
          to locate an existing identity. This attribute is used
          together with the identityAttributeName argument.
        </Description>
      </Argument>
    </Returns>
  </Signature>
  <Source>

Map returnMap = new HashMap();
  
String VIS_APP_LAN_ID = "AppliCationAccountIdentifier";
String VIS_IDENTITY_NAME = "name";
String VIS_IDENTITY_EMAIL = "email";
String VIS_IDENTITY_EMPLOYEE_NUMBER = "employeeNumber";

Map objectPropertiesFetched = new HashMap();
List objectPropertiesToFetch = new ArrayList();
objectPropertiesToFetch.add(VIS_IDENTITY_NAME);

Filter filter = null;
String appLanId = null;

Log log = LogFactory.getLog("vishal.rule.CorrelationRule");
log.debug("Entering Correlation Rule");

try{
 appLanId = account.getAttribute(VIS_APP_LAN_ID);
 filter = Filter.or( Filter.ignoreCase(Filter.eq(VIS_IDENTITY_NAME, appLanId)), Filter.ignoreCase(Filter.eq(VIS_IDENTITY_EMAIL, appLanId)), Filter.ignoreCase(Filter.eq(VIS_IDENTITY_EMPLOYEE_NUMBER, appLanId)) );
 objectPropertiesFetched = getObjectProperties(Identity.class, filter, objectPropertiesToFetch);
 if(objectPropertiesFetched.get(VIS_IDENTITY_NAME) != null){ 
  returnMap.put( "identityName", objectPropertiesFetched.get(VIS_IDENTITY_NAME));
 }
}catch(Exception exception){
 log.error("Exception caught in Correlation Rule: "+exception);
}
return returnMap;

  </Source>
</Rule>

We need to make sure that getObjectProperties() need to be added to some Rule Library and that rule library need to be referenced in the above rule using 


<ReferencedRules>
    <Reference class="sailpoint.object.Rule" name="VIS Rule Library"/>
 </ReferencedRules> 


public Map getObjectProperties(java.lang.Class objectType, Filter searchFilter, List propertiesToFetch){
 Object[] objectProperties;
 Map propertiesMap = new HashMap();
 QueryOptions queryOptions = new QueryOptions();
 queryOptions.addFilter(searchFilter);
 //iterator to iterate over managed attributes to fetch properties
 Iterator iterator = context.search(objectType, queryOptions, propertiesToFetch);
 //Assign iterator to objectProperties if iterator hasNext
 if(iterator.hasNext()){
  objectProperties = iterator.next();
  if (objectProperties != null ){
   //invoke method propertyArrayToMap to retrieve a map of property names and values
   propertiesMap = propertyArrayToMap(objectProperties, propertiesToFetch);
  }       
 } 
 Util.flushIterator(iterator);
 return propertiesMap; 
}