Using the PowerShell script to add user to a group in AD

Which IIQ version are you inquiring about?

8.3p3

Share all details about your problem, including any error messages you may have received.

Hello everyone.

Could someone please help me with the following problem.

We have a need to add a Joiner user to a group based on one-time access only. We have a group in AD to which any new account should be added, so as soon as the user completes the IT security test, they’ll be automatically removed from this group by the testing software.

The main problem for us is that when we use the IIQ to provision the groups, the entitlement is linked to the user and after the account aggregation and identity refresh tasks, the user is added back to the group.

I’m currently trying to use the execution of a powershell script for this operation, using the AfterProvisioning rule, so the entitlement would be detected and not assigned. But after the user is created he is still not added to the group and I don’t see any errors.

Here is the After Provisioning Rule code:

for ( AccountRequest accountRequest : plan.getAccountRequests() ) {
	if ( accountRequest.getOp() != null && accountRequest.getOp().equals(ProvisioningPlan.ObjectOperation.Create) ) {
    
		Identity identity = plan.getIdentity();
		if (identity == null) 
		{
		  throw new Exception("Identity is null");
		}
		else
		{
		  Map data = new HashMap();


		  Rule yourPowershellRuleObject = context.getObjectByName(Rule.class, "yourPowershellRuleObject");
		  Application ad = context.getObjectByName(Application.class, "Active Directory");
		  data.put("Request", accountRequest);
		  data.put("Application", ad.getAttributes());
		  data.put("postScript", yourPowershellRuleObject);

		  String iqServiceHost = myHost;
		  int iqServicePort = 6060;

		  RPCService service = new RPCService(iqServiceHost, iqServicePort, false, true); 
		  service.setConnectorServices(new sailpoint.connector.DefaultConnectorServices());
		  RpcRequest request = new RpcRequest("ScriptExecutor", "runAfterScript", data);
      
		  RpcResponse response = service.execute(request);
		}
    }
}

And here is the powershell script:

Add-type -Path C:\IdentityIQ\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);
$resultObject = New-Object Sailpoint.Utils.objects.ServiceResult;

Start-Sleep -Seconds 30  
  
foreach ($attribute in $requestObject.AttributeRequests){
	if($attribute.Name -eq "sAMAccountName"){
		# User Name
		$Username = $attribute.Value
		
		# Active Directory Group Name
		$GroupName = "CN=SAILPOINT-TEST-MOODLE,OU=Enterprise Groups,OU=DEV,OU=Sailpoint,OU=test,OU=KBP,DC=test,DC=intra"

		if (Get-ADGroup -Filter { Name -eq $GroupName }) {
			try {
				Add-ADGroupMember -Identity $GroupName -Members $Username
				Write-Output "User $Username added to group $GroupName successfully."
			} catch {
				Write-Output "Error adding user to group: $_"
			}
		} else {
			Write-Output "Group $GroupName does not exist."
		}
	}
}

If anyone can help me with the code issues, or any other ideas on how to solve this problem, I would be happy to hear from you.

Best Regards,
Danylo.

Hi @d_pustovoitov

Possible that where you have the group search filter:

You should have

1 Like

Hi @j_place ,

Thanks, I’ll check it now.

If there are multiple DC then you need to pass on which DC the user has been created.

Extract createdOnServer attribute from resultObject and server as parameter to below command -

Add-ADGroupMember -Identity $GroupName -Members $Username -Server <Value of created on server Name>
1 Like

Hi @j_place ,

Thanks, but it didn’t help.

Hi @d_pustovoitov - You will probably need @IAMpdu suggestion to target the same DC as the account creation as well

Hi @IAMpdu ,

Thanks for your reply.
I’ve tried it and added the next lines to the code.

This is for the rule:

