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

Hybrid exchange provisioning via PSS script

Hybrid exchange provisioning via PSS script

Hey Sailors, 

Hope you are healthy and safe during these uncertain and unprecedented times.

Running Powershell directly via the IQService. This is a Native Rule to invoke PowerShell which creates RemoteUserMailbox for clients that are in Hybrid Environment after the Active Directory account is created.

We need to send Exchange Attributes [i.e. username, password in text] to Provisioning Plan as attributes map in Account Request that is used while establishing a Remote PSS connection to exchange server.

 

public static Attributes<String, String> getExchangeAttributes(SailPointContext context, String flow)
			throws GeneralException {
		Custom custom = context.getObjectByName(Custom.class, "Customobject where Exchange credentials are saved");
		Attributes<String, String> attributes = new Attributes<String, String>();
		attributes.put("flow", flow);
		attributes.put("username", custom.get("SVC_UserName"));
		attributes.put("pwdText", context.decrypt((String) custom.get("SVC_Password")));
		return attributes;
	}

 

  • The above method can be created in Rule Library or Utility class file 

 

 

 acctReq.setArguments(CORPUtil.getExchangeAttributes(context,"Joiner"));

 

  • Add this arguments map in your plan to Enable and Disable operations whichever suits your organization need

 

ConnectorAfterCreate

Here some example code for the ConnectorAfterCreate PowerShell script that can be invoked after AD account creation.

 

 

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="RemoteMailbox-Create-PSScript" 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="150"/>
    </Map>
  </Attributes>
  <Description>
    An IdentityIQ Server-Side rule that is executed AFTER the connector's provisioning method is called. 
    This rule is called after accounts have been created on the underlying AD domain.
  </Description>
  <Signature>
    <Inputs>
      <Argument name="log">
        <Description>
          The log object associated with the SailPointContext.
        </Description>
      </Argument>
      <Argument name="context">
        <Description>
          A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
        </Description>
      </Argument>
      <Argument name="plan">
        <Description>
          The ProvisioningPlan object on its way to the Connector.
        </Description>
      </Argument>
      <Argument name="application">
        <Description>
          The application object that references this before/after script.
        </Description>
      </Argument>
    </Inputs>
  </Signature>
  <Source><![CDATA[


$logFile = "C:\ExchangeLogs\AfterCreateLogs\$(Get-Date -format "yyyy-MM-dd").ConnectorAfterCreate.log"

Function writeToLog() {
    
  param([string]$message)

  Add-Content ($(Get-Date -format "yyyy-MM-dd HH:mm:ss") + "::$message") -Path $logFile
  
}
  
Function sendEmail{   

  $emailMessage = New-Object System.Net.Mail.MailMessage

  $emailMessage.From = "John Smith <john@CORP.com>"

  $emailMessage.To.Add("akhilreddy@CORP.com" )

  $emailMessage.Subject = "User mailbox  creation failed for User -$sAMAccountName"

  $emailMessage.IsBodyHtml = $true

  $emailMessage.Body = @"

  <p>Hello Team,</p>

  <p>The usermailbox creation for user -$sAMAccountName has falied due to following erros.</p>

  <p> $dn on server: $exchangeServer . Error::  $_.FullyQualifiedErrorId $_.Exception.Message  </p>

  <p>Please take neccessary actions to create an mailbox for the individual immediately .</p>
    
  <p>Best Regards,</p>
          
  <p>-Akhil Reddy</p>
  "@

  $SMTPClient = New-Object System.Net.Mail.SmtpClient( "yourSMTPServer -FQDN/IP" , "port" )

  $SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $username , $pwdText );

  $SMTPClient.Send( $emailMessage)
}

#Notify that we are in afterscript
    
writeToLog("Running AfterCreate Script: 'CORP-Rule-AfterCreateScript'`r`n");

#Refer to SailPoint class library
  
Add-type -path "C:\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 object###
  
$xmlReader = [System.xml.XmlTextReader]([sailpoint.Utils.xml.XmlUtil]::getReader($sReader));

$xmlReader_Result = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sResult));

###Create SailPoint Request object
  
$requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
  
$resultObject = New-Object Sailpoint.Utils.objects.ServiceResult($xmlReader_Result);
  
##Done for inclusion in Log File  
 
$requestXML = $requestObject.toxml();

$resultXML = $resultObject.toxml();

writeToLog("Request Object :: $requestXML");

writeToLog("Result Object  :: $resultXML");

$objectType = ""


