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

How to read application configuration in IQService pre/post script

How to read application configuration in IQService pre/post script

I have seen many questions on community asking how we can read application configuration data in the before/after PowerShell scripts.

Most of the time implementors end up storing required information in the external file and reading that information using PowerShell commands.  If config data contains sensitive attributes like ‘password’ then in that case those are stored/retrieved using PowerShell command Import-CliXml and Export-CliXml. This external file needed to update each time whenever sensitive data values changes.

Following PowerShell script example will show how we can achieve this without storing data in the external file.

Example 1: Assume Azure AD application contains attribute ‘Office365UserName’ and ‘password’ which will store username and password to connect to Office365 using PowerShell commands. Following script will read those attributes to connect to Office365 and Exchange Online and will set some Exchange Online Attributes for the user.

I have provided 2 versions of each scripts based on IQService version.  In the IQService version 8.1 and 8.0p2 or above, we made it little simpler. 

Script which can be used for IQService version < 8.1, 8.0p2 or IdentityNow IQService version.

Add-type -path C:\Program files\IQService\bin\Debug\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);

# Retrive nativeIdentity from request object
$nativeIdentity = $requestObject.NativeIdentity

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

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

# Remove any line containing '<Date>' from app xml, because IQService was expecting date in milliseconds
# but application contains date in the format MM/DD/YY HH:MM:SS AM
$escaped = $sReader1 -split "`n" | Select-String -Pattern "Date" -NotMatch
 
# Convert String array to String 
$content = $escaped | Out-String
 
#Create stringReader object from app xml string
$stringReader = New-Object -TypeName System.IO.StringReader -ArgumentList $content

# New xml reader object 
$appXmlreader = [System.Xml.XmlTextReader] [sailpoint.Utils.xml.XmlUtil]::getReader([System.IO.TextReader]$stringReader);

$appXmlreader.MoveToContent()
 
# parsObject will return application object as a Hashtable
$appObject = $xmlFactory.parseObject($appXmlreader)
 
#Retrive application configuration entries named Office365username and password value from AzureAD application config
$office365AdminUsername = $appObject.Office365username

#Retrive password attribute value
$o365Password = $appObject.password

#create Credential object
$secpasswd = ConvertTo-SecureString $o365Password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($office365AdminUsername, $secpasswd)

#Connect to Office365
Import-Module msonline
Connect-MsolService -Credential $cred

#Connect Exchange-Online
$msoExchangeURL = "https://ps.outlook.com/powershell/"
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $msoExchangeURL -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $session

# Set mailbox properties
Set-MailBox -identity $nativeIdentity -UseDatabaseQuotaDefaults $false -IssueWarningQuota "200MB" -ProhibitSendQuota "250MB" -ProhibitSendReceiveQuota "280MB"



Script which can be used for IQService 8.1,8.0p2 onward.

 

# Refer to SailPoint class library.
Add-type -path C:\Program files\IQService\bin\Debug\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);

# Retrive nativeIdentity from request object
$nativeIdentity = $requestObject.NativeIdentity

# 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)

#Retrive application configuration entries named Office365username and password value from AzureAD application config
$office365AdminUsername = $appObject.Office365username

#Retrive password attribute value
$o365Password = $appObject.password

#create Credential object
$secpasswd = ConvertTo-SecureString $o365Password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($office365AdminUsername, $secpasswd)

#Connect to Office365
Import-Module msonline
Connect-MsolService -Credential $cred

#Connect Exchange-Online
$msoExchangeURL = "https://ps.outlook.com/powershell/"
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $msoExchangeURL -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $session

# Set mailbox properties
Set-MailBox -identity $nativeIdentity -UseDatabaseQuotaDefaults $false -IssueWarningQuota "200MB" -ProhibitSendQuota "250MB" -ProhibitSendReceiveQuota "280MB"

 

Example 2:  Reading AD application domainSettings and password

Script which can be used for IQService version < 8.1, 8.0p2 or IdentityNow IQService version.

Add-type -path "C:\IQService\Utils.dll"

# get xmlFactory object
 $xmlFactory = [sailpoint.Utils.xml.XmlFactory]::Instance;

# Read the environment variables
$sReader1 = [System.String]$env:Application;


# Remove any line containing '<Date>' because IQService was expecting date in milliseconds
# but application contains date in the format MM/DD/YY HH:MM:SS AM
$escaped = $sReader1 -split "`n" | Select-String -Pattern "Date" -NotMatch
 
# Convert String array to String 
$content = $escaped | Out-String
 
#Create stringReader object from app xml string
$stringReader = New-Object -TypeName System.IO.StringReader -ArgumentList $content

# New xml reader object 
$xmlreader = [System.Xml.XmlTextReader] [sailpoint.Utils.xml.XmlUtil]::getReader([System.IO.TextReader]$stringReader);
 
