Forecasting Projected Licensing Cost Based on Current Identity Count

Problem

If have an upcoming renewal but have not yet been quoted for it but still want an idea of the ballpark cost, this script may help you do it leveraging the PowerShell SDK

Diagnosis

You have outgrown your current identity license count and know you will need to buy more, you need something to tell you how much that might cost, and how many full vs lite licenses you need to purchase

According to the current Customer Agreements Definitions and Additional Terms, identities are generally segmented into two different license classes, Identity [-IU], and Lite Identity [-LU]

Lite identities often have a reduced cost, so this script can be a good cost-saving estimator if you need.

Solution

First, a couple caveats

  1. I am not using actual licensing costs. You need to source that based on your current agreement or come up with your own per-license unit cost
  2. This script relies on your lifecycle states having an identity state tied to them, otherwise you will modify the query
  3. This script also assumes the “IdentityNow” account/source does not count towards the up to 5 allowed for a Lite user, which is why the script checks if the identity has greater than 6 accounts
    image

With that behind us, let’s get into it.

First, you need to give the script a Full Identity annual unit cost. Second, you need to provide a percentage of how much a Lite Identity license costs by comparison. In this example, I’m going to use $150 per full identity per year, and Lite identities carrying 80% of that unit cost.

.\Get-LicenseCountByIdentityProfile.ps1 -fullunitcost 150 -liteUnitPercentage 0.8

It will query all your active identities and give you an output like this. First, your unit cost assumptions. Next, your license count breakdown by identity profile and user type. Next, your breakdown by just user type, and finally, your total cost

Here is the source script to run this

param($fullUnitCost = 140,$liteUnitPercentage = 0.8)
Import-Module PSSailPoint


$liteUnitCost = $fullUnitCost * $liteUnitPercentage


Write-Host ""

$search_body = @"
{
  "indices": [
    "identities"
  ],
  "query": {
    "query": "attributes.identityState:ACTIVE AND _exists_:identityProfile"
  },
  "queryResultFilter":{
    "includes":[
        "identityProfile",
        "id",
        "accountCount"
    ]
  },
  "sort":[
    "id"
  ]
}
"@

$search = ConvertFrom-JsonToSearch $search_body

$results = Invoke-Paginate -Function "search-post" -Increment 250 -Limit 10000 -InitialOffset 0 -Parameters @{"Search"= $search}

$licenseData = @()

foreach ($result in $results) {
  $userType = if ($result.accountCount -gt 6) { "Full" } else { "Lite" }
  $unitCost = if ($userType -eq "Lite") { $liteUnitCost } else { $fullUnitCost }
  $licenseData += [PSCustomObject]@{
    IdentityProfile = $result.identityProfile.name
    UserType = $userType
    Count = $result.accountCount
    UnitCost = $unitCost
  }
}

Write-Host "License Cost Assumptions"

$licenseUnitCosts = @(
    [PSCustomObject]@{
        LicenseType = "Full"
        UnitCost = ($fullUnitCost).ToString("C")
    },
    [PSCustomObject]@{
        LicenseType = "Lite"
        UnitCost = ($liteUnitCost).ToString("C")
    }
)

Write-Output $licenseUnitCosts | Out-Host

Write-Host "Breakdown by Identity Type and License Class (UserType)"
$identityTypeBreakdown = $licenseData |
  Group-Object "IdentityProfile", "UserType" |
  Select-Object @{Name="IdentityProfile"; Expression={$_.Group[0].IdentityProfile}}, `
    @{Name="UserType"; Expression={$_.Group[0].UserType}}, @{Name="Count"; Expression={$_.Count}}, `
    @{Name="Cost"; Expression={$_.Group[0].UnitCost*$_.Count}} |
  Sort-Object "IdentityProfile", "Count" -Descending

Write-Output $identityTypeBreakdown | Select-Object IdentityProfile,UserType,Count,@{Name="Cost"; Expression={($_.Cost).ToString("C")}} | Out-Host

Write-Host "Breakdown by License Class (UserType)"
$licenseClassBreakdown = $licenseData |
  Group-Object "UserType" |
  Select-Object @{Name="UserType"; Expression={$_.Group[0].UserType}}, `
    @{Name="Count"; Expression={$_.Count}}, `
    @{Name="Cost"; Expression={$_.Group[0].UnitCost*$_.Count}} |
  Sort-Object "Count" -Descending

Write-Output  $licenseClassBreakdown | Select-Object UserType,Count,@{Name="Cost"; Expression={($_.Cost).ToString("C")}} | Out-Host

$liteTotalCost = $licenseData | Where-Object {$_.UserType -eq "Lite"} | 
    Group-Object "UserType" |
    Select-Object @{Name="Cost"; Expression={$_.Group[0].UnitCost*$_.Count}}

$fullTotalCost = $licenseData | Where-Object {$_.UserType -eq "Full"} | 
    Group-Object "UserType" |
    Select-Object @{Name="Cost"; Expression={$_.Group[0].UnitCost*$_.Count}}

$totalCost = ($fullTotalCost.Cost + $liteTotalCost.Cost).ToString("C")

Write-Output $totalCost | Select-Object @{Name="TotalCost"; Expression={$_}} | Out-Host
5 Likes