if($resultObject.Errors.count -eq 0){
      foreach ($attribute in $requestObject.AttributeRequests){
        if($attribute.Name -eq "ObjectType"){
          $objectType = $attribute.value
        }
      if($attribute.Name -eq "op"){
        $op = $attribute.value
        }
        if($attribute.Name -eq "sAMAccountName"){
          $samAccountName = $attribute.value
        }
        if($attribute.Name -eq "userPrincipalName"){
          $upn = $attribute.value
        }
      }

if($objectType -eq "User"){
  
foreach ($resultEntry in $resultObject.Attributes.GetEnumerator()){
      
  if($resultEntry.Name -eq "createdOnServer"){

  $createdOnServer = $resultEntry.Value

  }
      
}

  
foreach ($requestEntry in $requestObject.Attributes.GetEnumerator()){

  if($requestEntry.Name -eq "username"){
    $username = $requestEntry.Value
    }

      if($requestEntry.Name -eq "pwdText"){
        $pwdText = $requestEntry.Value
        }

            if($requestEntry.Name -eq "flow"){
            $flow = $requestEntry.Value
            }
}


$dn = $requestObject.NativeIdentity;
$op= $requestObject.Operation

writeToLog("//********************* Main Entry Point *******************************//");


writeToLog("Request attributes ---- dn: $dn, ObjectType: $objectType, op : $op, createdOnServer: $createdOnServer, sAMAccountName: $sAMAccountName, upn: $upn, flow:$flow ");

if( $flow -eq "Joiner" -And $op -eq"Create"){
      
$sApplication = New-Object System.IO.StringReader([System.String]$env:Application);

$xmlReader_Application = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sApplication));

[System.Xml.XmlDocument]$document = new-object System.Xml.XmlDocument

$document.load($xmlReader_Application)

$exchangeServers = $document.SelectNodes("//Map/entry[@key='ExchHost']/value/List/String")

$exchangeServersString = $exchangeServers.InnerText

writeToLog("Exchange servers is :::::::::::::::::::::::::$exchangeServersString")


foreach ($exchServerAddress in $exchangeServers) {

Try {

$exchServerAddressString  = $exchServerAddress.InnerText

writeToLog("Trying exchange server: $exchServerAddressString")

$hostInfo = [System.Net.Dns]::GetHostByName($exchServerAddressString)

$exchangeServer = $hostInfo.HostName

$IsOnline = Test-Connection -ComputerName $hostInfo.HostName -BufferSize 16 -Count 1 -Quiet

writeToLog("is server online::::::::::::::::::::: $IsOnline ")

if ($IsOnline -eq $true){

Function Login {

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

$credObject = New-Object System.Management.Automation.PSCredential($username, $secpasswd)		

$uri = "http://"+ $exchangeServersString + ":80/PowerShell/"

$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $uri -Credential $credObject -Authentication Kerberos #-ErrorAction Stop

Import-PSSession $session -AllowClobber -DisableNameChecking	

$session

}

$session = Login

writeToLog("Session value: $session")

writeToLog("Invoking Enable-RemoteMailbox command for account: $samAccountName")

set-adserversettings -viewentireforest $true

$email = $samAccountName +"@CORP365.mail.onmicrosoft.com"

writeToLog("email:::::::::::::::::::::::$email")

writeToLog("Executing second cmd for account: $samAccountName")

Enable-RemoteMailbox $samAccountName  -RemoteRoutingAddress $email 

$logger = Get-RemoteMailbox -Identity $samAccountName 

writeToLog("checking mailbox print the display name of the user :: $logger")

writeToLog("cmdlets execution completed")
  
$id =$session.ID

Remove-PSSession -ID $session.ID
    
writeToLog("After session remove: $Session")
$scriptExecuted=$true
}
else{

writeToLog("Cannot connect to server : $exchServerAddressString")
  
}
if($scriptExecuted){
  
writeToLog("Mailbox script execution completed for ::: $samAccountName on server ::: $exchServerAddressString")
  
}

} catch {

writeToLog("Cannot create mailbox features for user: $dn on server: $exchangeServer . Error:  $_.FullyQualifiedErrorId $_.Exception.Message")

sendEmail
  
}
finally {
 
if($session){
  

  
writeToLog(":::::Finally:::")

Remove-PSSession -ID $session.ID
  
##Disconnect-PSSession -ID $session.ID
  
  }
  
}
 

}

}
else{
  
writeToLog("::::--!!  skipping the after create scripts execution as the plan would be from the identityRefreshExecutor !!--:::::")
  
}

 
 } else {

writeToLog("Skipping mailbox creation. After Create script triggered for ObjectType: $objectType")

} 
  
  
} else {

foreach ($errorMsg in $resultObject.Errors){
writeToLog("Errors from Service Result :::`n`r $errorMsg ");	
  
}

}

writeToLog("Executing After Create Script completed for User: $samAccountName");

writeToLog("//*********************End of Script *******************************//");

  ]]></Source>
</Rule>

 

  • The above script connects via Remote PSSession and executes the script for enabling the mailbox and it also sends an email notification upon failures while creating mailbox
  • The above snippet can be used with some modifications as AfterModifyScript - by changing the flow and powershell command for disabling and hiding the mail address.

 

 

 

Set-RemoteMailbox $sAMAccountName -HiddenFromAddressListsEnabled $true

 

  • This will make sure that the disabled user's mail id is hidden from the directory.
Version history
Revision #:
4 of 4
Last update:
‎May 16, 2026 10:42 AM
Updated by: