Active Directory - mS-DS-ConsistencyGuid

Which IIQ version are you inquiring about?

8.4p3

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

Hello,

I’m working on an integration involving an old Active Directory environment where the attribute mS-DS-ConsistencyGuid is already populated on user accounts.

My goal is to synchronize this value into a new Active Directory during account creation.

What I’ve done so far

I defined mS-DS-ConsistencyGuid as a string attribute in both application schemas.

On the new AD application, I added an Account Creation Provisioning Policy field:

<Field displayName="mS-DS-ConsistencyGuid" name="mS-DS-ConsistencyGuid" type="string">
    <RuleRef>
        <Reference class="sailpoint.object.Rule" name="AD - Account Creation - Field Value Rule"/>
    </RuleRef>
</Field>

Rule logic (simplified)

java

case "mS-DS-ConsistencyGuid": {
    IdentityService is = new IdentityService(context);
    Application oldAD = context.getObjectByName(Application.class, "Old AD");

    List<Link> oldADLinks = is.getLinks(identity, oldAD);
    Link mainAD = null;

    for (Link l : oldADLinks) {
        if (identity.getName().equals(l.getAttribute("sAMAccountName"))) {
            mainAD = l;
            break;
        }
    }

    if (mainAD == null) return;

    return mainAD.getAttribute("mS-DS-ConsistencyGuid");
}

The issue

In the old AD, the attribute looks like this:

mS-DS-ConsistencyGuid: {11111111-2222-3333-4444-555555555555}

But in the new AD, the attribute in the account is this:

mS-DS-ConsistencyGuid: {5c31315c-3131-315c-315c-31315c32325c}

It seems the second value is the hex-encoded representation of the ASCII characters, meaning AD is interpreting the string incorrectly.

From what I’ve researched, mS-DS-ConsistencyGuid is stored as a System.Byte[]in Active Directory.

I tried:

  • Removing {}

  • Removing -

  • Passing the GUID as a raw string

  • Converting the string to byte[] in a Before Provisioning Rule

but none of these attempts worked.

My questions

  1. Is defining this attribute as a string in the schema correct, or should it be defined as a another type?

  2. Is there a successful example of provisioning a GUID into AD?

  3. If the attribute must be binary, what is the correct way to convert the GUID string into the byte[] format that AD expects?

Any guidance or examples would be greatly appreciated.

@bruno-co Try to convert to byte using Util method and see if its working.

sailpoint.tools.Util

byte[] mS-DS-ConsistencyGuid = Util.serializableObjectToBytes(mainAD.getAttribute(“mS-DS-ConsistencyGuid”))

Using the serializableObjectToBytes, I’m getting this Result in the provisioning transactions:

And the Attribute Request shows the proper value type in the Provisioning Plan:

<ProvisioningPlan nativeIdentity="User1" targetIntegration="AD New">
  <AccountRequest application="AD New" nativeIdentity="CN=User1,OU=Users,OU=MyOrg,DC=ad,DC=com" op="Create" targetIntegration="AD New">
    ...
    <AttributeRequest name="mS-DS-ConsistencyGuid" op="Set">
      <Value>
        <ByteArray><![CDATA[rO0ABXQAJnsxMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTV9]]></ByteArray>
      </Value>
    </AttributeRequest>
    <ProvisioningResult status="committed"/>
  </AccountRequest>
  ...
</ProvisioningPlan>

No errors appear in IQService, but the IdentityRequest remains stuck in Pending:

<IdentityRequestItem application="AD New" approvalState="Finished" compilationStatus="Expansion" name="mS-DS-ConsistencyGuid" nativeIdentity="CN=User1,OU=Users,OU=MyOrg,DC=ad,DC=com" operation="Set" provisioningEngine="AD New" provisioningState="Pending" value="[B@7f5c66ed">

The value is also not being set in AD:

Do you have any suggestions on how to force the provisioningState to move from Pending to Finished?

@bruno-co Can you try removing hyphen (-) and curly braces {} from the original attribute value and then convert to byte format?

Hi @SivaprakashRNTBCI!

Its still in pending. I added some logs to see what is being provisioned:

[AD New] mS-DS-ConsistencyGuid: {11111111-1111-1111-1111-111111111111}
[AD New] clean: 11111111111111111111111111111111
[AD New] bytearry: [B@3a20c02a
-84 -19 0 5 116 0 32 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49

I noticed the byte array had some initial values so I also tried to remove them but still got the same result:

[AD New] bytearry clean: [B@646ef4c5
49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49

If an AD attribute requires values to be passed as byte array, then direct AD connector (IQService) wouldn’t work (thumbnailPhoto is a popular limitation).

Try using nativerules to make the update, make sure to send the value as string so that IQService wouldn’t strip it.

From my understanding, for Active Directory, all provisioning is done through IQService. Is this wrong?

If so, how can I use IQService to make the update?

I increased the log level of IQService to debug and got this:

RpcHandler [ Thread-5 ] INFO : "[TLS] IncomingRequest:

<RpcRequest method="provision" service="ADConnector" version="1.0">
...
<AttributeRequest name="mS-DS-ConsistencyGuid" op="Set">
    <Value>
        <ByteArray><![CDATA[MTExMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExMTEx]]></ByteArray>
    </Value>
</AttributeRequest>
...
</RpcRequest>
XmlFactory [ Thread-5 ] DEBUG : "Unknown/Unhandled tag [ByteArray] skipped."

@bruno-co If passing value as byte is not working, you can use IQService before script and set value through PowerShell.

Refer the below link for example scripts

@bruno-co I have just edited the reply, hope it’s a bit clear now.

TL;DR native rules are to be used if provisioning needs to be done for any AD attribute that needs value to be passed as bytes.

You can use the link provided by @SivaprakashRNTBCI to update the attribute mS-DS-ConsistencyGuid using native rules. Specifically the following section which reads the result of the provisioning operation and does actions.

Make sure to convert the value into bytearrary while setting it via PowerShell (

Set-ADUser ...

otherwise you may have the same problem as earlier where AD is interpreting the attribute as string incorrectly

I’ve created the following ConnectorAfterCreate Rule and configured it in my Application XML:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="AD New - ConnectorAfterCreate - Powershell" type="ConnectorAfterCreate">
  <Attributes>
    <Map>
      <entry key="disabled" value="false"/>
      <entry key="extension" value=".ps1"/>
      <entry key="objectOrientedScript" value="true"/>
      <entry key="program" value="powershell.exe"/>
      <entry key="timeout" value="1"/>
    </Map>
  </Attributes>
  <Description>IQService After Script. This is a PowerShell after script which ensures that the mS-DS-ConsistencyGuid is correctly set on the account.</Description>
  <Source>
# Load SailPoint class library
Add-Type -Path utils.dll

# Read environment variables
$sReader  = New-Object System.IO.StringReader([string]$env:Request);
$sResult  = New-Object System.IO.StringReader([string]$env:Result);

# Form XML readers
$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);

# Get nativeIdentity
$nativeIdentity = $requestObject.NativeIdentity;

# Extract mS-DS-ConsistencyGuid
$consistencyGuid = $null;

foreach ($attribute in $requestObject.AttributeRequests) {
  if ($attribute.name -eq "mS-DS-ConsistencyGuid") {
    $consistencyGuid = $attribute.value;
    break
  }
}

# Write GUID to AD
Import-Module ActiveDirectory

Set-ADObject -Identity $nativeIdentity -Replace @{ "mS-DS-ConsistencyGuid" = ([Guid]$consistencyGuid).ToByteArray() };
  </Source>
</Rule>

When this runs, the logs show:
After script returned non zero exit code : -1

I confirmed that the error is coming from the Set-ADObject call. If I insert an exit 0 immediately before that line, the script returns 0 as expected.

I also tried adding -Credential with the service account, but the result is the same. It works when executed directly in PowerShell.

Questions

  1. Do you see anything wrong with the script itself?

  2. Is there a way to add logging inside the PowerShell script so I can inspect the value of $consistencyGuid?

@bruno-co Check the IQService log for any errors. If you cannot find anything, try adding a condition to check if the account exist in AD (Get-ADUser command) before modifying the attribute.

I don’t see any error on logs and the request is successful.

It is returning code 0:
AbstractConnector [ Thread-11 ] DEBUG : “Script return code : 0”

Is it possible to print or log somewhere the value of $consistencyGuid?

I added the following validation after getting the $consistencyGuid:

# Validate the GUID value
if ([string]::IsNullOrWhiteSpace($consistencyGuid)) {
    exit -1;
}

And I’m getting the -1:

AbstractConnector [ Thread-10 ] DEBUG : "After script returned non zero exit code : -1 : "

Does this mean I’m not being able to read the consistencyGuid?

@bruno-co Based on your code, i have pinged few things to check over chat. Could you please confirm if you have already tried it or not?

In the above scenario, does the trace still show the below log?

If yes then you have to make sure to pass the attribute value as string in IIQ plan to make sure IQService doesn’t strip it.

Even before that try running the following powershell cmdlet in the IQService directly with hardcoded value to make sure that the syntax works.

Hi @BhuvaneshGeddam,

I changed it back to String, right now I’m receiving the following:

<entry key="Request">
  <value>
    <AccountRequest application="AD New" nativeIdentity="CN=User1,OU=Users,OU=MyOrg,DC=ad,DC=com" op="Create" trackingId="xxxxx">
        ...
        <AttributeRequest name="mS-DS-ConsistencyGuid" op="Set" value="11111111-1111-1111-1111-111111111111"/>
    </AccountRequest>
  </value>
</entry>

I’ve tried the Set-ADObject from PowerShell for this nativeIdentity and for this ConsistencyGuid value and it works.

Is the after script still returning non zero exit after changing it back to string? If yes, try printing the attributerequest as xml

Yes, it is still returning non zero. This is the full log:

04.01.2026 09:56:30 : RpcHandler [ Thread-8 ] INFO : "[TLS] IncomingRequest:
<?xml version='1.0' encoding='UTF-8'?>
<RpcRequest method="provision" service="ADConnector" version="1.0">
  <Arguments>
    <Map>
      <entry key="Application">
        <value>
          <Attributes>
            <Map>
              <entry key="IQServiceConfiguration">
                <value>
                  <List>
                    <Map>
                      <entry key="IQServiceHost" value="***"/>
                      <entry key="IQServicePassword" value="**********"/>
                      <entry key="IQServicePort" value="***"/>
                      <entry key="IQServiceUser" value="***"/>
                      <entry key="useTLSForIQService">
                        <value>
                          <Boolean>true</Boolean>
                        </value>
                      </entry>
                    </Map>
                  </List>
                </value>
              </entry>
              <entry key="acctAggregationEnd">
                <value>
                  <Date>1774996188589</Date>
                </value>
              </entry>
              <entry key="acctAggregationStart">
                <value>
                  <Date>1774996160531</Date>
                </value>
              </entry>
              <entry key="activeAppSync" value="true"/>
              <entry key="afterProvisioningRule" value="AD AfterProvisioning"/>
              <entry key="aggregationPartitioned">
                <value>
                  <Boolean></Boolean>
                </value>
              </entry>
              <entry key="aggregationType" value="group"/>
              <entry key="allowAutoPartitioning">
                <value>
                  <Boolean>true</Boolean>
                </value>
              </entry>
              <entry key="approvalBuilder"/>
              <entry key="authSearchAttributes">
                <value>
                  <List>
                    <String>sAMAccountName</String>
                  </List>
                </value>
              </entry>
              <entry key="autoPartitionCount" value="256"/>
              <entry key="beforeProvisioningRule" value="AD BeforeProvisioning"/>
              <entry key="compositeDefinition"/>
              <entry key="deletedObjectsContainer" value="CN=Deleted Objects,DOMAIN"/>
              <entry key="deltaAggregation">
                <value>
                  <Map>
                    <entry key="dc=ad,dc=com">
                      <value>
                        <Map>
                          <entry key="groups_cookie" value="***"/>
                          <entry key="lastDirsyncServer" value="***"/>
                          <entry key="users_cookie" value="***"/>
                        </Map>
                      </value>
                    </entry>
                  </Map>
                </value>
              </entry>
              <entry key="deltaIterationMode" value="dirSync"/>
              <entry key="domainSettings">
                <value>
                  <List>
                    <Map>
                      <entry key="authenticationType" value="simple"/>
                      <entry key="authorizationType" value="simple"/>
                      <entry key="domainDN" value="DC=ad,DC=comk"/>
                      <entry key="domainIterateSearchFilter"/>
                      <entry key="domainNetBiosName"/>
                      <entry key="enablePasswordLessAuthenticationForDomain">
                        <value>
                          <Boolean></Boolean>
                        </value>
                      </entry>
                      <entry key="forestName" value="defaultForest"/>
                      <entry key="password" value="**********"/>
                      <entry key="port" value="636"/>
                      <entry key="servers">
                        <value>
                          <List>
                            <String>***</String>
                          </List>
                        </value>
                      </entry>
                      <entry key="useSSL">
                        <value>
                          <Boolean>true</Boolean>
                        </value>
                      </entry>
                      <entry key="user" value="***"/>
                    </Map>
                  </List>
                </value>
              </entry>
              <entry key="earlyDeletion">
                <value>
                  <Boolean></Boolean>
                </value>
              </entry>
              <entry key="encrypted" value="domainSettings.password,forestSettings.password"/>
              <entry key="exchangeversion" value="DEFAULT"/>
              <entry key="fallbackApprover" value="***"/>
              <entry key="forestSettings">
                <value>
                  <List>
                    <Map>
                      <entry key="authenticationType" value="simple"/>
                      <entry key="authorizationType" value="simple"/>
                      <entry key="enablePasswordLessAuthenticationForForest">
                        <value>
                          <Boolean></Boolean>
                        </value>
                      </entry>
                      <entry key="forestName" value="defaultForest"/>
                      <entry key="gcServer" value="***"/>
                      <entry key="isResourceForest">
                        <value>
                          <Boolean></Boolean>
                        </value>
                      </entry>
                      <entry key="manageAllDomains">
                        <value>
                          <Boolean></Boolean>
                        </value>
                      </entry>
                      <entry key="password"/>
                      <entry key="useGroupMembershipPreloading"/>
                      <entry key="useSSL">
                        <value>
                          <Boolean></Boolean>
                        </value>
                      </entry>
                      <entry key="user"/>
                    </Map>
                  </List>
                </value>
              </entry>
              <entry key="group.searchDNs">
                <value>
                  <List>
                    <Map>
                      <entry key="iterateSearchFilter" value="(objectClass=Group)"/>
                      <entry key="searchDN" value="OU=GROUPS,OU=MyOrg,DC=ad,DC=com"/>
                      <entry key="searchScope" value="SUBTREE"/>
                    </Map>
                  </List>
                </value>
              </entry>
              <entry key="lyncAttributes" value="RegistrarPool,SipAddressType,SipAddress,SipDomain,msRTCSIP-UserEnabled"/>
              <entry key="manageLync">
                <value>
                  <Boolean></Boolean>
                </value>
              </entry>
              <entry key="manageRecycleBin">
                <value>
                  <Boolean></Boolean>
                </value>
              </entry>
              <entry key="nativeChangeDetectionAttributeScope" value="entitlements"/>
              <entry key="nativeChangeDetectionAttributes"/>
              <entry key="nativeChangeDetectionEnabled">
                <value>
                  <Boolean></Boolean>
                </value>
              </entry>
              <entry key="nativeChangeDetectionOperations"/>
              <entry key="nativeRules">
                <value>
                  <List>
                    <String>AD New - Account Creation - After Create - Powershell</String>
                  </List>
                </value>
              </entry>
              <entry key="pageSize" value="100"/>
              <entry key="searchDNs">
                <value>
                  <List>
                    <Map>
                      <entry key="iterateSearchFilter" value="(objectClass=Group)"/>
                      <entry key="searchDN" value="OU=GROUPS,OU=MyOrg,DC=ad,DC=com"/>
                      <entry key="searchScope" value="SUBTREE"/>
                    </Map>
                  </List>
                </value>
              </entry>
              <entry key="sysDescriptions">
                <value>
                  <Map>
                    <entry key="en"/>
                    <entry key="en_US" value="***"/>
                  </Map>
                </value>
              </entry>
              <entry key="templateApplication" value="Active Directory Template"/>
              <entry key="useSSL" value="false"/>
            </Map>
          </Attributes>
        </value>
      </entry>
      <entry key="Request">
        <value>
          <AccountRequest application="AD New" nativeIdentity="CN=User1,OU=Users,OU=MyOrg,DC=ad,DC=com" op="Create" trackingId="ec9e11f4d15649cf8bda897f890a76fb">
            <Attributes>
              <Map>
                <entry key="attachmentConfigList"/>
                <entry key="attachments"/>
                <entry key="flow" value="AccessRequest"/>
                <entry key="id" value="0a89f4f198f019078198f621756f12c8"/>
                <entry key="interface" value="LCM"/>
                <entry key="nativeIdUpdated">
                  <value>
                    <Boolean>true</Boolean>
                  </value>
                </entry>
                <entry key="operation" value="EntitlementAdd"/>
              </Map>
            </Attributes>
            <AttributeRequest assignmentId="5ed4236755204d27967bc76640afce7b" displayValue="AD-New-Group1" name="memberOf" op="Add" trackingId="ec9e11f4d15649cf8bda897f890a76fb" value="CN=AD-New-Group1,OU=GROUPS,OU=MyOrg,DC=ad,DC=com">
              <Attributes>
                <Map>
                  <entry key="assignment" value="true"/>
                </Map>
              </Attributes>
            </AttributeRequest>
            <AttributeRequest name="displayName" op="Set" value="***"/>
            <AttributeRequest name="mail" op="Set" value="***"/>
            <AttributeRequest name="sAMAccountName" op="Set" value="***"/>
            <AttributeRequest name="accountExpires" op="Set" value="0"/>
            <AttributeRequest name="objectClass" op="Set" value="user"/>
            <AttributeRequest name="userAccountControl" op="Set">
              <Value>
                <Integer>512</Integer>
              </Value>
            </AttributeRequest>
            <AttributeRequest name="pwdLastSet" op="Set">
              <Value>
                <Boolean>true</Boolean>
              </Value>
            </AttributeRequest>
            <AttributeRequest name="company" op="Set" value="***"/>
            <AttributeRequest name="co" op="Set" value="***"/>
            <AttributeRequest name="c" op="Set" value="**"/>
            <AttributeRequest name="countryCode" op="Set" value="***"/>
            <AttributeRequest name="l" op="Set" value="***"/>
            <AttributeRequest name="streetAddress" op="Set" value="***"/>
            <AttributeRequest name="postalCode" op="Set" value="***"/>
            <AttributeRequest name="st" op="Set" value="Vaud"/>
            <AttributeRequest name="initials" op="Set" value="***"/>
            <AttributeRequest name="employeeID" op="Set" value="***"/>
            <AttributeRequest name="password" op="Set" value="**********">
              <Attributes>
                <Map>
                  <entry key="secret" value="true"/>
                </Map>
              </Attributes>
            </AttributeRequest>
            <AttributeRequest name="mS-DS-ConsistencyGuid" op="Set" value="11111111-1111-1111-1111-111111111111"/>
          </AccountRequest>
        </value>
      </entry>
      <entry key="postScript">
        <value>
          <Rule created="1774860948219" id="0a89f4f19d001352819d3df4d2fb3d11" language="beanshell" modified="1775030019422" name="AD New - Account Creation - After Create - Powershell" significantModified="1775030019422" type="ConnectorAfterCreate">
            <Attributes>
              <Map>
                <entry key="disabled" value="false"/>
                <entry key="extension" value=".ps1"/>
                <entry key="objectOrientedScript" value="true"/>
                <entry key="program" value="powershell.exe"/>
                <entry key="timeout" value="60"/>
              </Map>
            </Attributes>
            <Description>IQService After Script. This is a PowerShell after script which ensures that the mS-DS-ConsistencyGuid is correctly set on the account.</Description>
            <Source>
# Load SailPoint class library
Add-Type -Path utils.dll

# Read environment variables
$sReader  = New-Object System.IO.StringReader([string]$env:Request);
$sResult  = New-Object System.IO.StringReader([string]$env:Result);

# Form XML readers
$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);

# Get nativeIdentity
$nativeIdentity = $requestObject.NativeIdentity;

# Extract mS-DS-ConsistencyGuid
$consistencyGuid = $null;

foreach ($attribute in $requestObject.AttributeRequests) {
  if ($attribute.Name -eq "mS-DS-ConsistencyGuid") {
    $consistencyGuid = $attribute.Value;
    break
  }
}

# Validate the GUID value
if ([string]::IsNullOrWhiteSpace($consistencyGuid)) {
    exit -2;
}

# Write GUID to AD
Import-Module ActiveDirectory
  
Get-ADUser -Identity $nativeIdentity

Set-ADObject -Identity $nativeIdentity `
  -Replace @{ "mS-DS-ConsistencyGuid" = ([Guid]$consistencyGuid).ToByteArray() };
  </Source>
          </Rule>
        </value>
      </entry>
    </Map>
  </Arguments>
</RpcRequest>

I added some logs and the issue seems to be with reading Environment Variables. I tried printing their value and its empty.

Is there anything wrong with my script when reading these variables?

Are there any special permissions needed to read Environment Variables?

@bruno-co Have you tried adding complete path for SailPoint class library like below?
image

Even with the full path I’m still getting the same result :confused:

I added a log to show the value of sReader but it is returning an empty string:

$sReader  = New-Object System.IO.StringReader([string]$env:Request);

$sReader.ReadToEnd() | Out-File -FilePath "E:\temp\Temp.log" -Append

Is this expected or should it have some value?