String createServer = " ";
    ProvisioningResult result = plan.getResult();
      if (result != null)
      {
        ResourceObject resObj = result.getObject();
        if (resObj != null)
        {
          Attributes attrMap = resObj.getAttributes();
          if (attrMap != null &amp;&amp; attrMap.getString("createdOnServer") != null)
          {
            createServer = attrMap.getString("createdOnServer"); 
          }
        }  
      }
      
      
      AttributeRequest attrReq = new AttributeRequest();
      attrReq.setName("createServer");
      attrReq.setValue(createServer);
      
      accountRequest.add(attrReq);

And here is the updated PS script:

Add-type -Path C:\IdentityIQ\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);
$resultObject = New-Object Sailpoint.Utils.objects.ServiceResult;

Start-Sleep -Seconds 20 
  
#Check if the request was processed successfully
foreach ($attribute in $requestObject.AttributeRequests){
	if($attribute.Name -eq "sAMAccountName"){
		# User Name
		$Username = $attribute.Value
		
    foreach ($attribute in $requestObject.AttributeRequests){
			if($attribute.Name -eq "createServer"){
       #createdOnServer
       $createdOn = $attribute.Value
      }
      
		# Active Directory Group Name
		$GroupName = "CN=SAILPOINT-TEST-MOODLE,OU=Enterprise Groups,OU=DEV,OU=Sailpoint,OU=test,OU=KBP,DC=test,DC=net,DC=intra"

		# Check if the group exists, then add the user
		if (Get-ADGroup -Filter { DistinguishedName -eq $GroupName }) {
			try {
				Add-ADGroupMember -Identity $GroupName -Members $Username -Server $createdOn
				Write-Output "User $Username added to group $GroupName successfully."
			} catch {
				Write-Output "Error adding user to group: $_"
			}
		} else {
			Write-Output "Group $GroupName does not exist."
		}
	}
}

And now I’m getting the next error:

Caused by: org.apache.bsf.BSFException: The application script threw an exception: sailpoint.tools.GeneralException: Exception occurred while executing the RPCRequest: Errors returned from IQService. After script returned non zero exit code : 1 : BSF info: USB : AD : After Provisioning at line: 0 column: columnNo

I’ve checked the forum for this error and found a few themes.
As it mentioned there I’ve added this line
<entry key="program" value="powershell.exe"/>
and increased the “timeout” value in the PS Rule Object, but it didn’t help.

You could potentially achieve this by an assignment rule on a bundle that is tied to the AD group as long as you have a flag or some condition you can check if the user has completed the IT security test. This way all logic for group assignment is within IIQ and not an external source.

1 Like

Hi @nbhansali ,

Unfortunately, that’s not possible for us because this external source has a closed internal logic and does not add or update any flags on the AD account.

Ahh gotcha! I would possibly look to the options within your Identity Refresh task then. I think the problem is that the entitlement remains on your cube so regardless of what’s happening in your target system IIQ will over-write it and enforce the entitlement. Perhaps a hook somewhere to remove the entitlement from the cube in IIQ.

2 Likes

@d_pustovoitov when user completes the IT security test, is there any flag somewhere sets in identity ? Or in any target app ?

1 Like

Hi @d_pustovoitov - Coming at it from a different angle; I believe AD LDAP honours the memberOf attribute (I say honours because it’s not a real attribute). I haven’t tried it but maybe you could try attribute mapping the (fixed) group DN to memberOf as part of account creation?

1 Like

PS - I can’t remember why i think AD honours memberOf over LDAP, I could be wrong :wink:

Hi @pravin_ranjan ,

There is a flag in the testing software but it’s out of the project scope, so there is no integration to check on it.

Hi @j_place ,
I’ve used the memberOf as an attribute in the account provisioning form for the AD and it works! Even with the multiple groups. And after manually deleting it in the AD, the IIQ doesn’t try to get the entitlement back.

I think I’ll show this to the team, they’ll decide if it’s more suitable than using the PS script in AfterProvisioning Rule or Joiner WF. So I might update the thread if they don’t like this solution :frowning:

Thank you very much!

1 Like

Wow - TBH, I wasn’t sure why I thought memberOf had been updated with some sort of LDAP wrapper, thought I was losing my mind a bit. But, good news!