Tuesday, July 20, 2021

Custom Report In Sailpoint IdentityIQ Using JavaDataSource

 Custom Report In Sailpoint IdentityIQ Using JavaDataSource , This Report Will give the Deleage Set for the User between the Dates (Start and End Date)

Form

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Form PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Form hidden="true" name="VIS Custom Delegate Identity Report Form" type="Report">
  <Section columns="2" label="Request Parameters" name="customProperties">
    <Field columnSpan="1" displayName="Forward Start Date" helpKey="rept_id_risk_help_last_login_start" name="forwardStartDate" type="date" value="ref:forwardStartDate">
      <Attributes>
        <Map>
          <entry key="endDate" value="true"/>
        </Map>
      </Attributes>
    </Field>
    <Field columnSpan="1" displayName="Forward End Date" helpKey="rept_id_risk_help_last_login_end" name="forwardEndDate" type="date" value="ref:forwardEndDate">
      <Attributes>
        <Map>
          <entry key="endDate" value="true"/>
        </Map>
      </Attributes>
    </Field>
  </Section>
</Form>

 TaskDefinition 

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE TaskDefinition PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<TaskDefinition executor="sailpoint.reporting.LiveReportExecutor" name="VIS Custom Delegate Identity Report" progressMode="String" resultAction="Delete" subType="Identity and User Reports" template="true" type="LiveReport">
  <Attributes>
    <Map>
      <entry key="report">
        <value>
          <LiveReport disablePreview="true" title="Identity Forwarding Report">
            <DataSource dataSourceClass="com.vis.reports.ExperianCustomUserForwardingDataSource" type="Java"/>
            <ReportForm>
              <Reference class="sailpoint.object.Form" name="VIS Custom Delegate Identity Report Form"/>
            </ReportForm>
            <Columns>
              <ReportColumnConfig field="identity" header="rept_usr_forward_col_identity" sortable="true" width="110"/>
              <ReportColumnConfig field="displayName" header="rept_usr_forward_col_identity_display" sortable="true" width="110"/>
              <ReportColumnConfig field="identityFirstName" header="First Name" sortable="true" width="110"/>
              <ReportColumnConfig field="identityLastName" header="Last Name" sortable="true" width="110"/>
              <ReportColumnConfig field="identityEmpNumber" header="Employee Number" sortable="true" width="110"/>
              <ReportColumnConfig field="identityStatus" header="Employee Status" sortable="true" width="110"/>
              <ReportColumnConfig field="identityEmail" header="Email" sortable="true" width="110"/>
              <ReportColumnConfig field="forwardingUser" header="Delegate User" width="110"/>
              <ReportColumnConfig field="forwardingDisplayName" header="Delegate User Display Name" width="110"/>
              <ReportColumnConfig field="startDate" header="Delegate StartDate" width="110"/>
              <ReportColumnConfig field="endDate" header="Delegate EndDate" width="110"/>
              <ReportColumnConfig field="forwardingEmail" header="Delegate Email" property="name" width="110"/>
              <ReportColumnConfig field="forwardingEmpNumber" header="Delegate Employee Number" width="110"/>
              <ReportColumnConfig field="forwardingFirstName" header="Delegate First Name" width="110"/>
              <ReportColumnConfig field="forwardingLastName" header="Delegate Last Name" width="110"/>
            </Columns>
          </LiveReport>
        </value>
      </entry>
    </Map>
  </Attributes>
  <Description>A list of users who have forwarding configured and to which user.</Description>
  <RequiredRights>
    <Reference class="sailpoint.object.SPRight" name="FullAccessUserReport"/>
  </RequiredRights>
  <Signature>
    <Inputs>
      <Argument name="forwardStartDate" type="date">
        <Description>delegation start date</Description>
      </Argument>
      <Argument name="forwardEndDate" type="date">
        <Description>delegation end date</Description>
      </Argument>
    </Inputs>
  </Signature>
</TaskDefinition>

 Report JavaDataSource src code

package com.vis.reports;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import sailpoint.api.SailPointContext;
import sailpoint.object.Attributes;
import sailpoint.object.Identity;
import sailpoint.object.LiveReport;
import sailpoint.object.QueryOptions;
import sailpoint.object.Sort;
import sailpoint.reporting.datasource.JavaDataSource;
import sailpoint.task.Monitor;
import sailpoint.tools.GeneralException;


