cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IdentityNow Rule Guide - After Modify Rule

IdentityNow Rule Guide - After Modify Rule

Purpose

This rule is used to execute PowerShell commands on the IQService component after a source account is modified, enabled, disabled, or unlocked.

 

Execution

  • Connector Execution - This rule executes within the Virtual Appliance and may offer special abilities to perform connector-related functions, and may offer managed connections to sources.
  • Logging - Logging statements are viewable within the ccg.log on the Virtual Appliance and by SailPoint personnel.
 

393243_image.png

 

Input

Argument Type Purpose
Application
System.Collections.Hashtable
Map of the application configuration.
Request
SailPoint.Utils.objects.AccountRequest
A reference to the account request provisioning instructions.
Result
SailPoint.Utils.objects.ServiceResult
A reference to the provisioning result that can be manipulated if needed.

 

Architecture Best Practices

For supportability, it is recommended that the After Creation rule be written with only the most basic logic necessary to trigger a PowerShell script, and shift the bulk of the downstream events and/or modifications to the PowerShell script itself. This script would reside on the client's servers and could therefore be easily maintained or modified by the client as needed. It also allows the client to implement changes to the PowerShell scripted functionality without requiring code review by SailPoint, as the code runs outside of the IdentityNow platform.

 

 

Rule Template

 

 

 

 

 

 

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
	<Rule language="beanshell" name="SampleSource AfterModify" type="ConnectorAfterModify">
		<Attributes>
			<Map>
				<entry key="ObjectOrientedScript" value="true" />
				<entry key="disabled" value="false" />
				<entry key="extension" value=".ps1" />
				<entry key="program" value="powershell.exe" />
				<entry key="timeout" value="300" />
			</Map>
		</Attributes>
		<Description>
			This is an IQService afterScript - On a successful provisioning event, this after script should be used as the starting point for 
            initiating a separate PowerShell script residing on the client's IQService server.

            Configuration tasks include:
             - Set a proper location for the $logFile variable
             - Set the proper script location and name for the $command variable
             - Set the $enableDebug flag to $true or $false to toggle debug mode
		</Description>
		<Source>
<![CDATA[

$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\Scripts\Logs\ConnectorAfterModify_$logDate.log"
$command = "c:\SailPoint\Scripts\SampleSource-AfterModify.ps1"
$enableDebug = $false

#====================-------Helper functions-------====================
function LogToFile([String] $info) {
    $info | Out-File $logFile -Append
}

#====================-------Get the request object-------====================
Try{
    if($enableDebug) {
        LogToFile("Entering SailPoint rule")
    }
	
    Add-type -path utils.dll;
	$sReader = New-Object System.IO.StringReader([System.String]$env:Request);
	$xmlReader = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sReader));
	$requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
    $requestAsString = $env:Request

    if($enableDebug) {
        LogToFile("Request as XML object is: $requestAsString")
    }

    #Call the client script
    $command = -join ($command, " -requestString '$requestAsString'")
    Invoke-Expression $command

}Catch{
	$ErrorMessage = $_.Exception.Message 
  	$ErrorItem = $_.Exception.ItemName
  	LogToFile("Error: Item = $ErrorItem -> Message = $ErrorMessage")
}

if($enableDebug) {
    LogToFile("Exiting SailPoint rule")
}

]]>
		</Source>
	</Rule>

 

 

 

 

 

 

 

 

PowerShell Script Template

 

 

 

 

 

 

###############################################################################################################################
# SETUP
# Instructions (for each IQService host that could run the script):
#   - Update the path to Utils.dll (can be an unqualified path like "Utils.dll" since script is copied to IQService folder for execution)
#   - Make sure Utils.dll is in the specified folder on each IQService host
#   - Be sure the account that runs IQService has appropriate permissions to create directories and set permissions on them
#   - Be sure to set the "run as" account for the IQService in Windows Service to the above-specified account instead of just the "logged on" user
#   - Set a proper location for the $logFile variable
#   - Set the $enableDebug flag to $true or $false to toggle debug mode
###############################################################################################################################

param (
	[Parameter(Mandatory=$true)][System.String]$requestString
)

#include SailPoint library
Add-Type -Path "c:\SailPoint\IQService\Utils.dll";

#import AD cmdlets
Import-Module activeDirectory

#log file info
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\Scripts\Logs\SampleSourceAfterModifyScript_$logDate.log"
$enableDebug = $false

