List everyone who has an Application Role for applications in Azure
Some time ago I had to validate who or what has access to the applications we created in our Azure environment.
There were hundreds of different applications with each their own specific Application Roles. Both users and service principals had roles assigned to the applications to perform the required operations.
It is possible to click through every application in Entra ID and validate the assigned roles. However, this takes quite a bit of time.
So I figured “Is it possible to iterate through all my applications in Entra ID and see who or what has an application role assigned?”
Needless to say, the answer is “Yes!”.
By using the Azure CLI and the Graph API I was able to accomplish what is required.
#########################################################
# Login if running local and you haven't done so already
#########################################################
Function Login {
# Subscription used for logging in. Necessary to get a context to work in.
$loggedInSubscription = "The subscription name"
$tenantId = "73fefcf4-c062-45ef-9607-e19aba33f82d"
az login --tenant $tenantId
# # Log in to a subscription which resides in the tentant we want to add & configure MG's to.
az account set --subscription $loggedInSubscription
}
Function Get-AppRoleAssignments {
[CmdletBinding()]Param()
Write-Verbose -Message "Starting to retrieve all Enterprise Applications matching the naming convention."
$roleAssignmentsForAllApplications = $null
$enterpriseAppRegistrationCollection =
az ad sp list --filter "startswith(displayname, 'jv-sample-app1') or startswith(displayname, 'jv-sample-app2')"
| ConvertFrom-Json
Write-Verbose -Message "Found $($enterpriseAppRegistrationCollection.Length) enterprise applications."
foreach ($enterpriseAppRegistration in $enterpriseAppRegistrationCollection) {
$servicePrincipalAppRoles = $null
$assignedAppRolesForServicePrincipal = $null
# The service principal from 'az ad sp list' already has all the data we need
$servicePrincipalAppRoles = $enterpriseAppRegistration.appRoles
Write-Verbose -Message "Found $($servicePrincipalAppRoles.Length) appRoles for $($enterpriseAppRegistration.id)."
$assignedAppRolesForServicePrincipal =
az rest `
--method get `
--uri https://graph.microsoft.com/v1.0/servicePrincipals/$($enterpriseAppRegistration.id)/appRoleAssignedTo
| ConvertFrom-Json
| Select-Object -expand value
Write-Verbose -Message "Found $($assignedAppRolesForServicePrincipal.Length) assigned identities for $($enterpriseAppRegistration.id)."
$roleAssignmentsForAllApplications += foreach($assignedAppRole in $assignedAppRolesForServicePrincipal) {
$role = $servicePrincipalAppRoles | Where-Object{ $_.id -eq $assignedAppRole.appRoleId}
Write-Verbose -Message "Adding $($role.displayName) to collection for $($assignedAppRole.principalDisplayName) on application $($enterpriseAppRegistration.displayName)."
New-Object PsObject -Property @{
AppRoleId = $assignedAppRole.appRoleId
AppRoleDisplayName = $role.displayName
PrincipalObjectId = $assignedAppRole.principalId
PrincipalDisplayName = $assignedAppRole.principalDisplayName
ApplicationDisplayName = $enterpriseAppRegistration.displayName
ApplicationApplicationId = $enterpriseAppRegistration.appId
ApplicationObjectId = $enterpriseAppRegistration.id
}
}
}
return $roleAssignmentsForAllApplications
}
#Login
Get-AppRoleAssignments -Verbose | Sort-Object -Property ApplicationDisplayName | Format-Table -Property ApplicationDisplayName, ApplicationApplicationId, ApplicationObjectId, PrincipalObjectId, PrincipalDisplayName, AppRoleId, AppRoleDisplayName | Out-File "AppRoleAssignments.md"
The output looks pretty much like this
ApplicationDisplayName ApplicationApplicationId ApplicationObjectId PrincipalObjectId PrincipalDisplayName AppRoleId
---------------------- ------------------------ ------------------- ----------------- -------------------- ---------
jv-sample-app1 768e6a21-dc24-4824-80c1-b288802b912b 34990cc8-7834-4b1c-a921-39b1e18f396f 1bb1840c-97db-4e87-bdee-00b20bce29bf Jan de Vries1 17604bce-7031-4b3c-…
jv-sample-app2 f18edfa7-1ab5-4f64-9c46-7413c214a8db b53f783d-81e0-43c9-b874-8576855301ae b9bc3ac9-9a35-45e4-961a-2929158bb73e Jan de Vries2 17604bce-7031-4b3c-…
Nice, right?
I know this is just a small script to share, which could have been a Gist, but having a post makes it more discoverable for me.