public class CustomUserForwardingDataSource implements JavaDataSource{
	
	private Map<String, Object> currentRow;
	private QueryOptions baseQueryOptions;
	private SailPointContext context;
	private Map customQueryOptions = new HashMap();
	private Integer startRow;
	private Integer pageSize;
	private Iterator<Map<String, Object>> finalobjects;
	private Map<String, Object> object = new HashMap<String, Object>();	
	private Iterator<Entry<String, Object>> mapIterator;
	private List<Map<String, Object>> objectList = new ArrayList<Map<String, Object>>();
	
	Log logger = LogFactory.getLog("vis.task.CustomTask");
	
	@SuppressWarnings("unchecked")
	public void initialize(SailPointContext context, LiveReport report,Attributes<String, Object> arguments, String groupBy, List<Sort> sort) throws GeneralException {
		logger.info("entered initialize method of  CustomUserForwardingDataSource with :::arguments : "+arguments);
		this.context = context;
		baseQueryOptions = new QueryOptions();	
		try {			
			SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-YYYY");			
			if(arguments.containsKey("forwardStartDate")) { 
			    String startDate= formatter.format(arguments.get("forwardStartDate"));   
				customQueryOptions.put("forwardStartDate",startDate);	
				logger.info("forwardStartDate------convert" +startDate);
			}
			if(arguments.containsKey("forwardEndDate")) {
			    String endDate= formatter.format(arguments.get("forwardEndDate"));
				customQueryOptions.put("forwardEndDate",endDate);				
				logger.info("forwardEndDate------convert" +endDate);
			}			
			prepare();			
		} catch(Exception ex) {
			logger.info("Exception occured in initialize method CustomUserForwardingDataSource :::");
			ex.printStackTrace();
			logger.error(ex.getMessage());
		 }
	}
	
	private void prepare() throws GeneralException{
		
		logger.info("Enter in method prepare() of CustomUserForwardingDataSsource Class::::");
		Map<String, Object> itemMap = null;		
		String sql;
		String forwardStartDate = "";
		String forwardEndDate = "";		
		try {			
			if(null != customQueryOptions.get("forwardStartDate")) {
				
				forwardStartDate = (String) customQueryOptions.get("forwardStartDate");
			} 
			if(null != customQueryOptions.get("forwardEndDate")) {
				forwardEndDate = (String)customQueryOptions.get("forwardEndDate");
			}
	
			//SQL Query to fetch the delegated identity details with in date range.
	
        sql= "with A as(select name,display_name,EXTRACT(xmltype(preferences),'/Map/entry[@key=\"forward\"]/@value').getStringVal() as delegateduser,EXTRACT(xmltype(preferences),'/Map/entry[@key=\"forwardStartDate\"]/value/Date/text()').getStringVal() as forwardStartDate ,EXTRACT(xmltype(preferences),'/Map/entry[@key=\"forwardEndDate\"]/value/Date/text()').getStringVal() as forwardEndDate from spt_identity where preferences like ('%forward%'))"
		+ "select A.name as identity,A.display_name as displayName,A.delegateduser as forwardingUser, A.forwardStartDate as startDate,A.forwardEndDate as endDate from A "
		+ "where To_date('1970-01-01 00', 'yyyy-mm-dd hh24') + (A.forwardStartDate) / 1000 / 60 / 60 / 24 >=" 
		+ "'"+forwardStartDate+"'"+" and To_date('1970-01-01 00', 'yyyy-mm-dd hh24') + (A.forwardEndDate) / 1000 / 60 / 60 / 24<="
		+ "'"+forwardEndDate+"'";

		logger.info("Sqlquery build---------"+sql);
		System.out.println("Sqlquery build---------"+sql);
			
			Connection connection = context.getJdbcConnection();
	           Statement  stmt = connection.createStatement();
	           if (stmt == null){
	     			throw new Exception("Unable to create stmt");
	     		}
	           
	           ResultSet rs=stmt.executeQuery(sql);
	           if (rs == null){
	               throw new Exception("Result set is null");
	             }
	           ResultSetMetaData md = rs.getMetaData();
	           int columns = md.getColumnCount();	          
	           while (rs.next()){
	        	     itemMap = new HashMap<String, Object>();
				     for(int i=1; i<=columns; ++i){           
				    	 itemMap.put(md.getColumnName(i),rs.getObject(i));
				     }				     
				     mapIterator = itemMap.entrySet().iterator();				     
				     while(mapIterator.hasNext()) {
				    	 Entry<String, Object> entry = 	mapIterator.next();	 
				    	// logger.info("Item map entries::::"+entry.getKey() + ": " + entry.getValue());
				     }
				     
				     objectList.add(itemMap);				    
	           }
	           			           		
	           finalobjects = objectList.iterator();
	           
		}catch(Exception ex){
			System.out.println("Error occured in prepare() method of CustomUserForwardingDataSsource Class:::");
			ex.printStackTrace();
			logger.error(ex.getMessage());
		}
	}

