Skip to content

Entra ID Inventory Modules

Overview

AzureScout includes 17 Entra ID (Identity) inventory modules that extract tenant-wide identity and access management data via the Microsoft Graph API. They live alongside one ARM-based module (ManagedIds — user-assigned managed identity resources, as opposed to the Entra-side ManagedIdentities service-principal view below) in the Identity category folder — see ARM Modules: Identity for that one.

Run Entra-only extraction with:

powershell
Invoke-AzureScout -Scope EntraOnly

How Entra Extraction Works

The Start-AZSCEntraExtraction function calls Invoke-AZSCGraphRequest for each Entra module, which:

  1. Authenticates via the Graph token obtained during login
  2. Queries the relevant Microsoft Graph endpoint
  3. Handles pagination (following @odata.nextLink)
  4. Normalizes each result into a consistent resource shape:
json
{
  "id": "...",
  "name": "Display Name",
  "TYPE": "microsoft.graph/users",
  "tenantId": "00000000-...",
  "properties": { }
}

Module Catalog

Get-ScoutEntraQueryCatalog (src/collect/Get-ScoutEntraQueryCatalog.ps1) is the single source of truth for these 17 queries — Start-AZSCEntraExtraction runs exactly this list, and the -PermissionAudit impact table is built by joining the same list against the collector manifests, so the two can no longer drift the way a hand-maintained second copy could.

ModuleGraph EndpointPermissionDescription
Users/usersUser.Read.AllAll user accounts (members and guests)
Groups/groupsGroup.Read.AllSecurity groups, Microsoft 365 groups, distribution lists
Applications/applicationsApplication.Read.AllApplication registrations (app IDs, credentials, API permissions)
Service Principals/servicePrincipalsApplication.Read.AllEnterprise applications and service principals
Managed Identities/servicePrincipals (filtered to servicePrincipalType eq 'ManagedIdentity')Application.Read.AllManaged identities (system and user-assigned), as seen from the Entra service-principal object
Directory Roles/directoryRolesRoleManagement.Read.DirectoryActivated directory roles and their members
PIM Assignments/roleManagement/directory/roleAssignmentsRoleManagement.Read.DirectoryPrivileged Identity Management (PIM) role assignments
Conditional Access Policies/identity/conditionalAccess/policiesPolicy.Read.AllConditional Access policies
Named Locations/identity/conditionalAccess/namedLocationsPolicy.Read.AllTrusted locations for conditional access
Administrative Units/directory/administrativeUnitsAdministrativeUnit.Read.AllAdministrative units for delegated management
Domains/domainsDomain.Read.AllVerified and unverified domains
Subscribed SKUs/subscribedSkusOrganization.Read.AllLicense SKUs and service plan assignments
Cross-Tenant Access/policies/crossTenantAccessPolicy/partnersPolicy.Read.AllB2B cross-tenant access settings
Security Policies/policies/authorizationPolicyPolicy.Read.AllTenant authorization policy
Risky Users/identityProtection/riskyUsersIdentityRiskyUser.Read.AllUsers flagged by Identity Protection (requires Entra ID P2)
Identity Providers ⚠️/identity/identityProvidersIdentityProvider.Read.AllConfigured external/social identity providers
Security Defaults ⚠️/policies/identitySecurityDefaultsEnforcementPolicyPolicy.Read.AllTenant-wide security defaults enforcement state

⚠️ Collected, normalized, and read by nothing

Identity Providers and Security Defaults are queried and land in EntraResources like every other row here, but no collector consumes either entra/identityproviders or entra/securitydefaults type. The catalog keeps them rather than dropping them so the -PermissionAudit impact table can say so explicitly — a permission Scout asks for and does not need belongs in the report, not in a comment nobody reads. AuditLog.Read.All used to be requested with the same problem (no collector ever consumed auditLogs/*); it has been removed from the ask entirely rather than kept as a fourth unconsumed entry.

Required Microsoft Graph Permissions

"I'm a Global Administrator but the Entra modules still fail with 403 — why?"

Global Administrator is an Entra directory role, not a Microsoft Graph API scope. Entra extraction uses the Graph token issued for the same Az context account and tenant that ARM collection uses (Get-AzAccessToken). That token only carries the delegated Graph scopes issued to the authentication client — your directory role does not widen those OAuth scopes. So an endpoint whose scope has not been consented returns 403 Forbidden regardless of your role.

To read every module above, the signed-in identity needs these delegated Microsoft Graph permissions carried by the selected identity's token (or application permissions on your own service principal) — see the Permission column in the Module Catalog above for which permission unlocks which module:

PermissionUnlocks
User.Read.AllUsers
Group.Read.AllGroups
Application.Read.AllApplications, Service Principals, Managed Identities
RoleManagement.Read.DirectoryDirectory Roles, PIM Assignments
Policy.Read.AllConditional Access Policies, Named Locations, Security Policies, Cross-Tenant Access, Security Defaults ⚠️
AdministrativeUnit.Read.AllAdministrative Units
Domain.Read.AllDomains
Organization.Read.AllSubscribed SKUs
IdentityRiskyUser.Read.AllRisky Users (Identity Protection — also requires Entra ID P2)
IdentityProvider.Read.All ⚠️Identity Providers

⚠️ marks the two permissions behind the unconsumed queries — granting them satisfies the pre-flight but adds nothing to any report; see the warning above.

A broad Directory.Read.All grant also satisfies User.Read.All, Group.Read.All and Application.Read.All in practice, since it is a superset scope, but the table above is the minimum each query actually needs.

Grant/consent once (tenant admin), e.g.:

powershell
# Re-establish the Az context for the exact account and tenant being scanned:
Connect-AzAccount -Tenant '<tenant-id>'
# For scopes the delegated token cannot carry, use AzureScout's service-principal parameters
# with the required Microsoft Graph application permissions admin-consented in Entra ID.

Endpoints requiring a licensing tier you don't have (e.g. Risky Users without Entra ID P2) will still 403 — that is expected and is handled by Graceful Degradation below rather than aborting the run.

Data Normalization

All 17 Entra modules produce output in the same normalized shape:

FieldSource
idGraph object id
namedisplayName (or most relevant name field)
TYPESynthetic type string (e.g., microsoft.graph/users)
tenantIdTenant ID from the current session
propertiesFull Graph object properties

This normalization allows ARM and Entra resources to be processed by the same reporting pipeline.

Graceful Degradation

If a single Entra query fails (e.g., insufficient permissions for Conditional Access policies), the module:

  • Logs a warning
  • Continues with the remaining 16 queries
  • Returns partial results rather than failing entirely

If all queries fail, the function returns an empty EntraResources collection.

Released under the MIT License.