Invoke-RiskyRolesAudit
Every privileged Azure RBAC and Entra ID role assignment in your tenant, scored, in one HTML report.
Required permissionsAzure Reader on the subscriptions you audit, or at a management group above them. On Graph the delegated scopes RoleManagement.Read.Directory, Directory.Read.All, Group.Read.All and Application.Read.All, which you consent to at sign-in. Entra ID P2 for the PIM parts; without it the audit warns once and continues, and -SkipPim silences the warning.
One file, nothing to install. Sign in, read, get a report you can hand to someone.
Finds what the portal and posture tools do not put in one place: custom roles rated by the actions they really grant after NotActions, privilege inherited through nested groups with every member named, app registrations holding privileged roles with no valid credential, disabled users with permanent assignments, and PIM eligible and activated assignments next to permanent ones.
Read-only. It signs in with read scopes, reads, and writes an HTML file. It changes nothing.
The report gives you the native command for every finding. If you would rather remove them with a prompt, a JSON backup and a refusal for anything inherited through a group, held in PIM, named as break-glass or belonging to you, the repository holds a module that does exactly that:
https://github.com/simon-vedder/risky-roles-analyzer
Syntax
./Invoke-RiskyRolesAudit.ps1 [[-OutputPath] <string>] [[-TenantId] <string>] [[-SubscriptionId] <string[]>] [[-AdditionalAzureRole] <string[]>] [[-AdditionalEntraRole] <string[]>] [[-BreakGlassAccount] <string[]>] [[-MinimumSeverity] <string>] [-SkipAzure] [-SkipEntra] [-SkipPim] [-UseDeviceCode] [-NoOpen] [<CommonParameters>]
Requirements
| Prerequisites | PowerShell 7.2 or later, and the modules Az.Accounts, Az.Resources and Microsoft.Graph.Authentication. Install those once with Install-Module Az.Accounts, Az.Resources, Microsoft.Graph.Authentication -Scope CurrentUser |
| Writes | Nothing. The only Azure cmdlet with a changing verb that the script calls is Set-AzContext, which switches your local subscription context per subscription and puts it back afterwards. |
| License | MIT. https://github.com/simon-vedder/risky-roles-analyzer |
| Generated | From the RiskyRolesAnalyzer module 0.1.0-preview by tools/Build-StandaloneScript.ps1. Do not edit this file. Change the module and rebuild, or the next build overwrites you. |
Parameters
| Name | Type | Required | Pipeline | Default | Description |
|---|---|---|---|---|---|
-OutputPath | String | no | no | Where to write the report. Default: ./RiskyRolesAnalyzer-report- | |
-TenantId | String | no | no | Tenant to sign in to. Without it the sign-in picks your home tenant. | |
-SubscriptionId | String[] | no | no | Limit the Azure part to these subscriptions. Without it, every enabled subscription in the tenant. | |
-AdditionalAzureRole | String[] | no | no | Azure role names to treat as privileged on top of the built-in list. | |
-AdditionalEntraRole | String[] | no | no | Entra role names to treat as privileged on top of the built-in list. | |
-BreakGlassAccount | String[] | no | no | UPNs or object ids of emergency access accounts. They are still reported, and marked so nobody acts on them by mistake. | |
-MinimumSeverity | String | no | no | Info | Drop findings below this severity. Default Info, which keeps everything. |
-SkipAzure | SwitchParameter | no | no | Entra ID only. No Azure sign-in, no Azure RBAC. | |
-SkipEntra | SwitchParameter | no | no | Azure RBAC only. | |
-SkipPim | SwitchParameter | no | no | Do not read PIM eligibility. Use it on tenants without Entra ID P2 to silence the warning. | |
-UseDeviceCode | SwitchParameter | no | no | Device code sign-in, for hosts without a browser. | |
-NoOpen | SwitchParameter | no | no | Do not open the report when it is written. |
Examples
Example 1
./Invoke-RiskyRolesAudit.ps1
Everything, into a timestamped report in the current folder, opened when it is written.
Example 2
./Invoke-RiskyRolesAudit.ps1 -BreakGlassAccount 'breakglass@contoso.com'
The same, with the emergency access account marked as protected instead of listed as something to clean up.
Example 3
./Invoke-RiskyRolesAudit.ps1 -SkipAzure -SkipPim -OutputPath ./entra.html
Entra ID only, on a tenant without Entra ID P2, to a path you choose.
Generated from the comment-based help in the module. Same text as Get-Help Invoke-RiskyRolesAudit -Full, and as the copy on GitHub.