	public Object getFieldValue(String fieldName) throws GeneralException {
		
		logger.info("Enter into getFieldValue() method of CustomUserForwardingDataSsource Class:::");;
		
     	Identity identity = this.context.getObjectByName(Identity.class, (String)this.object.get("IDENTITY"));		
		Identity delegateId = this.context.getObjectByName(Identity.class, (String)this.object.get("FORWARDINGUSER"));				
		SimpleDateFormat formatteddate = new SimpleDateFormat("MM/dd/yyyy");		
		if(fieldName.equals("identity")) {			
			return this.object.get("IDENTITY");
		}else if(fieldName.equals("displayName")) {			
			return this.object.get("DISPLAYNAME");			
		}else if(fieldName.equals("identityFirstName")) {
			return identity.getFirstname();
		}else if(fieldName.equals("identityLastName")) {
			return identity.getLastname();
		}else if(fieldName.equals("identityEmpNumber")) {
			return identity.getAttribute("employeeNumber");
		}else if(fieldName.equals("identityStatus")) {
			return identity.getAttribute("employeeStatus");
		}else if(fieldName.equals("identityEmail")) {
			return identity.getEmail();
		}else if(fieldName.equals("forwardingUser")) {
			return this.object.get("FORWARDINGUSER");
		}else if(fieldName.equals("startDate")) {					
			Date d = new Date();
			 if(this.object.get("STARTDATE") != null) {
				 long milliSeconds= Long.parseLong((String) this.object.get("STARTDATE"));
			    d.setTime(milliSeconds);
			    String startDate = formatteddate.format(d);
			    return startDate;
			 }
				 return "";
		}
		else if(fieldName.equals("endDate")) {			
			Date d = new Date();
			 if(this.object.get("ENDDATE") != null) {
				 long milliSeconds= Long.parseLong((String) this.object.get("ENDDATE"));
			    d.setTime(milliSeconds);
			    String endDate = formatteddate.format(d);
			    return endDate;
			 }
				 return "";
		}else if(fieldName.equals("forwardingEmail")) {
			return delegateId.getEmail();
		}
		else if(fieldName.equals("forwardingEmpNumber")) {
			return delegateId.getAttribute("employeeNumber");
		}else if(fieldName.equals("forwardingFirstName")) {
			return delegateId.getFirstname();
		}
		else if(fieldName.equals("forwardingLastName")) {
			return delegateId.getLastname();
		}else if(fieldName.equals("forwardingDisplayName")) {
			return delegateId.getDisplayName();
		}
		else {
			throw new GeneralException("Unknown column '" + fieldName + "'");
		} 	
	}
	
	public int getSizeEstimate() throws GeneralException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void close() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setMonitor(Monitor arg0) {
		// TODO Auto-generated method stub
		
	}

	public Object getFieldValue(JRField jrField) throws JRException {
		String fieldName = jrField.getName();
		try {			
			return getFieldValue(fieldName);
			
		} catch (GeneralException e) {
			throw new JRException(e);
		}
	}

	public boolean next() throws JRException {
		boolean hasMore = false;
		 
		if (this.finalobjects != null) {
			hasMore = this.finalobjects.hasNext();
			if (hasMore) {
				this.object = this.finalobjects.next();
			} else {
				this.object = null;
			}

		}
		return hasMore;
	}

	@Override
	public void setLimit(int startRow, int pageSize) {
		this.startRow = startRow;
		this.pageSize = pageSize;

	}

	@Override
	public String getBaseHql() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryOptions getBaseQueryOptions() {
		return baseQueryOptions;
	}
}

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>