###############################################################################################################################
# HELPER FUNCTIONS
###############################################################################################################################

#save logging files to a separate txt file
function LogToFile([String] $info) {
    $info | Out-File $logFile -Append
}

#if we have a non-null account request, get our value; otherwise return nothing
function Get-AttributeValueFromAccountRequest([sailpoint.Utils.objects.AccountRequest] $request, [String] $targetAttribute) {
    $value = $null;
    
    if ($request) {
        foreach ($attrib in $request.AttributeRequests) {
            if ($attrib.Name -eq $targetAttribute) {
                $value = $attrib.Value;
                break;
            }
        }
    } else {
        LogToFile("Account request object was null");
    }
    return $value;
}

  
###############################################################################################################################
# BODY
###############################################################################################################################
if($enableDebug) {
    LogToFile("Entering afterScript")
}

try {

    ##########################
    # Begin SailPoint protected code -- do not modify this code block
    #
        $sReader = New-Object System.IO.StringReader([System.String]$requestString);
        $xmlReader = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sReader));
        $requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
        
        #debug line for testing
        if($enableDebug) {
            LogToFile("Request object contents:")
            LogToFile($requestObject | Out-String)
        }
    #
    # End SailPoint protected code
    ##########################


    ##########################
    # Begin Client-provided code

    #get the necessary info we need from the accountRequest object
    #as an example: $nativeIdentity = $requestObject.nativeIdentity

    #do whatever work needs to be done here

    #
    # End Client-provided code
}
catch {
    $ErrorMessage = $_.Exception.Message 
  	$ErrorItem = $_.Exception.ItemName
  	LogToFile("Error: Item = $ErrorItem -> Message = $ErrorMessage")
}

if($enableDebug) {
    LogToFile("Exiting afterScript")
}

 

 

 

 

 

 

 

 

 

Comments

Hi Team,

I can able to fetch all the application arguments with below command.
$applicationInformation=($env:Application);
It is printing as a String but the expected was Map.
How can I store the Application attributes in Map & how can I fetch only required attributes from the entire map?
For example, I need iqservicehost & port alone from the map
Please advise.

Thanks,
Sasitharan Duraisamy.

@Sasi13130203 This is the code you need to convert the Application environment variable to an object, then you will be able to address its properties

# Get xmlFactory object to retive application configuration
$xmlFactory = [sailpoint.Utils.xml.XmlFactory]::Instance;

# Read the environment variables
$sReader1 = $env:Application

# Retrive application configuration object
$appObject = $xmlFactory.parseXml($sReader1)

#Read properties
$IQServicePort = $appObject.IQServicePort

 

Is there a way to get variables inside powershell into the solution ? (like set an attribute from a PS request result for example..)

BeanShell script error: bsh.EvalError: Sourced file: inline evaluation of: ``import sailpoint.tools.xml.XMLObjectFactory; String firstName = (String) obje . . . '' Token Parsing Error: Lexical error at line 5, column 17. Encountered: "\u201c" (8220), after : "" : at Line: 4 : in file: inline evaluation of: ``import sailpoint.tools.xml.XMLObjectFactory; String firstName = (String) obje . . . '' : String secondName = ( String ) object .getAttribute ( "secondName" ) BSF info: customization fullname at line: 0 column: columnNo

What is the path for attaching AfterModifyRule to Source ?

I am trying to decrypt the password in the attribute request, however, when I add context.decrypt($password), and trying to create the rule, I got error asking me to remove "context", does anyone know how to get the decrypted password in the afterCreate rule? I believe this is the right place to email the password. or any idea to where the password email should be triggered?

 

Thank you

May I make a couple of suggestions?  We ran into a situation in our environment where the wrapper in the rule would encounter an error and not execute the after-modify script.  This error happened in cases where there was an apostrophe in the data.  To fix this, I changed the line 

$requestAsString = $env:Request

to 

$requestAsString = $env:Request

 

Also, the function Get-AttributeValueFromAccountRequest may be reduced to this:

($request.AttributeRequests | Where-Object Name -eq $targetAttribute).Value
 
I know there are a dozen different ways to approach each solution, and mine is just one of several possibilities.

 

Apparently, my code modification did not make it through the editor, even though it looked fine in the preview.

$requestAsString = ($env:Request).Replace("'","''")

 

Version history
Revision #:
6 of 6
Last update:
‎Sep 10, 2021 06:24 PM
Updated by: