Connector Rule that triggers Powershell Script residing on IQServer

I have created the rule that would trigger a powershell script when provisioning activity happens for my Azure source . After attaching it to the source I get below erro name of my Rule is AFTERLOG

Errors

java.lang.IllegalStateException: Null Object XML returned from cloud for type [Rule] with identifier[{AFTERLOG}]

Rule Below :

    {
        "description": "After Provisioning rule that triggers a PowerShell script to create a log file upon provisioning activity",
        "type": "ConnectorAfterCreate",
        "signature": {
            "input": [],
            "output": null
        },
        "sourceCode": {
            "version": "1.0",
            "script": "<?xml version='1.0' encoding='UTF-8'?>\r\n<!DOCTYPE Rule PUBLIC \"sailpoint.dtd\" \"sailpoint.dtd\">\r\n<Rule language=\"beanshell\" name=\"After Provisioning Log Creation\" type=\"ConnectorAfterCreate\">\r\n<Attributes>\r\n<Map>\r\n<entry key=\"ObjectOrientedScript\" value=\"true\" />\r\n<entry key=\"disabled\" value=\"false\" />\r\n<entry key=\"extension\" value=\".ps1\" />\r\n<entry key=\"program\" value=\"powershell.exe\" />\r\n<entry key=\"timeout\" value=\"300\" />\r\n</Map>\r\n</Attributes>\r\n<Description>\r\n   This rule triggers a PowerShell script on the IQServer after a provisioning activity occurs.\r\n   The script logs the activity details to a file in the same folder.\r\n</Description>\r\n<Source>\r\n<![CDATA[\r\n   $logDate = Get-Date -UFormat \"%Y%m%d\"\r\n   $scriptFolder = \"c:\\SailPoint\\IQService\\#######\"\r\n   $logFile = \"$scriptFolder\\ProvisioningActivityLog_$logDate.log\"\r\n   $scriptName = \"triggeronprovisioning.ps1\"\r\n   $command = \"$scriptFolder\\$scriptName\"\r\n   $enableDebug = $true\r\n   function LogToFile([String] $info) {\r\n     $info | Out-File $logFile -Append\r\n   }\r\n   Try {\r\n     if($enableDebug) {\r\n       LogToFile(\"Entering ProvisioningActivityLogger rule\")\r\n     }\r\n     Add-type -path 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     $command = -join ($command, \" -requestString '$requestAsString' -logFile '$logFile'\")\r\n     Invoke-Expression $command\r\n   } Catch {\r\n     $ErrorMessage = $_.Exception.Message\r\n     $ErrorItem = $_.Exception.ItemName\r\n     LogToFile(\"Error: Item = $ErrorItem -> Message = $ErrorMessage\")\r\n   }\r\n   if($enableDebug) {\r\n     LogToFile(\"Exiting ProvisioningActivityLogger rule\")\r\n   }\r\n ]]>\r\n</Source>\r\n</Rule>"
        },
        "attributes": {
            "sourceVersion": "1.0"
        },
        "id": ##########################################
        "name": "AFTERLOG",
        "created": "2024-11-19T15:24:44.260Z",
        "modified": "2024-11-19T15:24:44.260Z"
    },

U can unescape the script part if required .

I have seen JDBC Connector Error

But for me i have added the rule under native rules using the payload and still did not work

Hi @anuragbong,

You need to use the template mentioned in below link.

Before and After Operations on Source Account Rule | SailPoint Developer Community

Further in the Rule (in “script”), you just need to escape the part inside <![CDATA[ .... ]]>. Before that add the Log file and Powershell script location as mentioned in the template. I have mentioned the part you need to update and escape it before updating the rule.

$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")
}

Check this and let me know if it works.

Thanks.

2 Likes

@nikhleshsdg I am trying as you have said I have previously tried it but the template says the type of the rule is type="ConnectorBeforeCreate"and description says
“This is an IQService afterScript - On a successful provisioning event, this after script should be used as the starting point to
initiate a separate PowerShell script residing on the client’s IQService server.”

That got me confused . Would you want to comment on that ?

Template is same for all the Before/After Create/Modify rule. It’s just mentioned for ConnectorBeforeCreate in documentation.

Thanks.

I tried with the template and it did not work below is my powershell script

###############################################################################################################################
# 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,
[Parameter(Mandatory=$true)][System.String]$logFile
)
#include SailPoint library
Add-Type -Path "c:\SailPoint\IQService\Utils.dll";
#log file info
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\IQService\Scripts\Logs\ConnectorAfterCreate_$logDate.log"
$enableDebug = $true
###############################################################################################################################
# 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("Script execution started.")
}
LogToFile("Script is running.")
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
   # Write basic message indicating script ran
   LogToFile("Script completed successfully.")
   #
   # End Client-provided code
}
catch {
   $ErrorMessage = $_.Exception.Message
   LogToFile("Error: Message = $ErrorMessage")
}
if($enableDebug) {
   LogToFile("Exiting script.")
}

I removed the import AD cmdlet as I just want to trigger the script and log something into the file

What error you received? Have you unlocked the Utils.dll file in IQ Services?

To do this you need to go Utils.dll file and right click to Properties and unlock the file.

Also, at which part you got the error. Calling powershell script from Rule or running powerhsell script? As I see earlier you were not able to call powersehll script as well.

NO errors but no interaction with the script so far .

Did you updated the log file path and utils.dll path?

Can you check this?

@anuragbong ,

Please make sure your IQService service account is part of local administrator group on IQservice server box. and IQservice service logon is updated with service account.

Check powershell output for command: Get-ExecutionPolicy is Remote.

1 Like

I saw issue with your script value remove xml element tags and just put escaped bean shell code and try. hope would help to resolve your issue.

2 Likes

U mean the the add path in the CDATA section right ? I did that

You need to update the Log file and utils.dll path in powershell script as well for logs of powershell script.

Thanks.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
 <Rule language="beanshell" name="AFTERLOG" 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 to
            initiate a separate PowerShell script residing on the client's IQService server.

            Configuration tasks include the following:
             - 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\IQService\Scripts\Logs\ConnectorAfterCreate_$logDate.log"
$command = "c:\SailPoint\IQService\Scripts\triggeronprovisioning.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'"," -logFile '$logFile'")
    Invoke-Expression $command

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

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

]]>
  </Source>
 </Rule>

@nikhleshsdg on any provisioning activity this rule should trigger the powershell script

Depends on type of rule you have added in source.

For After create, it will trigger after every Create account activity.

For After modify, it will trigger after every modify account activity.

Let me know if you need any specifc details.

Thanks.

I have used connectorAftercreate if I change it to connector after modify do i need to make changes else where in the rule or just the tpe can be changed

also can I update type of a rule using update rule API?

You cannot change the type in existing Rule, you need to create another rule for After modify which will be triggered when there is any modify activity (eg. Add/Remove access) on account of the source where Rule is patched.

Thanks.

sailpoint.tools.GeneralException: Exception occurred while executing the RPCRequest: Errors returned from IQService. After script returned non zero exit code : 255 :

Got this error

Please check here:

1 Like