This rule is used to execute PowerShell commands on the IQService component after a source account is created.
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.
|
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.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="SampleSource AfterCreate" type="ConnectorAfterCreate">
<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\ConnectorAfterCreate_$logDate.log"
$command = "c:\SailPoint\Scripts\SampleSource-AfterCreate.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>
###############################################################################################################################
# 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\SampleSourceAfterCreateScript_$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")
}
Is there documentation for the methods/functions we call from the
Sailpoint.Utils.objects.AccountRequest
object?
There is one example provided, and one helper function in the above template but other than that the object structure is quite ambiguous.
Hello just an FYI for others I believe the 2nd line in the rule template should be this:
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
instead of this:
<!DOCTYPE sailpoint PUBLIC "sailpoint.dtd" "sailpoint.dtd">
In the afterModify script, the following line is not commented out. Is the same true for this one or not?
#Add-type -path utils.dll;
Is there any document available to specify the process of updating rule related details to a Source ?
Hi @Sri_Veera , for detail rule review process and guidelines, refer IdentityNow Rule Guide.
Hi @dinesh_mishra ,
Thanks for your response. But i am looking for json keys and value template for attaching the different rules to source.
eg: "beforeProvisioningRule": "rulename"
I think it would beneficial to state here that these rule names must be added via "nativeRules" to the AD connector in case ES doesn't attach the rule for you after peer review.
example:
Anyone know what to do with this Rule template? Does it get loaded into the system via API calls?
I'm looking for info on how to load afterCreate rule that runs a PowerShell script.
I found somewhere on the rule guide where it gives the below code as rule object model.
What do i do with these - the rule template and the rule object model?
{ "id": "2c91808674a2816a0174af21a6450009", "name": "Example WebServices Rule", "description": "This is just an example", "created": "2020-09-21T05:27:32.170Z", "modified": null, "type": "WebServiceBeforeOperationRule", "signature": { "input": [], "output": null }, "attributes": { "sourceVersion": "2020-09-21 05:27:31" }, "sourceCode": { "version": "2020-09-21 05:27:31", "script": "\n import java.util.HashMap;\n import org.json.JSONArray;\n import org.json.JSONException;\n import org.json.JSONObject;\n\n import org.apache.http.HttpEntity;\n import org.apache.http.HttpResponse;\n import org.apache.http.client.HttpClient;\n import org.apache.http.client.methods.HttpPost;\n import ... requestEndPoint.getBody().put(\"jsonBody\",requestXML); \n }\n }\n }\n log.info(\"Done Ultipro Onboarding before operation rule...\");\n return requestEndPoint;\n" } }
Hello @Ola5 ,
The Json you get (more a sample than a template) is for another event (see type WebServiceBeforeOperationRule).
The Json is for IdentityNow API, don't if it's the same for IIQ.
You need to create a Json for your specific Rule with the good type :
* ConnectorAfterCreate
* WebServiceAfterOperationRule
Depends what you want to do. In the sourceCode/script put your script.
See IdN API for the Rule creation https://developer.sailpoint.com/idn/api/beta/create-connector-rule.
Best regards,
Hi @Ola5 ,
Were you able to resolve your query? I have also the similar use case i.e. to write after create rule and calling a PS from it. But i dont understand how to prepare JSON for this.
{
"name": "ActiveDirectoryAfterCreateRule",
"type": "ConnectorAfterCreate",
"sourceCode": {
"version": {},
"script": {
"value": "<----My code-->"
}
},
"description": "This rule does that",
"signature": {
"input": [],
"output": null
},
"attributes": {}
}
In the "My code" section how to include powershell code to call the script i am not able to understand.
Thanks
Where do i put the entry keys on the JSON body?
@yunus_ali yes, i was able to resolve it. The value for "scripts" in your json body for your connector rule would take your powershell code converted to json.
Sample:
{
"description": "This rule does this and that",
"type": "RuleType",
"signature": {
"input": [],
"output": null
},
"sourceCode": {
"version": "1.0",
"script": "#Entering Powershell Code\r\n$service = get-service\r\nWrite-Output \"All services:\" $service"
},
"attributes": {
"ObjectOrientedScript": "true",
"extension": ".ps1",
"sourceVersion": "1.0",
"disabled": "false",
"program": "powershell.exe",
"timeout": "360"
},
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"name": "Rule Name"
}
@Ola5 Thanks for your response.
Could you please tell me how did you tag this rule to your active directory source? What exact api and key you have used to tag it?
I tried with "nativeRules" and "connectorAfterCreate" but it doesnt seem to invoke the rule.
Thanks
Yunus
Hi @yunus_ali
You have to use the PATCH method on "https://tenant.api.identitynow.com/beta/sources/{sourceID}"
In the header, you have to specify Content-Type as "application/json-patch+json"
and in the body you should have something like this:
where "Rule 1" and "Rule 2" are the names of your rules.
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.
Hi all,
The Rule is getting executed even after the account creation results in a fail. Is this expected? if so, is there a possibility to not execute the rule after an creation error?
Thanks,
Hi @Ola5 & @yunus_ali ,
Can anybody help me with the process of writing the connector rule with powershell script in the source and then tagging the rule to Active Directory Source ?
Thanks in advance
Here's the code I used. I found it somewhere on this platform.
$logDate = Get-Date -UFormat %Y%m%d
$logFile = "c:\SailPoint\Scripts\Logs\ConnectorAfterCreate_$logDate.log"
$command = "C:\Temp\AfterCreateScript.ps1\"
$enableDebug = $true
#====================-------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 "C:\SailPoint\IQService\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")
}
You need to convert that to JSON to get something like this, which is what you need for the connector rule:
"$logDate = Get-Date -UFormat %Y%m%d\r\n$logFile = \"c:\\SailPoint\\Scripts\\Logs\\ConnectorAfterCreate_$logDate.log\"\r\n$command = \"C:\\Temp\\AfterCreateScript.ps1\\\"\r\n$enableDebug = $true\r\n\r\n#====================-------Helper functions-------====================\r\nfunction LogToFile([String] $info) {\r\n $info | Out-File $logFile -Append\r\n}\r\n \r\n#====================-------Get the request object-------====================\r\nTry{\r\n if($enableDebug) {\r\n LogToFile(\"Entering SailPoint rule\")\r\n }\r\n Add-type -path \"C:\\SailPoint\\IQService\\Utils.dll\\\";\r\n $sReader = New-Object System.IO.StringReader([System.String]$env:Request);\r\n $xmlReader = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sReader));\r\n $requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);\r\n $requestAsString = $env:Request\r\n if($enableDebug) {\r\n LogToFile(\"Request as XML object is: $requestAsString\")\r\n }\r\n\r\n #Call the client script\r\n $command = -join ($command, \" -requestString \u0027$requestAsString\u0027\")\r\n Invoke-Expression $command\r\n}\r\nCatch {\r\n $ErrorMessage = $_.Exception.Message \r\n $ErrorItem = $_.Exception.ItemName\r\n LogToFile(\"Error: Item = $ErrorItem -\u003e Message = $ErrorMessage\")\r\n}\r\nif($enableDebug) {\r\n LogToFile(\"Exiting SailPoint rule\")\r\n}"
Then create a connector rule using POST on "https://tenant.api.identitynow.com/beta/connector-rules". In the body of the request, you would have something like this:
{
"description": "This rule Executes Post-Creation Tasks",
"type": "ConnectorAfterCreate",
"signature": {
"input": [],
"output": null
},
"sourceCode": {
"version": "1.0",
"script": "your JSON code goes in here"
},
"attributes": {
"ObjectOrientedScript": "true",
"extension": ".ps1",
"sourceVersion": "1.0",
"disabled": "false",
"program": "powershell.exe",
"timeout": "360"
},
"name": "Call it whatever you like. E.g:Connector After Create"
}
As a final step, you need to attach the rule to your source's connector. The same step described above by @yunus_ali . More detail here: https://developer.sailpoint.com/idn/api/v3/update-source
Hope this helps.
Hi All,
I am trying to invoke the powershell script via the AfterCreate rule and for some reason i am getting error with the script. I am seeing below error in the IQtrace log.
DEBUG : "Script return code : 255"
04/26/2022 16:23:11 : AbstractConnector [ Thread-11 ] DEBUG : "EXIT executeScript"
04/26/2022 16:23:11 : AbstractConnector [ Thread-11 ] DEBUG : "After script returned non zero exit code : 255 : "
04/26/2022 16:23:11 : AbstractConnector [ Thread-11 ] DEBUG : "EXIT executePostScript"
Is there any way to identify the error code. Also, the powershell i am invoking i am just trying to send a notification to manager for user AD password.
Hello @anuragt, curious if you ever found a solution to the error 255? We're seeing the same error messages when attempting to run the post create script.
Thanks.
Hello @anuragt , @dustin_yeager @anuragt ,
Did you find the solution for non zero exit code : 255 ?
Thanks,
IAM-PDU
Hi Everyone,
I am new to PowerShell script, Can you please tell me how to get the provisioned account details in after creating rule and how to set those values to parameters.
Thank you...!!!
Hi All,
Is it possible to attached multiple rules of same type into a source? For example, if I attach multiple ConnectorAfterCreate rule in an AD source, does this execute both aftercreate rule?