Simon Vedder

Cloud Engineer · Zürich

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

PrerequisitesPowerShell 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
WritesNothing. 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.
LicenseMIT. https://github.com/simon-vedder/risky-roles-analyzer
GeneratedFrom 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

NameTypeRequiredPipelineDefaultDescription
-OutputPathStringnonoWhere to write the report. Default: ./RiskyRolesAnalyzer-report-.html
-TenantIdStringnonoTenant to sign in to. Without it the sign-in picks your home tenant.
-SubscriptionIdString[]nonoLimit the Azure part to these subscriptions. Without it, every enabled subscription in the tenant.
-AdditionalAzureRoleString[]nonoAzure role names to treat as privileged on top of the built-in list.
-AdditionalEntraRoleString[]nonoEntra role names to treat as privileged on top of the built-in list.
-BreakGlassAccountString[]nonoUPNs or object ids of emergency access accounts. They are still reported, and marked so nobody acts on them by mistake.
-MinimumSeverityStringnonoInfoDrop findings below this severity. Default Info, which keeps everything.
-SkipAzureSwitchParameternonoEntra ID only. No Azure sign-in, no Azure RBAC.
-SkipEntraSwitchParameternonoAzure RBAC only.
-SkipPimSwitchParameternonoDo not read PIM eligibility. Use it on tenants without Entra ID P2 to silence the warning.
-UseDeviceCodeSwitchParameternonoDevice code sign-in, for hosts without a browser.
-NoOpenSwitchParameternonoDo 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.