# This step is missing in existing IQservice 
$xmlreader.MoveToContent()
 
# parsObject will return application object as a Hashtable
$appObject = $xmlFactory.parseObject($xmlreader)
 
#Retrive domainSettings value from AD application config
$domainSettings = $appObject.domainSettings

#Read domain info of 1st domain in DomainSettings
$domainDN = $domainSettings[0].domainDN
$forestName = $domainSettings[0].forestName
$servers = $domainSettings[0].servers
$useSSL = $domainSettings[0].servers
$user = $domainSettings[0].user

#Encoded password of 1st domain setting object
$encodede = $domainSettings[0].password
#Decoded password of 1st domain setting object
$decoded = [sailpoint.Utils.tools.Util]::decode($encodede, $true)

 

Script which can be used for IQService 8.1,8.0p2 onward.

 

Add-type -path "C:\IQService\Utils.dll"

 $xmlFactory = [sailpoint.Utils.xml.XmlFactory]::Instance;

# Read the environment variables
$sReader1 = $env:Application   
$appObject = $xmlFactory.parseXml($sReader1)

#Retrive domainSettings value from AD application config
$domainSettings = $appObject.domainSettings

#Read domain info of 1st domain in DomainSettings
$domainDN = $domainSettings[0].domainDN
$forestName = $domainSettings[0].forestName
$servers = $domainSettings[0].servers
$useSSL = $domainSettings[0].servers
$user = $domainSettings[0].user

#Encoded password of 1st domain setting object
$encodede = $domainSettings[0].password
#Decoded password of 1st domain setting object
$decoded = [sailpoint.Utils.tools.Util]::decode($encodede, $true)
Comments

Thank you @sagar_bhingare for this informative post.  What I am unclear on is if the password is encrypted in the Application config file, will the code below return the decrypted value so that the ConvertTo-SecureString is acting on plain text? 

#Retrive password attribute value
$o365Password = $appObject.password

#create Credential object
$secpasswd = ConvertTo-SecureString $o365Password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($office365AdminUsername, $secpasswd)

 

@Gilly : Application config will always contains encrypted value for the password.

$o365Password = $appObject.password

will return password value in plain text.

$secpasswd = ConvertTo-SecureString $o365Password -AsPlainText -Force

ConvertTo-SecureString will convert to plaintext password to SecureString object, which is used later to create PSCredential object for connecting to Office365.

In case of AD connector, retrieving plain text password from DomainSettings is slightly different, I will soon update doc with the example of AD connector.

@sagar_bhingare  I am trying to read config for Active Directory.

$appXmlreader = [System.Xml.XmlTextReader] [sailpoint.Utils.xml.XmlUtil]::getReader([System.IO.TextReader]$stringReader);

$appXmlreader.MoveToContent()

I am not able to get password attribute from config. I added logs after above line, and see that password attribute is not getting after creating XML object from stringreader step. Did i miss anything?  when I print content variable, I see all attributes related to Application xml.

@sagar_bhingare  my current need is using the AD connector so I will be interested in the updated guidance you are working on.  Thanks.

@Gilly @saketh  I have updated doc with example of Active Directory, please check.  There are two script examples given based on the version of IQService

@sagar_bhingare  Thanks for sharing for AD application. I could able to get encoded password, but the last step decode password when I use 

$decoded = [sailpoint.Utils.tools.Util]::decode($encodede, $true)

 

Am getting error.

"System.FormatException The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."

I verified the encoded password in ps logs and the format is correct.

@saketh Which version of IQService you are using ?
Can you try with

$decoded = [sailpoint.Utils.tools.Util]::decode($encodede, $false)

 

@sagar_bhingare We are using 7.3p1, I am getting same error even if I use below query. 

$decoded = [sailpoint.Utils.tools.Util]::decode($encodede, $false)

 

I tried encoding a password in PS and see that encoded password doesn't have 1: in it.

I wrote sample PS script where I encoded passcode and decoded using the above command, then it works. From what I see above command is not working if passwords are in IIQ encrypted values. (1: , 2: , 3:)

@sagar_bhingare Is there any possible way to use powershell script to check the option "User cannot change password" in Active Directory application via a provisioning plan? 

@saketh :  This is not the way it should be used.  You are bypassing connector and IIQ server side mechanism here and directly passing IIQ encrypted password to IQService.  There is difference between the way of encrypting secret values in IIQ and IQService.  IQService doesn't know IIQ system encryption keys and it shouldn't be.  When this before/after script is invoked from the connector then connector takes care of passing encrypted values in the format that IQService expects and this is the way it should be used. 

Version history
Revision #:
8 of 8
Last update:
‎May 02, 2023 02:18 PM
Updated by:
 
Contributors