Skip to content

Assessment Auth & Permissions

This page is specific to the CAF/WAF assessment platform (Invoke-AzureScout -Assessment). It is a different, narrower permission model than inventory mode’s — see Permissions for the Invoke-AzureScout / Test-AZSCPermissions model, which is not the same function and is not what this page describes.

Source of truth: src/assess/Test-ScoutPermission.ps1, src/ingest/Import-Governance.ps1 (the default governance collector), and src/ingest/Import-AzGovViz.ps1 (the opt-in third-party collector).

Governance data is native by default — no Graph permission required for it

As of the native governance collector (AB#5041), the 26 assessments whose Ingest used to be AzGovViz (CAF: Azure Landing Zone, Management, Identity, Scout: Governance Baseline, Policy) now use Ingest = Governance by default — Import-Governance populates collect.json's governance object from Azure Resource Graph and ambient-token ARM REST calls, needing only ARM Reader at the management-group root, the same requirement every other assessment already has. The Microsoft Graph application permissions below are needed only if you explicitly opt an assessment into the legacy AzGovViz ingestor value instead of the native default — they are no longer a default requirement for any assessment.

The short version

RequirementWho needs it
ARM Reader at the tenant-root management groupEvery assessment, with no exception — including the 5 governance-data assessments, now served by the native Import-Governance collector.
Microsoft Graph app permissions (User.Read.All, Group.Read.All, Application.Read.All, PrivilegedAccess.Read.AzureResources)Only if you opt an assessment into the legacy AzGovViz ingestor instead of the native Governance default. Not required by any assessment out of the box.

Every entry in the registry needs ARM Reader only by default. No Graph permission, delegated or application, is required unless you deliberately switch an assessment's Ingest back to AzGovViz.

Check before you scan

powershell
Invoke-AzureScout -Assessment 'CAF: Azure Landing Zone','Assess: Identity' -PermissionAudit

Runs Test-ScoutPermission for the given assessment(s) and returns/prints a table before any collection happens. See what it actually checks below — it is not a full live Graph check.

Why ARM Reader must be at the management-group root, not the subscription

Test-ScoutPermission checks the role assignment at /providers/Microsoft.Management/managementGroups/<tenantId> — i.e. the tenant root management group, not any individual subscription:

powershell
Get-AzRoleAssignment -Scope "/providers/Microsoft.Management/managementGroups/$($ctx.Tenant.Id)" `
    -SignInName $ctx.Account.Id | Where-Object RoleDefinitionName -eq 'Reader'

A Reader assignment scoped only to individual subscriptions will fail this specific check (Test-ScoutPermission does not walk down to subscription-level assignments as a fallback). Assign Reader at the root management group so every subscription under it inherits read access.

Whether Reader at root MG alone is enough is unresolved — do not add Management Group Reader on spec

Reader assigned at the tenant-root management group is confirmed necessary. Whether it is also sufficient for the ManagementGroups and CustomRoleDefinitions data, or whether Management Group Reader is genuinely additional, has not been settled by a live test. If those worksheets come back empty with root-MG Reader in place, treat it as worth investigating rather than assuming the fix is a bigger role grant. See Permissions.

Three Azure RBAC roles were dropped from the ask — do not grant them for assessment mode either

Security Reader, Monitoring Reader, and Cost Management Reader (the Azure RBAC roles, not the Entra role of the same name) grant nothing an assessment collector calls that Reader does not already grant, and two of them additionally carry Microsoft.Support/* — including support-ticket creation. See Permissions for the full reasoning. It applies here too: an assessment is rule evaluation over data its collectors already gathered, so it never needs a permission the underlying collectors don't already need — and none of them need these three.

The Scout: Cost Optimization assessment has one additional, non-role prerequisite: EA "AO view charges" or MCA "Azure charges" must be enabled by a billing administrator (an Enterprise Administrator for EA, a Billing Profile Owner for MCA — not a subscription or resource owner). No Azure RBAC role, including Reader or Cost Management Reader, substitutes for this setting. With it disabled, Microsoft.CostManagement/query returns empty regardless of role assignment.

Per-assessment matrix

"Governance data" marks the 26 assessments that collect governance data — by default via the native Import-Governance collector (ARM Reader only, same as every other row). "Graph (opt-in AzGovViz)" is only Yes if you've explicitly switched that assessment's Ingest back to the legacy AzGovViz value — none of them require Graph out of the box.

AssessmentARM Reader @ MG rootGovernance dataGraph (opt-in AzGovViz)
CAF: Azure Landing ZoneRequiredYes (native)Only if opted in
EstateRequiredNoNo
ManagementRequiredYes (native)Only if opted in
MonitorRequiredNoNo
NetworkingRequiredNoNo
IdentityRequiredYes (native)Only if opted in
SecurityRequiredNoNo
ComputeRequiredNoNo
StorageRequiredNoNo
DatabasesRequiredNoNo
ContainersRequiredNoNo
WebRequiredNoNo
AnalyticsRequiredNoNo
AIRequiredNoNo
IntegrationRequiredNoNo
HybridRequiredNoNo
IoTRequiredNoNo
Scout: Governance BaselineRequiredYes (native)Only if opted in
PolicyRequiredYes (native)Only if opted in
Scout: Update ManagerRequiredNoNo
Scout: Monitoring BaselineRequiredNoNo
Scout: Cost OptimizationRequiredNoNo

The Graph permissions (only if you opt into the legacy AzGovViz ingestor)

These four application permissions are not needed by default for any assessment — the native Import-Governance collector needs only ARM Reader. They only apply if you explicitly set an assessment's Ingest back to AzGovViz. When Test-ScoutPermission sees an AzGovViz-ingesting assessment in the requested set, it lists these four application permissions:

PermissionPurpose
User.Read.AllAzGovViz's identity export
Group.Read.AllAzGovViz's identity export
Application.Read.AllAzGovViz's identity export
PrivilegedAccess.Read.AzureResourcesPIM-eligible role assignments — requires an Entra ID P2 license

Grant these as application permissions with admin consent on the service principal / app registration AzureScout authenticates as (or a user account in Directory Readers, per Test-ScoutPermission's remediation text).

PrivilegedAccess.Read.AzureResources is currently never exercised

Import-AzGovViz.ps1 always passes -NoPIMEligibility to the Azure Governance Visualizer — unconditionally, not only when the permission/license is missing:

powershell
& "$govPath/repo/pwsh/AzGovVizParallel.ps1" `
    -ManagementGroupId $ManagementGroupId `
    -OutputPath        $govPath `
    -DoPSRule `
    -NoScopeInsights `
    -NoPIMEligibility `
    -ALZPolicyAssignmentsChecker

In the current implementation, PIM-eligibility data is never collected through this ingest path, regardless of whether you grant PrivilegedAccess.Read.AzureResources or hold an Entra ID P2 license. The permission is still listed by Test-ScoutPermission (it's part of AzGovViz's own general permission set) — grant it if you want to future-proof for when -NoPIMEligibility is lifted, but do not expect PIM data in findings.json today. This is a real gap between the permission checklist and what the code does; flagged here rather than silently documented as "working."

What -PermissionAudit actually verifies

Test-ScoutPermission performs one live check and one static checklist — they are not the same kind of validation:

CheckHow it's validatedOk value
ARM Reader @ MG rootLive — actually calls Get-AzRoleAssignment against the current context$true / $false
Graph: <permission> (×4, only when an assessment is explicitly opted into the legacy AzGovViz ingestor)Not validated — always emitted with Ok = $null as an informational checklist entry$null (always)

In other words: -PermissionAudit will tell you definitively whether your ARM Reader assignment is correct, but it does not call Microsoft Graph to confirm the four app permissions are actually granted — it only reminds you they're needed and what to do about it (Fix column). Verify Graph application permissions independently (Entra admin center → App registrations → API permissions, or Get-MgServicePrincipalAppRoleAssignment) before relying on a clean -PermissionAudit run as proof they're in place.

-ManagementGroupId and governance data collection

By default, the 5 governance-data assessments (CAF: Azure Landing Zone, Management, Identity, Scout: Governance Baseline, Policy) use the native Import-Governance collector, which does not need an explicit -ManagementGroupId to run — it collects via Azure Resource Graph and ambient-token ARM REST calls regardless. What actually depends on management-group visibility is the ALZ benchmark diff: if the identity running the scan doesn't have Reader at the management-group root, the benchmark degrades to an explicit Unknown (with remediation guidance pointing at "grant Reader at MG root") rather than a false 0%. This is not a permission failure and will not show up in -PermissionAudit.

powershell
Invoke-AzureScout -Assessment 'CAF: Azure Landing Zone' -ManagementGroup 'contoso-root-mg' -OutputFormat React

-ManagementGroupId scopes the Resource Graph Collect layer — Invoke-Collect passes it through to every Search-AzGraph call as -ManagementGroup. Omitting it leaves ARG queries running tenant-wide against whatever your authenticated context can see (no -ManagementGroup/-Subscription filter is sent at all). The ARM Reader requirement in The short version still applies regardless of whether you pass -ManagementGroupId — it only narrows which subscriptions under your Reader scope get queried, it does not substitute for the role assignment.

If you've opted an assessment into the legacy AzGovViz ingestor instead of the native default, Import-AzGovViz.ps1 still needs an explicit -ManagementGroupId to know where to scope the Azure Governance Visualizer run — omitting it there logs Import-AzGovViz: no -ManagementGroupId supplied; skipping AzGovViz ingest and that ingestor's data is skipped, same behavior as before this default changed.

Verification status

The permission claims on this page are documentation analysis, not a tested result — no run has been performed against a Reader-only principal to confirm every assessment still scores correctly. Treat this page as probable, not proven, until a live comparison run exists.

Next steps

Released under the MIT License.