Attribute sync issue

Hi everyone,

I’m working on a complex use case with IdentityNow where we need to implement custom provisioning logic across multiple target systems with varying schema attributes. I’ve been experimenting with Transformations and Entitlements in IdentityNow but am running into challenges ensuring consistent attribute mapping and real-time synchronization between IdentityNow and the target systems. Has anyone tackled a similar scenario?
Specifically, I’d like to hear about strategies for handling attribute normalization across different sources and maintaining synchronization integrity during high-volume provisioning tasks. Any guidance or best practices would be valuable!

We have a scenario where there is a potential for 30,000 accounts to be created in one go which the OOB connector to AD cannot cope with.
I’ve written a PS script that searches for a ‘prestage’ LCS and then changes it to ‘prestart’ which then provisions the AD account. It does take 8hrs to run, but it doesn’t fall over. (You can use workflow if you have paid for that module)
Is this what you are looking for?

If I understood correctly, you are looking for a way to use Transforms for all the target sources, change attribute names in your logics as per your target source ?

Hi @phil_awlings ,
We don’t have the workflow module enabled. Is there a way without using the workflows? If possible Can you share a sample of the script that you mentioned?

Here you go:
Its set for 2000 users at a time (about 26 minutes) with a 5 minute wait between cycles to allow SP to catch up, and I currently run it in VSC. Each API call takes around .75s to run. Hope this helps

# Load the SailPoint IdentityNow PowerShell module
Import-Module PSSailPoint

# Enter all parameters here
$tenant = ''
$clientID = ""
$clientSecret = ""

$token = Get-AccessToken -tenant $tenant -clientID $clientID -clientSecret $clientSecret

function Get-AccessToken {
    param (
        [String]$tenant,
        [String]$clientID,
        [String]$clientSecret
    )
    $params = @{
        uri    = "https://$tenant.api.identitynow.com/oauth/token?grant_type=client_credentials&client_id=$($clientID)&client_secret=$($clientSecret)"
        method = "POST"
    }
    return (Invoke-RestMethod @params).access_token
}

function Update-UserLifecycleState {
    param (
        [string]$tenant,
        [hashtable]$headers,
        [string]$queryBody,
        [string]$updateBody
    )

    do {
        $response = Invoke-RestMethod -Uri "https://$tenant.api.identitynow.com/v2024/search?limit=2000" -Method 'POST' -Headers $headers -Body $queryBody
        $userIDs = $response.id
        $userCount = $userIDs.Count

        Write-Progress -Activity "Updating User Lifecycle State" -Status "User Count = $userCount"

        if ($userCount -gt 0) {
            foreach ($userID in $userIDs) {
                $response = Invoke-RestMethod -Uri "https://$tenant.api.identitynow.com/v2024/identities/$userID/set-lifecycle-state" -Method 'POST' -Headers $headers -Body $updateBody
                $response | ConvertTo-Json

            }
        } else {
            Write-Progress -Activity "Updating User Lifecycle State" -Status "No more users to update."
        }

        if ($userCount -eq 2000) {
            start-sleep -seconds 300
        }

    } while ($userCount -eq 2000)
}

# Define headers and bodies
$headers = @{
    "Content-Type" = "application/json"
    "Accept" = "application/json"
    "Authorization" = "Bearer $token"
}

$queryBody = @"
{
    `"indices`": [
        `"identities`"
    ],
    `"query`": {
        `"query`": `"attributes.cloudLifecycleState:prestage`"
    },
    `"queryResultFilter`": {
        `"includes`": [
            `"id`"
        ]
    }
}
"@

# Updating to 'prestart'
$updateBody = @"
{
    `"lifecycleStateId`": `"*your source ID goes here `" 
}
"@

# Call the function
#Update-UserLifecycleState -tenant $tenant -headers $headers -queryBody $queryBody -updateBody $updateBody

# Measure the time taken to execute the Update-UserLifecycleState function
$executionTime = Measure-Command {
  Update-UserLifecycleState -tenant $tenant -headers $headers -queryBody $queryBody -updateBody $updateBody
}

# Output the total runtime
Write-Output "Total runtime: $($executionTime.Minutes) minutes and $($executionTime.Seconds) seconds"
3 Likes

@phil_awlings , Thank you for sharing this! Much appreciated! This should help!

2 Likes