Enumerate Azure RBAC and Microsoft Entra ID permissions for Entra ID groups, service principals, and users.
- Includes PIM (Privileged Identity Management) eligible and active directory role assignments for users.
- Export results to JSON, CSV, table, or Markdown.
- Query a previously exported file to see what a given group, service principal, or user can do.
pip install git+https://github.com/ReversecLabs/azure-iam-enum.gitOr clone and install locally:
git clone <repo-url>
cd azure-iam-enum
pip install .This tool uses the Brokered Flow (often referred to as BroCI or Nested App Authentication - NAA). Its a relatively newly discovered method of obtaining access tokens by using refresh tokens from other application. Similar to the concept Family of Client IDs, where you could use the refresh token from one application to get an access token for another application. The brokered flow is similar, but slightly more restricted. There are few applications, mainly the Azure Portal (c44b4083-3bb0-49c1-b47d-974e53cbdf3c) that can be used as a broker client for other client and resource pairs. If you are able to get an access token for a brokered client, this massively expands your opportunities to get an access token for a client with the relevant pre-consented permissions.
The recommended way to authenticate to this CLI tool is to use roadtx to get a token for the Azure portal. This will return a refresh token that can be used to get an access token for the ADIbizaUX (Ibiza IAM) API (74658136-14ec-4630-ad9b-26e160ff0fc6). Aled Mehta has done some research on what the Ibiza IAM API is if you are curious. I also mention it at my talk at fwd:cloudsec 2025.
roadtx interactiveauth -c c44b4083-3bb0-49c1-b47d-974e53cbdf3c -r msgraph --pkce -u $user --origin https://portal.azure.com
Currently the source code hard codes the Broker client and target client so you cant use any other. But its an easy change if you need to modify this on an engagement. I didn't think it was worth implementing Dirkjans firstpartyscopes.json file to do this dynamically, but it wouldn't be that difficult to retroactively add in.
BROKER_CLIENT_ID = "c44b4083-3bb0-49c1-b47d-974e53cbdf3c"
TARGET_CLIENT_ID = "74658136-14ec-4630-ad9b-26e160ff0fc6"
Note
In order to see the PIM Group information it will try and refresh to the PIM Common client (50aaa389-5a33-4f1a-91d7-2c45ecd8dac8). This may be blocked by CAPs for you. Depends on the environment.
If needed you can provide tokens for ARM and Graph if for some reason you can't get a token for the Azure portal/ perform the brokered flow.
--access-token YOUR_TOKEN- ARM token (for Azure RBAC permissions)--graph-token TOKENfor Microsoft Graph (will resolve human readable names of objects).
usage: azure-iam-enum [-h] [-f TOKENFILE] [--access-token TOKEN] [--graph-token TOKEN] [-o OUTPUT] [-t {json,csv,table,markdown}] [-v] [--subscription-id SUBSCRIPTION_ID] [--exclude-inherited] [--concurrency N] [--max-req-per-sec N] {all,groups,serviceprincipals,users,what-can} ...
positional arguments:
{all,groups,serviceprincipals,users,what-can}
Subcommand to run
all Enumerate RBAC permissions for all Azure AD / Entra objects
groups Enumerate RBAC permissions for Azure AD / Entra groups
serviceprincipals Enumerate RBAC permissions for service principals (app registrations)
users Enumerate Azure RBAC and Entra permissions for users (includes PIM eligible and active)
what-can What can a group, service principal, or user do? (from a previously exported JSON file)
options:
-h, --help show this help message and exit
-f TOKENFILE, --tokenfile TOKENFILE
Path to auth file (default: .roadtools_auth when neither this nor --access-token is given)
--access-token TOKEN Azure access token for authentication
--graph-token TOKEN Microsoft Graph token for display names (optional). With --tokenfile and refresh token, Graph token can be obtained automatically.
-o OUTPUT, --output OUTPUT
Output file path (default: print to stdout)
-t {json,csv,table,markdown}, --type {json,csv,table,markdown}
Output format (default: table)
-v, --verbose Enable verbose output
--subscription-id SUBSCRIPTION_ID
Filter results to a specific subscription ID
--exclude-inherited Exclude inherited role assignments (by default, inherited roles are included)
--concurrency N Max concurrent API requests (default: 8)
--max-req-per-sec N Rate limit: max requests per second (default: 10)
Enumerate groups (RBAC assignments):
azure-iam-enum groups -o groups.json
azure-iam-enum groups -f /path/to/.roadtools_auth -o groups.json
azure-iam-enum groups --access-token $TOKEN -o groups.txt -t csvEnumerate service principals:
azure-iam-enum serviceprincipals -o sps.mdEnumerate users (Azure RBAC + Entra directory roles + PIM eligible/active):
azure-iam-enum users -o users.json
azure-iam-enum users -f .roadtools_auth -o users.csvEnumerate all entities (groups, service principals, and users) in one pass:
azure-iam-enum all -o all.jsonQuery a group, service principal, or user from an exported JSON file:
azure-iam-enum what-can "My Group Name" -f groups.json
azure-iam-enum what-can "object_id or name" -f sps.json
azure-iam-enum what-can "user@domain.com" -f users.jsonYou can provide partial names of users, groups or service principals to return multiple results. For example take the group name ado-rbac-users-dev. You can run:
azure-iam-enum what-can "ado-rbac-users" -f groups.jsonWhich will return all groups that match that pattern such as:
ado-rbac-users-devado-rbac-users-testado-rbac-users-prodado-rbac-usersblahblahblah- it will return any groups with theado-rbac-usersstring withinblahblahblahado-rbac-users