But in post solution you are saying that accountCount=sourceCount, that is not true, as under one source i can have multiple accounts.
Example:
My identity is present in 3 sources, but in one of the sources i have 5 accounts, so if i run search with “accountCount” i will have 7 accounts returned. But i need to get returned number of sources, that would be 3.
The BEST would be if i could generate a report with both - number of sources and number of accounts.
Example:
Identty | Number of sources | Number of accounts
Aleksandra H. | 3 | 7
Hey @karapuuzina, I wrote a quick PowerShell script that will generate a report according to what you’re looking for. Please feel free to modify as you see fit.
Script Purpose
Based on what you requested, this quick script will generate a report in CSV format with the following headers:
Identity Id
Identity Name
Number of Sources
Number of Accounts
Preqrequisites
Generate an Access Token by either grabbing the token from your web browser with an active session with Identity Security Cloud, or other means such as through Postman. You can also generate one via PowerShell. Whatever works for you!
Either enter the token into the $token variable, or provide it in the console when prompted.
Provide your SailPoint Identity Security Cloud API url, such as https://{Org name}.api.identitynow.com
Provide a name of a file and its path in the $exportFilePath variable to which the data should be exported. Make sure it is a text or CSV file. You can also just provide this in the console when prompted.
Script
# Preqrequisites
# 1. Generate an Access Token by either grabbing the token from your web browser with an active session with Identity Security Cloud, or other means such as through Postman. You can also generate one via PowerShell. Whatever works for you!
# 2. Either enter the token into the `$token` variable, or provide it in the console when prompted.
# 3. Provide your SailPoint Identity Security Cloud API url, such as `https://{Org name}.api.identitynow.com`
# 4. Provide a name of a file and its path in the `$exportFilePath` variable to which the data should be exported. **Make sure it is a text or CSV file**. You can also just provide this in the console when prompted.
#-------------------------------------------------- Variables --------------------------------------------------#
$token = "" # Either enter your access (bearer) token here or enter it into the console when prompted.
$uri = "https://{Org name}.api.identitynow.com"
$fileExportPath = "C:\SailPoint\AccountsReport.csv" # Define an appropriate file path for the data to be saved.
#---------------------------------------------------------------------------------------------------------------#
#------------------------------------------------ Begin Process ------------------------------------------------#
while (-not $token) {$token = Read-Host "Enter your Access Token"}
$AuthHeader = @{"Accept" = "application/json"; "Authorization" = "Bearer $token"}
try {
$allAccounts = Invoke-RestMethod -Uri "$uri/v3/accounts" -Method GET -Headers $AuthHeader
if (-not $allAccounts -or $allAccounts.Count -eq 0) {Write-Host "Response is empty." -BackgroundColor DarkYellow; return}
}
catch {
Write-Host "Exception returned when attempting to retrieve accounts. Exception: ""$($_.Exception.Message)""" -BackgroundColor DarkRed
return
}
$accountsGrouped = $allAccounts | Group-Object {$_.IdentityId}
$outData = @("Identity Id,Identity Name,Number of Sources,Number of Accounts")
$accountsGrouped | ForEach-Object {
$identityId = $_.Group.identityId | Sort-Object -Unique
$identityName = $_.Group.identity.name | Sort-Object -Unique
$sourceCount = $_.Group | Sort-Object sourceName -Unique | Select-Object sourceName | Measure-Object | % Count
$accountCount = $_.Count
$outData += "$identityId,$identityName,$sourceCount,$accountCount"
}
if (-not $outData) {Write-Host "The outData variable is empty; nothing is present to save." -BackgroundColor DarkYellow; return}
while (-not $fileExportPath) {$fileExportPath = Read-Host "Enter a file path to which the data should be saved. Provide a csv file name as well"}
$outData | Out-File $fileExportPath
#-------------------------------------------------- End Process --------------------------------------------------#
Disclaimer
If saving this script locally or remotely, be sure to remove the value from the $token variable. Although tokens are issued temporarily and will expire, it is always a best practice to ensure any form of credentials are not stored in plain text and insecure manners.
Hello @brennenscott ,
thank you for the prompt response.
Script works perfectly, except that it stops when account sum hits the default limit of 250.
I’ve tried to workaround it with "$uri/v3/accounts?limit=550", but it gives error 400 Bad request.
Any suggestions, how we can skip the limit, so all identities and accounts are in report.
As i have thousands of those in total
That’s a great point; the maximum count for list endpoints is 250, so we could either use the a Search endpoint which has a limit of 10,000, or we can just iterate with the list endpoint. I modified the script to iterate until no accounts are left by adjusting the offset by increments of 250 each time we retrieve accounts. Please see the updated script below, and let me know how it goes.
# Preqrequisites
# 1. Generate an Access Token by either grabbing the token from your web browser with an active session with Identity Security Cloud, or other means such as through Postman. You can also generate one via PowerShell. Whatever works for you!
# 2. Either enter the token into the `$token` variable, or provide it in the console when prompted.
# 3. Provide your SailPoint Identity Security Cloud API url, such as `https://{Org name}.api.identitynow.com`
# 4. Provide a name of a file and its path in the `$exportFilePath` variable to which the data should be exported. **Make sure it is a text or CSV file**. You can also just provide this in the console when prompted.
#-------------------------------------------------- Variables --------------------------------------------------#
$token = "" # Either enter your access (bearer) token here or enter it into the console when prompted.
$url = "https://{Org name}.api.identitynow.com"
$fileExportPath = "C:\Users\brennen.scott\Downloads\AccountsReport.csv" # Define an appropriate file path for the data to be saved.
#---------------------------------------------------------------------------------------------------------------#
#------------------------------------------------ Begin Process ------------------------------------------------#
while (-not $token) {$token = Read-Host "Enter your Access Token"}
$AuthHeader = @{"Accept" = "application/json"; "Authorization" = "Bearer $token"}
try {
$allAccounts = Invoke-RestMethod -Uri "$url/v3/accounts" -Method GET -Headers $AuthHeader
if (-not $allAccounts -or $allAccounts.Count -eq 0) {Write-Host "Response is empty." -BackgroundColor DarkYellow; return}
# Begin iterating if count is 250, then continue until response is empty, meaning there are no more accounts left to gather
if ($allAccounts.Count -eq 250) {
$iteratedAccounts = @("Empty")
for ($offset = 250; $iteratedAccounts.Count -ne 0; $offset += 250) {
$iteratedAccounts = Invoke-RestMethod -Uri "$url/v3/accounts?offset=$offset" -Method GET -Headers $AuthHeader
$allAccounts += $iteratedAccounts
}
}
}
catch {
Write-Host "Exception returned when attempting to retrieve accounts. Exception: ""$($_.Exception.Message)""" -BackgroundColor DarkRed
return
}
$accountsGrouped = $allAccounts | Group-Object {$_.IdentityId}
$outData = @("Identity Id,Identity Name,Number of Sources,Number of Accounts")
$accountsGrouped | ForEach-Object {
$identityId = $_.Group.identityId | Sort-Object -Unique
$identityName = $_.Group.identity.name | Sort-Object -Unique
$sourceCount = $_.Group | Sort-Object sourceName -Unique | Select-Object sourceName | Measure-Object | % Count
$accountCount = $_.Count
$outData += "$identityId,$identityName,$sourceCount,$accountCount"
}
if (-not $outData) {Write-Host "The outData variable is empty; nothing is present to save." -BackgroundColor DarkYellow; return}
while (-not ($fileExportPath)) {$fileExportPath = Read-Host "Enter a file path to which the data should be saved. Provide a csv file name as well"}
$outData | Out-File $fileExportPath
#-------------------------------------------------- End Process --------------------------------------------------#
Just to build on this, it can also be done by using the search endpoint and pulling back all identities instead of accounts. Since the returned identities include nested accounts, we can have Powershell count the accounts under each identity.
Using the bones from @brennenscott’s script (note: I also did my loop a little differently as a matter of personal preference, but either way should realistically work):
# Preqrequisites
# 1. Generate an Access Token by either grabbing the token from your web browser with an active session with Identity Security Cloud, or other means such as through Postman. You can also generate one via PowerShell. Whatever works for you!
# 2. Either enter the token into the `$token` variable, or provide it in the console when prompted.
# 3. Provide your SailPoint Identity Security Cloud API url, such as `https://{Org name}.api.identitynow.com`
# 4. Provide a name of a file and its path in the `$exportFilePath` variable to which the data should be exported. **Make sure it is a text or CSV file**. You can also just provide this in the console when prompted.
#-------------------------------------------------- Variables --------------------------------------------------#
$token = "" # Either enter your access (bearer) token here or enter it into the console when prompted.
$url = "https://{Org name}.api.identitynow.com"
$fileExportPath = "C:\Users\brennen.scott\Downloads\AccountsReport.csv" # Define an appropriate file path for the data to be saved.
#---------------------------------------------------------------------------------------------------------------#
#------------------------------------------------ Begin Process ------------------------------------------------#
while (-not $token) {$token = Read-Host "Enter your Access Token"}
$AuthHeader = @{"Accept" = "application/json"; "Authorization" = "Bearer $token"}
$body = @{
query = @{
query = '*'
}
queryResultFilter = @{
includes = @(
"id"
"name"
"accounts"
)
}
sort = @(
'id'
)
indices = @(
'identities'
)
}
try {
$allIdentities = Invoke-RestMethod -Uri "$url/v3/search?count=true" -Method POST -Body ($body | ConvertTo-Json) -Headers $AuthHeader -ResponseHeadersVariable responseHeaders -ContentType 'application/json' -ErrorAction Stop
if (-not $allIdentities -or $allIdentities.Count -eq 0) {
Write-Host "Response is empty." -BackgroundColor DarkYellow
return
}
$totalCount = [int]::Parse($responseHeaders.'X-Total-Count')
$retrievedCount = $allIdentities.Count
Write-Host "Retrieved $retrievedCount items out of total $totalCount."
while ($retrievedCount -lt $totalCount) {
$p = $retrievedCount/$totalCount
Write-Progress -Activity "Retrieving identities" -Status "Retrieved $retrievedCount of $totalCount - $($p.ToString("P")) Complete" -PercentComplete ($p*100)
try {
$nextQuery = $body + @{searchAfter = @($allIdentities[-1].id) }
$allIdentities += Invoke-RestMethod -Uri "$url/v3/search" -Method Post -Body ($nextQuery | ConvertTo-Json) -Headers $AuthHeader -ContentType 'application/json' -ErrorAction Stop
$retrievedCount = $allIdentities.count
}
catch {
Write-Host "Retrieval failed. Will try again. Exception: $($_.Exception.Message)"
}
}
}
catch {
Write-Host "Exception returned when attempting to retrieve identities. Exception: $($_.Exception.Message)" -BackgroundColor DarkRed
return
}
$outData = $allIdentities | Select-Object id,name,@{label="sourceCount";expression={($_.accounts.source.id | Sort-Object -Unique).count}},@{label="accountCount";expression={$_.accounts.count}}
if (-not $outData) {Write-Host "The outData variable is empty; nothing is present to save." -BackgroundColor DarkYellow; return}
while (-not ($fileExportPath)) {$fileExportPath = Read-Host "Enter a file path to which the data should be saved. Provide a csv file name as well"}
$outData | Export-Csv $fileExportPath -NoTypeInformation
#-------------------------------------------------- End Process --------------------------------------------------#
True, but our examples don’t otherwise leverage the SDK and can be used as-is without any other dependencies like installing modules. No sense making someone go through the effort of installing the module just for the sake of pagination.