Checking left over identities in Azure

Recently, I was working on a task where I had to delete a subscription because it was no longer needed. On that subscription, however, there were still some identities having permissions asigned. I wanted to check if those identities were still used in other subscriptions. Turns out there is no easy way to do this. So, I wrote a script to get all the principals on the subscription and check their permissions in all subscriptions in the tenant.

The first step is to get all the principals left on the subscription. This can be done with the following command:

$principalIds = $(az role assignment list --query "[?principalType=='ServicePrincipal'].{principalName:principalName }"  -o tsv)

This will give you a list of all the service principals left on the subscription and it will only return the names of the principals. I wasn’t interested in Users or Groups at this point. The next step is to get all the subscriptions in the tenant. This can be done with the following command:

$sub_ids=$(az account list --query "[?tenantId=='<your-tenant-id>'].{id:id}" -o tsv)

This will give you a list of all the subscriptions in the tenant. I’m filtering on tenantId because I’m almost always logged into multiple tenants on the Azure CLI.

The next step is to loop over all the principals and all the subscriptions and check the permissions. The script creates a file for each principal with the permissions in each subscription. The output looks something like this:

Principal                             Role                         Scope
------------------------------------  ---------------------------  ---------------------------------------------------
<principal-id>                        Virtual Machine Contributor  /subscriptions/<subscription-id>
<principal-id>                        Backup Contributor           /subscriptions/<subscription-id-2>

It allows you to quickly check if the principal is still used in other subscriptions.

The script with the loop over all principals and subscriptions is shown below:

foreach ($principalId in $principalIds) {
    write-host "checking principal Id: $principalId"

    foreach ($sub_id in $sub_ids) {
        az account set --subscription $sub_id
        $assignments = $(az role assignment list --all --assignee $principalId --include-inherited --include-groups -o table)

        if ($assignments) {
            $fileName = "$directoryPath$principalId.txt"
            if (Test-Path -Path $fileName) {
                # If the file exists, append the user data to it
                Add-Content -Path $fileName -Value $assignments
            } else {
                # If the file doesn't exist, create a new file and add the user data
                Set-Content -Path $fileName -Value $assignments
            }

            Add-Content -Path $fileName -Value ""
        }
    }
}

Here’s the complete script:

# Description: This script will get all principals assigned on a particular subscription 
# and check their permissions in all subscriptions in the tenant.
# The script will create a file for each principal with the permissions in each subscription.

az account set --subscription <subscription-id-of-subscription-to-remove>

$principalIds = $(az role assignment list --query "[?principalType=='ServicePrincipal'].{principalName:principalName }"  -o tsv)

write-host "Principal Ids: $principalIds"

$sub_ids=$(az account list --query "[?tenantId=='<your-tenant-id>'].{id:id}" -o tsv)

$directoryPath = "output/"
if (-not (Test-Path -Path $directoryPath -PathType Container)) {
    New-Item -Path $directoryPath -ItemType Directory
}

foreach ($principalId in $principalIds) {
    write-host "checking principal Id: $principalId"

    foreach ($sub_id in $sub_ids) {
        az account set --subscription $sub_id
        $assignments = $(az role assignment list --all --assignee $principalId --include-inherited --include-groups -o table)

        if ($assignments) {
            $fileName = "$directoryPath$principalId.txt"
            if (Test-Path -Path $fileName) {
                # If the file exists, append the user data to it
                Add-Content -Path $fileName -Value $assignments
            } else {
                # If the file doesn't exist, create a new file and add the user data
                Set-Content -Path $fileName -Value $assignments
            }

            Add-Content -Path $fileName -Value ""
        }
    }
}