Search This Blog

Wednesday, December 30, 2020

SailPoint Identity attribute naming recommendations

 I have seen some very odd names for Identity attributes.

Just as a refresher, Identity attributes are defined in the ObjectConfig-Identity.xml file.

For example:

<ObjectAttribute displayName="Job Title" editMode="readOnly" name="jobTitle"/>

My example doesn't include any source or target definitions.

If you want the field to be searchable, you have two options.  One option is to use one of the extendedNumber values.  If you just check the searchable box in the UI, SailPoint will assign the next available extendedNumber value.  This option is fraught with dangers.  The first danger is that OOTB there are only 10 extended attributes defined in the IdentityExtended.hbm.xml file, so if you exceed 10, you will need to uncomment the 11-20 lines and then create the database table fields.  The second danger is that only 5 of the OOTB extended attributes have indexes defined, so any search on those non-indexed attributes will generate a table scan in the database, affecting performance.  You should define and create these indexes as soon as possible in your installation process.

The second option is to used named columns.  This method is described in the hibernate file and here is where this post is important to apply.  My recommendation is to always use strict and concise camelCase for identity attribute names, which go in the ObjectConfig-Identity.xml and in the IdentityExtended.hbm.xml files.  Here are some naming schemes that have generated terrible results:

All caps like EMPLID

Trailing caps like personID

Leading caps like ADLoginName

Numbers like AS400Login

Pascal Case such as JobTitle

Repeated caps like autoFRActivate

Long long names like ADLastModifiedDatetime

Using underscores (snake case) like job_title

Database keywords or function names.  Here are some I have discovered:

  • position

Single lower case values are FINE - emplid, title, these are fine although not very descriptive.

If you want to use "ID" in the description, use "Id" in the name such as personId

Keep it short, keep it simple.  Two words is best: jobTitle, departmentName, adLogin, adGuid, empoyeeId, etc.  Remember that Oracle 12c only allows a 30 character identifier.

When you deploy the hibernate file and then execute the iiq extendedSchema command, the extendedSchema job takes the camel case and splits it into words, like this:

jobTitle       becomes job_title

This is done because database don't normally care about case.  For this same reason, always make your indexes to look like the field name, not like the camelCase.

<property name="jobTitle" type="string" length="450"

  access="sailpoint.persistence.ExtendedPropertyAccessor"

  index="spt_identity_job_title_ci"/>

NOT index="spt_identity_jobTitle_ci"/>

Don't try to create the database scripts on your own, you will likely make a mistake.





End

Wednesday, November 25, 2020

SailPoint why you should NEVER open any OOTB or cloned OOTB workflow in UI

Here's a good suggestion

Unless you authored a workflow in the Business Processes UI in SailPoint, don't open it in the UI.  This includes any OOTB workflow - you should NEVER modify any OOTB workflow.  It also includes any workflow that you cloned from OOTB.

How do you clone a workflow?  How to you clone any replicatable object?  Open it in the Debug Page, then change the Name, and then remove the created, id, and (if there) modified tags from the first line (actually line 3).  Also then search for and remove any created, id, or modified tags anywhere in the file.

Why don't you want to open an OOTB workflow in the UI?  Because the UI will reorganize the workflow in a way you don't want to happen.  It will reformat the descriptions, it will add or remove arguments to steps, and you will not be able to make comparisons to the OOTB workflows.  It also adds the explicitTransitions tag which is not wanted.

Here's what it does to LCM Provisioning:

Reformats the Descriptions to remove line feeds - they are ugly

In the Initialize step, it adds the following arguments:

  • <Arg name="identityRequest">
  • <Arg name="asyncCacheRefresh">

It also confusingly shuffles the remaining arguments.

In the Create Ticket step, it adds the following arguments:

  • <Arg name="ticketProject">
  • <Arg name="ticketPlan">
In the Pre Split Approve step, it adds the following arguments:
  • <Arg name="dontUpgradePlan"/>
  • <Arg name="clearApprovalDecisions"/>
  • <Arg name="workItemDescription"/>
