Search This Blog

Friday, June 5, 2020

Customizing SailPoint Task Definitions - Run with Response

Subject: Batch Processing in SailPoint

Regarding: Adding responses to a batch process using Run Rule

Creating a TaskDefinition for running a rule is normally performed by the following:

Setup -> Tasks
New Task -> Run Rule

Enter the details such as what you want the rule to be named, description, then the rule to be executed.  Save and Run


Once you have done this, you will have a framework TaskDefinition with the following elements:

<Attributes>
  <Map>
    <entry key="ruleName" value="the rule you chose"/>
  </Map>
</Attributes>

and also:

<Parent>
  <Reference class="sailpoint.object.TaskDefinition" name="Run Rule"/>
</Parent>

You may want to output some results.  The issue with this is that the Run Rule normally does not have a section for outputs.

To fix this you can add the following elements:

<Signature>
  <Returns>
    <Argument name="totalCount" type="int">
      <Prompt>Total users processed</Prompt>
    </Argument>
    <Argument name="resultString" type="string">
      <Prompt>Results:
    </Argument>
  </Returns>
<Signature>

You also can add this to a clone of Run Rule and use that as a template for new rules.  But this does not populate the values.
 
To populate the values, the following is needed in the rule:
 
 (imports)
import sailpoint.tools.Message;
import sailpoint.tools.Message.Type;
import sailpoint.object.Attributes;
import sailpoint.object.TaskResult;
import sailpoint.object.TaskResult.CompletionStatus;

variables:
int resultCount=0;
String resultString="";

Set these values in your code.

Then just before the return:

if(taskResult!=void) {
  taskResult.addMessage(new Message(Message.Type.Info,"Completed Successfully", null));
  Attributes resultAttr=new Attributes();
  resultAttr.put("totalCount",new Integer(resultCount));
  resultAttr.put("resultString",resultString);
  taskResult.setAttributes(resultAttr);
  taskResult.setCompletionStatus(TaskResult.CompletionStatus.Success);
}

I use a StringBuffer instead of concatenating the resultString, and then set resultString to the toString() result of the StringBuffer.


Inputs:

If you want to add inputs to the Run Rule task definition, you would need to start by pulling the signature inputs from Run Rule.  From there you can add fields as you would any TaskDefinition.

For example:

<Signature>
  <Inputs>
    <Argument helpKey="help_task_run_rule_rule" name="ruleName" required="true" type="Rule">
      <Prompt>label_rule</Prompt>
    </Argument>
    <Argument helpKey="help_task_run_rule_ruleconfig" name="ruleConfig" type="string">
      <Prompt>label_rule_config</Prompt>
    </Argument>
    <Argument helpKey="Enter action to be taken" name="action" type="string">
      <Prompt>Action</Prompt>
    </Argument>
  </Inputs>
</Signature>

In the rule you can use the following code to check for action:

String actionStr=null;
if(config.containsKey("action"))
  actionStr=config.get("action");
}

then later you can check the value of actionStr
If nothing was entered the value will not be in config



Customizing SailPoint Task Definitions - Custom inputs

Subject: Batch Processing in SailPoint

Regarding: Using a rule to execute batch processing, with custom inputs that are more easily explained to a client


Creating a TaskDefinition for running a rule is normally performed by the following:

Setup -> Tasks
New Task -> Run Rule

Enter the details such as what you want the rule to be named, description, then the rule to be executed.  Save and Run

Once you have done this, you will have a framework TaskDefinition with the following elements:

<Attributes>
  <Map>
    <entry key="ruleName" value="the rule you chose"/>
  </Map>
</Attributes>

and also:

<Parent>
  <Reference class="sailpoint.object.TaskDefinition" name="Run Rule"/>
</Parent>

Customizing this involves creating the following elements:

<Signature>
  <Inputs>
    <Argument helpKey="Text for when user mouses over question mark"
        name="variableName" type="datatype">
      <Prompt>Text on page</Prompt>
    </Argument>
  </Inputs>
</Signature>

Each argument is displayed as you normally see on the Task page with the prompt on the left, with the input area on the right, and with a question mark that displays the help text.

datatype is the type of input you require, and you also specify the datatype of the value that is passed into your rule.  Some example data types:

string - Sends in a java.lang.String object
boolean - Sends in a java.lang.Boolean object - shows as a checkbox
Identity - Sends in a sailpoint.object.Identity object
Application - Sends in a sailpoint.object.Application object
Workflow - Sends in a sailpoint.object.Workflow object
You get the pattern

There is one more attribute in the <Argument> tag which can be used and that is multi="true" which causes the task to gather multiple values and pass in as a List<> containing multiple instances of them.

Each of the values specified by variableName (that's the name of the variable) is passed into the rule as a key in the config Map, and can / should be analyzed to see if it is provided, using containsKey() method, with the value provided using the get() method, which should be null and instanceof checked.

Happy batch processing

Customizing SailPoint TaskDefinitions - OOTB method

Subject: Batch processing in SailPoint

Regarding: Using a rule to execute batch processing, customization of the inputs



Creating a TaskDefinition for running a rule is normally performed by the following:

Setup -> Tasks
New Task -> Run Rule

Enter the details such as what you want the rule to be named, description, then the rule to be executed.  Save and Run



The normal method for making changes to the behavior of the rule is through the Rule Config line.  In this, the input data, separated by commas, is entered as:

key,value,key,value,key,value,key,value

Which translates into an input variable called config, which is passed into the rule as a Map.  You can verify the value exists by using this:

if(config==void || config==null || config.isEmpty()) {
    log message
}
else {
  extract the key value pairs out of the map
}

The problem with this method is that it is hard to train people how to use it.  See further posts for how to get around this.