Identities with cloudLifecycleState equals postTerm

I need to develop powershell script to get the identities with cloudLifecycleState equals postTerm. Please suggest with API call options.

Extending the requirement further.
Automated email through powerShell script for
for Identities cloudLifecycleState equals postTerm and enabled accounts for all sources but exclude given source ids in string arraylist.

Hi @rvemula I am sharing you the API which will get the identities with cloudLifecycleState equals “postTerm”.

This is the API i.e List Identities with end point https://sailpoint.api.identitynow.com/beta/identities

Here is the documentation link list-identities | SailPoint Developer Community

You need to use filter cloudStatus eq “postTerm”

Now you can use this end point in your PowerShell script using PAT and you will get the identities whose cloudLifecycleState is “postTerm”

1 Like

400 bad request, this filter is not working

Hi @rvemula,

You can use the search API to achieve this.

Use something like this in the body. You can add the required filters in the body to limit the fields returned in the output JSON.

{
    "indices": [
        "identities"
    ],
    "query": {
        "query": "attributes.cloudLifecycleState:postTerm"
    },
    "queryResultFilter": {
        "includes": [
            "name",
            "email"
        ]
    }
}

Can you please share the Screen Shot. Because this should work fine.

Please check the requirement, I have edited now in detail.

Hi @rvemula,

You could modify the search query to something like this and mention the required sources :

attributes.cloudLifecycleState:postTerm AND @accounts(source.name:"ActiveDirectory" AND disabled:false)

This search query (UI) is using out of the box configuration and have to manually configure. The requirement I have is to build generic script to get all identities with cloudLifecycleState equals postterm and enabled accounts for all sources but exclude given source ids in string arraylist.

@rvemula In below pasted SS just replace cloud Life cycle state and source name with source id as per your requirements.


This may help you .

The query can be used in the API call, instead of the UI.

You will probably need to mention the sources in the query if you need to include or exclude certain sources.

{
    "indices": [
        "identities"
    ],
    "query": {
        "query": "attributes.cloudLifecycleState:postTerm AND @accounts(source.name:"ActiveDirectory" AND disabled:false)"
    },
    "queryResultFilter": {
        "includes": [
            "name",
            "email"
        ]
    }
}

Thanks for all your suggestions. Finally I have run this code and generate the csv dynamically. Please suggest if you find any changes required in the code.

    $Tenant=""
    $ClientId=""
    $ClientSecret=""
    $ExportFilePath=""
    $excludeSourceNames = @('IdentityNow','Workday Preview','Workday HRMS')

Class WorkerClass {
    $FirstName
    $LastName
    $Email
    $id
    $cls
    $accountsEnabledSources
   
}

$Headers = New-Object  "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("Content-Type", "application/json")
$Headers.Add("Accept", "application/json")
$grant_type = "client_credentials"

$Token = Invoke-WebRequest -Uri "https://$($Tenant).api.identitynow.com/oauth/token?grant_type=$($grant_type)&client_id=$($ClientId)&client_secret=$($ClientSecret)" -Method Post
$Token = $Token.Content | ConvertFrom-Json

$Headers.Add("Authorization", "Bearer $($Token.access_token)")


$limit  = 500
$CountUri = "https://$($Tenant).api.identitynow.com/v2024/search?count=true&limit=$($limit)"
$Query = '{"indices": ["identities"],"query": {"query": "attributes.cloudLifecycleState:postTerm"},`"sort`": [`"id`"]}'

$CountResponse = Invoke-WebRequest -Uri $CountUri -Method Post -Headers $Headers -Body $Query




$FullCountString =  $CountResponse.Headers.'X-Total-Count'
$FullCount = [int]$FullCountString

Write-Host("Full Count :: "+ $FullCount)

$FullSailPointIdentities = @()

$offset=0



if($FullCount -gt 500){
    do{
        

        if($offset -ge 500) {
            $Query = "{`"indices`": [`"identities`"],`"query`": {`"query`": `"attributes.cloudLifecycleState:postTerm`"},`"sort`": [`"id`"],`"searchAfter`":[`"$(($FullSailPointIdentities | select -Last 1).id)`"]}"
        }

        $Url = "https://$($Tenant).api.identitynow.com/v2024/search?limit=$($limit)"
        $Response = Invoke-WebRequest -Uri $Url -Method Post -Headers $Headers -Body $Query

        Write-host("Do while Loop :: JSON Body: "+$Query+ "  "+"offset: " + $offset+"  limit: "+$limit)
        
        $FullSailPointIdentities += $Response.Content | ConvertFrom-Json
        $offset += 500
        
    }while($offset -le $FullCount)
}

 $AllWorkers = @()
 

 $RecordCount=0

foreach($SailPointIdentity in $FullSailPointIdentities){
    $Worker = [WorkerClass]::new()
    $Worker.FirstName =  $SailPointIdentity.attributes.firstname
    $Worker.LastName =  $SailPointIdentity.attributes.lastname
    $Worker.Email =  $SailPointIdentity.attributes.email
    $Worker.id =  $SailPointIdentity.id
    $Worker.cls = $SailPointIdentity.attributes.cloudLifecycleState
    try{
 
           $accountURL = "https://$($Tenant).api.identitynow.com/v3/accounts?filters=identityId eq ""$($Worker.id)"""
           $accountresponse = Invoke-RestMethod -Uri $accountURL -Method 'GET' -Headers $headers  -ContentType "application/json" 
                  
           $SB = New-Object -TypeName System.Text.StringBuilder

           foreach($identityaccount in $accountresponse){

                

                if($excludeSourceNames -notcontains $identityaccount.sourceName) {
                    $disabledValue = $identityaccount.disabled
                    if ($disabledValue -ne $null -and $disabledValue -ne "True") {

                        $SB.Append($identityaccount.sourceName +";   ")
                    }

                }
           }

           if($SB.ToString().Length -gt 0) {

                $Worker.accountsEnabledSources =  $SB.ToString()
                $AllWorkers += $Worker

            }
   
            
    } catch{
            $ErrorMessage = $_.Exception.Message
            $ErrorItem = $_.Exception.ItemName
            Write-Host("Error: Item = $ErrorItem -> Message = $ErrorMessage")
    }
            Remove-Variable Worker

            $RecordCount=$RecordCount+1

            Write-Host("Checked count "+$RecordCount+"  out of total:: "+$FullSailPointIdentities.Count)
           
}

$AllWorkers | Export-Csv "$($ExportFilePath)" -Append -Force -NoTypeInformation
1 Like