In the Approve and Provision Split step, it adds the following arguments:

    • <Arg name="clearApprovalDecisions"/>
    • <Arg name="requesterEmailTemplate"/>
    • <Arg name="approvalEmailTemplate"/>
    • <Arg name="endOnProvisioningForms"/>
    • <Arg name="enableRetryRequest"/>
    • <Arg name="endOnManualWorkItems"/>
    • <Arg name="userEmailTemplate"/>
    • <Arg name="batchRequestItemIId"/>

    In the Approve and Provision step, it adds the following arguments:

    • <Arg name="approvalEmailTemplate"/>
    • <Arg name="batchRequestItemId"/>
    • <Arg name="clearApprovalDecisions"/>
    • <Arg name="enableRetryRequest"/>
    • <Arg name="endOnManualWorkItems"/>
    • <Arg name="endOnProvisioningForms"/>
    • <Arg name="requesterEmailTemplate"/>
    • <Arg name="userEmailTemplate"/>
    In the Finalize step, it adds the following arguments:
    • <Arg name="autoVerifyIdentityRequest"/>
    • <Arg name="ticketDataGenerationRule"/>


    Monday, November 23, 2020

    SailPoint which files should go in your comparison folder

     In the ExportXML class you have an option to compare against existing data and create a merge file for certain files.  Here are the files you will need to place in there and how to organize them.  You want to generate these files from a perfectly stock deployment so that the client's customizations are actually captured in the merge files.  If you don't, then the merge file will only contain modifications after the date you generated it.

    Create a folder I normally call mine base (or Base for Windows based).

     Next create the following folders and put the shown files into those folders:

    AuditConfig

        AuditConfig-AuditConfig.xml

    Configuration

        Configuration-ConnectorRegistry.xml

        Configuration-IdentityAIConfiguration.xml

        Configuration-IdentitySelectorConfiguration.xml

        Configuration-SystemConfiguration.xml

    ObjectConfig

        ObjectConfig-Bundle.xml

        ObjectConfig-Identity.xml

        ObjectConfig-Link.xml

        ObjectConfig-ManagedAttribute.xml

    UIConfig

        UIConfig-UIConfig.xml

     

    My normal ExportXML output is  $Class$-$Name$ that is why they are named that way.

    IdentityAI is not found on lower versions of IIQ.

    Sunday, November 8, 2020

    SailPoint saving AD values as a secondary auth source

     This post is primarily so I remember how I do every client's AD.  The point of saving AD values as Identity Attributes is twofold: first, to indicate if the user has an AD account (this can literally be done for any target, but AD is the one that almost everyone uses for their primary provisioning target).  Second, it allows you the OPTION of saving the values for all time, which would allow you to ensure that no duplicates be created.

     I create 5 Identity Attributes:

    adLogin (AD Login) which derives from sAMAccountName

    adEmailAddress (AD Email Address) which derives from mail

    adDistinguishedName (AD Distinguished Name) which derives from distinguishedName

    adUserPrincipalName (AD User Principal Name) which derives from userPrincipalName

    adObjuctGuid (AD Object Guid) which derives from objectguid

     Any or all of these can be backed up with a global rule I normally call IdentityAttribute-PersistOldValue whose source is literally return oldValue;

    You have to decide on your own which if any are sortable. Make a value sortable if you plan to do a search on it using any search method.

    If you use the global rule then your values will not be removed if the user loses their AD Account.  Be careful and aware of this. 

     


    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.

    Thursday, May 7, 2020

    Making SailPoint TaskDefinition settings survive a deployment

    There is some discussion (maybe not disagreement) regarding which SailPoint object types to put into the Source Code Repository and managed via SSB.  I won't get into all of them right here, but one of the most difficult decisions is around TaskDefinition objects.

    The newest Object Exporter tool ExportXML.class does have a setting called "Strip environment-specific metadata" which removes the transient values of:

    TaskDefinition.runLengthAverage
    TaskDefinition.runLengthTotal
    TaskDefinition.runs

    from the XML it generates for TaskDefinition objects.  For many of us dealing with Tasks, there are some settings that we would like to manage in the UI and not be overwritten by a deployment.  I suggest that the following changes to the TaskDefinition XML files can help with Task Management.

    The following settings may or may not be in this class of "preserve with deploy"
    •  resultAction (shown as Previous Result Action)
    • TaskSchedule.host (shown as Host)
    • taskCompletionEmailNotify (shown as Email Notification as a dropdown)
    • taskCompletionEmailRecipients (dropdown shown when above is set)
    • taskCompletionEmailTemplate (shown when above is set)
    • optional - Owner (not shown - defined on creation and only edited in debug
     How to do this:  Follow this process:

    Take a current export - using the Export Tool or use my KCSExportXML tool (available soon)

    Make the following edits:
    On the  DOCTYPE tag (line 2) change TaskDefinition to sailpoint
    Add 2 lines between the DOCTYPE tag and the TaskDefinition tag:
    <sailpoint>
      <ImportAction name="merge">
    Then indent everything below that down 4 spaces for proper XML indented format
    Then at the end add:
      </ImportAction>
    </sailpoint>

    Finally, delete the XML attributes or elements you do not want overwritten on a deployment, my list is above but yours may be different.  You might include lists on sequential tasks, or on tasks with lists of Applications, etc.

    Message me for help.