After we have upgraded our Staging environment from 8.0 to 8.3p3 we are seeing some weird behavior when trying to run powershell scripts through IQService. We created the rule below in order to try to troubleshoot the issue we found after the upgrade. We are able to reproduce the same behavior where IQService receives the Script but doesn’t process it/run it. Have been running IQService in Console mode, and don’t see any messages for it either.
<Source>
import sailpoint.api.SailPointContext;
import sailpoint.connector.RPCService;
import sailpoint.object.Application;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.ProvisioningPlan.Operation;
import sailpoint.object.RpcRequest;
import sailpoint.object.RpcResponse;
import sailpoint.object.Rule;
import sailpoint.tools.GeneralException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// Map to supply to the RPC Service to run PowerShell on IQService
Map data = new HashMap();
// Get the application definition
Application connect = context.getObjectByName(Application.class, "Application");
//logger.debug("Fetched connect object");
// Get the Rule definition
Rule theRule = context.getObjectByName(Rule.class, "The Remote Rule");
//logger.debug("Fetched rule");
// Get the Account Request
// Fake account request
AccountRequest accountRequest = new AccountRequest();
accountRequest.setApplication(connect.getName());
accountRequest.setNativeIdentity("*FAKE*");
accountRequest.setOperation(AccountRequest.Operation.Modify);
// Fake attribute request
AttributeRequest fakeAttribute = new AttributeRequest();
fakeAttribute.setOperation(Operation.Add);
fakeAttribute.setName("CmdletResponse");
fakeAttribute.setValue("");
List fakeAttributeRequests = new ArrayList();
fakeAttributeRequests.add(fakeAttribute);
accountRequest.setAttributeRequests(fakeAttributeRequests);
// Add to the IQService params
data.put("Request", accountRequest);
//logger.debug(String.format("Lockout request: %s", req.toXml()));
// Populate the RPC 'data' argument
Application ad = context.getObjectByName(Application.class, "Application");
data.put("Application", ad.getAttributes());
data.put("postScript", theRule);
// Build the RPC Service
RPCService service = new RPCService("server", 5050, false);
service.setConnectorServices(new sailpoint.connector.DefaultConnectorServices());
accountRequest.add(new AttributeRequest("username", "Credential"));
String decrypted = "Password";
String encrypted = service.encode(decrypted);
accountRequest.add(new AttributeRequest("password", encrypted));
//logger.debug("Built RPC Service");
// Build the RPC Request
RpcRequest request = new RpcRequest("ScriptExecutor", "runAfterScript", data);
//logger.debug("Built RPC Request");
// Execute the request
RpcResponse response = service.execute(request);
//logger.debug(String.format("RPC Response: %s", response.toXml()));
return response.toXml();
</Source>
Can you also share the Powershell rule "The Remote Rule" and the IQService.exe location ?
In the past I has similar issues when we installed a new/other IQService version. When placed in a different directory the PowerShell rule needed to be updated to find the utils.dll
Taken from a SSB (so using target.properties):
#Refer to SailPoint class library.
Add-type -path %%IQSERVICE_PATH%%\utils.dll
What is you enable debug logging of the IQService: IQService.exe -d -l 3
The strangest thing is; the response states it was a success.
Does the user running IQService has write access to D:\IQService\stuff.txt ?
You can also add a return message in the powershell (The Remote Rule). Something like:
#Read the environment variable
$sResult = New-Object System.IO.StringReader([System.String]$env:Result);
#Form the xml reader object
$xmlReader_Result = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sResult));
#Create SailPoint object
$resultObject = New-Object Sailpoint.Utils.objects.ServiceResult($xmlReader_Result);
#Add message to resultObject
$resultObject.Messages.add("This is a message from PS to IIQ");
If you place this after the ‘Hello World’ statement, you should see it back in the response.toXml();
It appears that our issue is rooted in the Application being passed to the script. We tried with other applications and everything goes through perfectly.
Will try to investigate and try to see what could be the issue. Need to try and figure it out since this is an old “legacy” Exchange application that is still leveraged for old custom code.
We have experiences issues with getting messages returned back from powershell to IIQ despite adding the return message in powershell as you have listed here.
We have peeled back our powershell code to do the bare minimum - read the environment variable, form the xml reader object, create the result object, and add the message back to the result object. The result back to IIQ is just:
Do you have any suggestions? I am not sure if Jose tried what you suggested but I noticed that they do not have any messages sent back in their RcpResponse either. Having these messages sent back to IIQ would be a huge help for us for future debugging efforts.
Can you test the following powershell script? And look to the IQService log file.
This script will add an error and a message to the result and before ending the script send the resultObject to the IQService log"
Add-type -path d:\iqservice\utils.dll
Read the environment variables
$sReader = New-Object System.IO.StringReader([System.String]$env:Request);
$sResult = New-Object System.IO.StringReader([System.String]$env:Result);
#Form the xml reader objects
$xmlReader = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sReader));
$xmlReader_Result = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sResult));
#Create SailPoint objects
$requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
$resultObject = New-Object Sailpoint.Utils.objects.ServiceResult($xmlReader_Result);
$resultObject.Messages.add("A Message in the Return Object");
$resultObject.toxml() | out-file $args[0];
This should show the resultObject in the IQService log file and also in IIQ.
If really needed I can setup my PoC environment to do exactly the same, but that would take some extra time
– Remold
Some extra info:
If you want to use a different log file you can cahneg the last line to:
An extra note:
It appears only the after scripts return the ResultObject.
The powershell should be called as an after script rule being ConnectorAfterCreate, ConnectorAfterModify or ConnectorAfterDelete.
This works! However, for our use case we are using Start-Job and having this code run within a job. Due to that we are unable to extract the output back to IIQ. Do you know if there is any way to store information within the resultAttributes as that we can get back to IIQ with no issue even when using jobs.