Public/Get-IAMCoreObject.ps1

<#
.SYNOPSIS
    Gets core objects from the IAM Core API.

.DESCRIPTION
    This function retrieves core objects from the IAM Core API. It supports pagination to handle large

.EXAMPLE
    Get-IAMCoreObject -ObjectType "CoreIdentity"

.EXAMPLE
    Get-IAMCoreObject -ObjectType "CoreOrgUnit" -PageSize 5000
#>

function Get-IAMCoreObject {
    [CmdletBinding(DefaultParameterSetName = "Default")]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet("CoreIdentity", "CoreOrgUnit", "CoreRelationship")]
        [String] $ObjectType,

        [Parameter(Mandatory = $false, ParameterSetName = "Default")]
        [int] $PageSize = 10000,

        [Parameter(Mandatory = $false, ParameterSetName = "Default")]
        [ValidateRange(0, 50)]
        [int] $MaxRetries = 3,

        [Parameter(Mandatory = $true, ParameterSetName = "Single", ValueFromPipelineByPropertyName = $true)]
        [ValidatePattern("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", ErrorMessage = "Id must be a valid GUID.")] # Is a guid connector object id
        [string] $Id
    )

    process {
        if (-not $Script:APIRoot -or -not $Script:AccessTokenProfile) {
            throw "Not connected to IAM Core. Please run Connect-IAMCore first."
        }

        $Uri = "$Script:APIRoot/sync/coreobjects/"

        switch ($ObjectType) {
            "CoreIdentity" { $Uri += "identities" }
            "CoreOrgUnit" { $Uri += "orgunits" }
            "CoreRelationship" { $Uri += "relationships" }
        }

        if ($PSCmdlet.ParameterSetName -eq "Single") {
            $Uri += "/$Id"
            Write-Verbose "Getting IAM Core object from URI: $Uri"
            $Result = Invoke-RestMethod -Uri $Uri -Headers (Get-IAMCoreHeader) -SkipHttpErrorCheck -StatusCodeVariable StatusCode -Verbose:$false -ConnectionTimeoutSeconds 60 -OperationTimeoutSeconds 60

            if ($Result.IsSuccess) {
                return $Result.Data
            }
            else {
                throw "Failed to get IAM Core object: $($Result.ErrorMessage)"
            }
        }       

        $CurrentUri = "$($Uri)?pageSize=$($PageSize)"
        $ErrorCounter = 0
        $Page = 1
        while ($CurrentUri) {
            $Result = $null
            $StatusCode = $null
            try {
                Write-Verbose "Getting IAM Core object page $Page from URI: $CurrentUri"
                $Result = Invoke-RestMethod -Uri $CurrentUri -Headers (Get-IAMCoreHeader) -SkipHttpErrorCheck -StatusCodeVariable StatusCode -Verbose:$false -ConnectionTimeoutSeconds 60 -OperationTimeoutSeconds 60
                $ErrorCounter = 0
            }
            catch {
                $ErrorCounter += 1
                Write-Warning "Got error when getting IAM Core object: $_. Exception: $($_.Exception). Status code: $StatusCode. Attempt $ErrorCounter of $($MaxRetries + 1)."
                if ($ErrorCounter -ge $MaxRetries) {
                    throw "Exceeded maximum number of retries ($MaxRetries) for getting IAM Core object."
                    break
                }
                else {
                    Start-Sleep -Seconds ([Int]::Min(($ErrorCounter * $ErrorCounter), 20)) # Exponential backoff
                    continue
                }
            }

            $CurrentUri = $null

            if ($Result.IsSuccess) {
                $Result.Data
                $Page += 1
            
                if ($Result.NextCursor) {
                    Write-Debug "Next cursor: $($Result.NextCursor)"
                    $encodedNextCursor = [System.Web.HttpUtility]::UrlEncode($Result.NextCursor)
                    $CurrentUri = "$($Uri)?pageSize=$($PageSize)&nextCursor=$encodedNextCursor"
                }
            }
            else {
                throw "Failed to get IAM Core object: $($Result.ErrorMessage)"
            }
        }
    }
}