Home

Awesome

Azure Governance Visualizer aka AzGovViz

OpenSSF Scorecard

Do you want to get granular insights on your technical Azure Governance implementation and document it in CSV, HTML, Markdown, and JSON?

Azure Governance Visualizer is a PowerShell based script that iterates through your Azure Tenant's Management Group hierarchy, starting from the root Management Group down to the Subscription, Resource Group and Resource level. It collects data from various Azure APIs including Azure ARM, Microsoft Graph and Storage.

From the collected data it generates enriched insights for capabilities such as Azure Policy, RBAC, and a lot more.

Within an HTML output it provides visibility on your HierarchyMap, creates a TenantSummary, creates DefinitionInsights and builds granular ScopeInsights on Azure Management Groups and Subscriptions.

Further, CSV exports with enriched information per capability will be generated and detailed JSON files are exported which document your entire Azure tenant setup for Management Groups, Subscriptions, Azure RBAC definitions and assignments, Azure policy definitions and assignments. These exports come in handy for change tracking scenarios as well as redeployment of configuration (e.g. tenant migration scenario) and can even serve as a backup.

The technical requirements as well as the required permissions are minimal.

You can run the script either for your tenant root management group or any other management group.

Mission

"Governance can be a complex thing.."

Challenges:

Azure Governance Visualizer is intended to help you to get a holistic overview on your technical Azure Governance implementation by connecting the dots.

ConnectingDot

Table of contents

Azure Governance Visualizer @ Microsoft CAF

Microsoft Cloud Adoption Framework (CAF)

:rocket: Azure Governance Visualizer deployment guide

The instructions to deploy the Azure Governance Visualizer is found in the Azure Governance Visualizer (AzGovViz) deployment guide. Follow those instructions to run AzGovViz from your terminal (console), GitHub Codepaces, Azure DevOps, or GitHub.

As an alternative, you can use the Azure Governance Visualizer accelerator to deploy the Azure Governance Visualizer per code.

Azure Governance Visualizer accelerator

The Azure Governance Visualizer accelerator provides an easy and fast deployment process that automates the creation and publishing of AzGovViz to an Azure Web Application and provides automation to configuring the pre-requisites for AzGovViz.

Release history

Changes (2024-November-01 / 6.6.1 Patch)

Changes (2024-October-26 / 6.6.0 Minor)

Changes (2024-October-9 / 6.5.5 Patch)

Full release history

Demo

Demo

Demo (v6_major_20220927_1)

More demo output

Media

Presentations

Short presentation on Azure Governance Visualizer: download

Features

Screenshots

HTML file

HierarchyMap

HierarchyMap

TenantSummary

TenantSummary

DefinitionInsights

DefinitionInsights

ScopeInsights

ScopeInsights

*IDs from screenshot are randomized

markdown in Azure DevOps Wiki as Code

alt text *IDs from screenshot are randomized

Note: there is some fixing ongoing at the mermaid project to optimize the graphical experience: https://github.com/mermaid-js/mermaid/issues/1177

Outputs

Trust

How can we trust a 20k lines PowerShell script? Besides assuring that Azure Governance Visualizer will not harm at any intent, you may want to secure yourself. Let's use Azure built-in capabilities such as VM Insights to monitor the Azure Governance Visualizer activity.

Setup a Virtual Machine in Azure, deploy the dependency agent extension and execute Azure Governance Visualizer.

In the Azure Portal navigate to the Virtual Machine, Click on Insights in the Monitoring section and click on Map. All connections that have been established will be shown. Now let's focus on the process pwsh and review the established connections.

Insights on pwsh

Query for Log Analytics:

VMConnection
| where AgentId =~ '<GUID>'
| where ProcessName =~ 'pwsh'
| summarize by DestinationIp, DestinationPort, RemoteIp, Protocol, Direction, RemoteDnsQuestions, BytesSent, BytesReceived

Technical documentation

Permissions overview

example output

Required permissions in Azure

These permissions are mandatory in each and every scenario!

ScenarioPermissions
ALL'Reader' role assignment on management group

Required permissions in Microsoft Entra ID

<table> <tbody> <tr> <th>Scenario</th> <th>Permissions</th> </tr> <tr> <td><b>A</b><br>Console | Member user account</td> <td>No Microsoft Entra ID permissions required </td> </tr> <tr> <td><b>B</b><br>Console | Guest user account</td> <td>If the tenant is hardened (Microsoft Entra ID External Identities / Guest user access = most restrictive) then Guest User must be assigned the Microsoft Entra role 'Directory readers'<br> &#x1F4A1; <a href="https://learn.microsoft.comentra/fundamentals/users-default-permissions#compare-member-and-guest-default-permissions" target="_blank">Compare member and guest default permissions</a><br> &#x1F4A1; <a href="https://learn.microsoft.com/entra/identity/users/users-restrict-guest-permissions" target="_blank">Restrict guest access permissions in Microsoft Entra ID</a> </td> </tr> <tr> <td><b>C</b><br>Console | Service principal | Managed identity</td> <td> <table> <tbody> <tr> <th>Capability</th> <th>Microsoft Graph API permissions</th> </tr> <tr> <td>Get Microsoft Entra ID<br>Users</td> <td>Service principal's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / User / User.Read.All<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/user-get#permissions" target="_blank">Get user</a></td> </tr> <tr> <td>Get Microsoft Entra ID<br>Groups</td> <td>Service principal's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / Group / Group.Read.All<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/group-get#permissions" target="_blank">Get group</a></td> </tr> <tr> <td>Get Microsoft Entra ID<br>SP/App</td> <td>Service principal's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / Application / Application.Read.All<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/serviceprincipal-get#permissions" target="_blank">Get servicePrincipal</a>, <a href="https://learn.microsoft.com/graph/api/application-get#permissions" target="_blank">Get application</a></td> </tr> <tr> <td>Get PIM eligibility<br>SP/App</td> <td>Service principal's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / PrivilegedAccess / PrivilegedAccess.Read.AzureResources<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/resources/privilegedaccess" target="_blank">Get privilegedAccess for Azure resources</a><br>If you cannot grant this permission then use parameter <i>-NoPIMEligibility</i></td> </tr> </tbody> </table> Optional: Microsoft Entra ID role 'Directory readers' could be used instead of API permissions (more 'read' than required) </td> </tr> <tr> <td><b>D</b><br>Azure DevOps / Github Actions | Service principal</td> <td> <table> <tbody> <tr> <th>Capability</th> <th>API Permissions</th> </tr> <tr> <td>Get Microsoft Entra ID<br>Users</td> <td>Azure DevOps service connection's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / User / User.Read.All<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/user-get#permissions" target="_blank">Get user</a></td> </tr> <tr> <td>Get Microsoft Entra ID<br>Groups</td> <td>Azure DevOps service connection's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / Group / Group.Read.All<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/group-get#permissions" target="_blank">Get group</a></td> </tr> <tr> <td>Get Microsoft Entra ID<br>SP/App</td> <td>Azure DevOps service connection's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / Application / Application.Read.All<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/serviceprincipal-get#permissions" target="_blank">Get service principal</a>, <a href="https://learn.microsoft.com/graph/api/application-get#permissions" target="_blank">Get application</a></td> </tr> <tr> <td>Get PIM eligibility<br>SP/App</td> <td>Service principal's <b>App registration</b><br>grant with <b>Microsoft Graph</b> permissions:<br>Application permissions / PrivilegedAccess / PrivilegedAccess.Read.AzureResources<br>&#x1F4A1; <a href="https://learn.microsoft.com/graph/api/resources/privilegedaccess" target="_blank">Get privilegedAccess for Azure resources</a><br>If you cannot grant this permission then use parameter <i>-NoPIMEligibility</i></td> </tr> </tbody> </table> Optional: Microsoft Entra ID role 'Directory readers' could be used instead of API permissions (more 'read' than required) </td> </tr> </tbody> </table>

Screenshot of Microsoft Graph permissions in the Microsoft Entra admin center

Screenshot of Microsoft Graph permissions in the Microsoft Entra admin center

PowerShell

Parameters

API reference

Azure Governance Visualizer polls the following APIs

EndpointAPI versionAPI name
MS Graphbeta/groups/entraGroupId/transitiveMembers
MS Graphbeta/privilegedAccess/azureResources/resources
MS Graphbeta/privilegedAccess/azureResources/roleAssignments
MS Graphv1.0/applications
MS Graphv1.0/directoryObjects/getByIds
MS Graphv1.0/users
MS Graphv1.0/groups
MS Graphv1.0/servicePrincipals
ARM2021-05-01-preview/resourceId/providers/Microsoft.Insights/diagnosticSettingsCategories
ARM2018-11-01-preview/scopeId/providers/Microsoft.Blueprint/blueprints/blueprintName
ARM2021-04-01/providers
ARM2021-06-01/providers/Microsoft.Authorization/policyDefinitions
ARM2021-06-01/providers/Microsoft.Authorization/policySetDefinitions
ARM2020-02-01/providers/Microsoft.Management/getEntities
ARM2021-06-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/policyAssignments
ARM2021-06-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/policyDefinitions
ARM2020-07-01-preview/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/policyExemptions
ARM2021-06-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/policySetDefinitions
ARM2015-07-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/roleAssignments
ARM2020-10-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/roleAssignmentScheduleInstances
ARM2018-07-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Authorization/roleDefinitions
ARM2018-11-01-preview/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.Blueprint/blueprints
ARM2024-01-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.CostManagement/query
ARM2020-01-01-preview/providers/Microsoft.Management/managementGroups/managementGroupId/providers/microsoft.insights/diagnosticSettings
ARM2019-10-01/providers/Microsoft.Management/managementGroups/managementGroupId/providers/Microsoft.PolicyInsights/policyStates/latest/summarize
ARM2020-05-01/providers/Microsoft.Management/managementGroups/managementGroupId
ARM2020-02-01/providers/Microsoft.Management/managementGroups/tenantId/settings
ARM2020-05-01/providers/Microsoft.Management/managementGroups
ARM2022-10-01/providers/Microsoft.ResourceGraph/resources
ARM2021-05-01/resourceId/providers/Microsoft.Insights/metrics
ARM2020-01-01/subscriptions/subscriptionId/locations
ARM2020-07-01-preview/subscriptions/subscriptionId/providers/Microsoft.Advisor/advisorScore
ARM2016-09-01/subscriptions/subscriptionId/providers/Microsoft.Authorization/locks
ARM2021-06-01/subscriptions/subscriptionId/providers/Microsoft.Authorization/policyAssignments
ARM2021-06-01/subscriptions/subscriptionId/providers/Microsoft.Authorization/policyDefinitions
ARM2020-07-01-preview/subscriptions/subscriptionId/providers/Microsoft.Authorization/policyExemptions
ARM2021-06-01/subscriptions/subscriptionId/providers/Microsoft.Authorization/policySetDefinitions
ARM2015-07-01/subscriptions/subscriptionId/providers/Microsoft.Authorization/roleAssignments
ARM2020-10-01/subscriptions/subscriptionId/providers/Microsoft.Authorization/roleAssignmentScheduleInstances
ARM2019-08-01-preview/subscriptions/subscriptionId/providers/Microsoft.Authorization/roleAssignmentsUsageMetrics
ARM2023-07-01-preview/subscriptions/subscriptionId/providers/Microsoft.Authorization/roleDefinitions
ARM2023-07-01-preview/providers/Microsoft.Authorization/roleDefinitions
ARM2022-05-01-preview/subscriptions/subscriptionId/providers/Microsoft.Blueprint/blueprintAssignments
ARM2018-11-01-preview/subscriptions/subscriptionId/providers/Microsoft.Blueprint/blueprints
ARM2024-01-01/subscriptions/subscriptionId/providers/Microsoft.CostManagement/query
ARM2021-05-01-preview/subscriptions/subscriptionId/providers/Microsoft.Insights/diagnosticSettings
ARM2019-10-01/subscriptions/subscriptionId/providers/Microsoft.PolicyInsights/policyStates/latest/summarize
ARM2022-07-01/subscriptions/subscriptionId/providers/Microsoft.Network/locations/location/availablePrivateEndpointTypes
ARM2022-05-01/subscriptions/subscriptionId/providers/Microsoft.Network/privateEndpoints
ARM2022-05-01/subscriptions/subscriptionId/providers/Microsoft.Network/virtualNetworks
ARM2020-06-01/subscriptions/subscriptionId/providers/Microsoft.Resources/tags/default
ARM2024-01-01/subscriptions/subscriptionId/providers/Microsoft.Security/pricings
ARM2020-01-01/subscriptions/subscriptionId/providers/Microsoft.Security/securescores
ARM2020-01-01-preview/subscriptions/subscriptionId/providers/Microsoft.Security/securityContacts
ARM2022-05-01/subscriptions/subscriptionId/providers/Microsoft.Security/settings
ARM2019-10-01/subscriptions/subscriptionId/providers
ARM2021-04-01/subscriptions/subscriptionId/resourcegroups
ARM2024-03-01/subscriptions/subscriptionId/resources
ARM2020-01-01/subscriptions
ARM2020-01-01/tenants

Integrate with AzOps

Did you know you can run AzOps from Azure DevOps? Check AzOps accelerator. You can integrate Azure Governance Visualizer (same project as AzOps).

pipelines:
  - pipeline: "Push"
    source: "AzOps - Push"
    trigger:
      branches:
        include:
          - master

Integrate PSRule for Azure

Pausing 'PSRule for Azure' integration. Azure Governance Visualizer used the Invoke-PSRule cmdlet, but there are certain resource types where also child resources need to be queried to achieve full rule evaluation.

Let's use PSRule for Azure and use over 260 pre-built rules to validate Azure resources based on the Microsoft Well-Architected Framework (WAF) principles. PSRule for Azure is listed as security monitoring tool in the Microsoft Well-Architected Framework.

Parameter: -DoPSRule (e.g. .\pwsh\AzGovVizParallel.ps1 -DoPSRule) Optional parameters:

Outputs:

TenantSummary HTML output example:

PSRule for Azure / Azure Governance Visualizer TenantSummary

Stats

In order to better understand the Azure Governance Visualizer usage and to optimize the product accordingly some stats will be ingested to Azure Application Insights. Results of stats analysis may be shared at a later stage.

How / What?

If the script is run in Azure DevOps then the repository ID and executing principal's object ID will be used to create an unique identifier. If the script is not run in Azure DevOps then the tenant ID and executing principal's object ID will be used to create an unique identifier.

SHA384/512 hashed combination of:

Combine identifier0 and identifier1

To conclude the approach: taking 6 or 4 characters from tenant ID / respository ID and object ID of the executing principal to create a unique identifier, which may not be backward resolveable.

identifier

The following data will be ingested to Azure Application Insights:

"accType": "ServicePrincipal / User (member) / User (Guest)",
"azCloud": "Azure environment e.g. AzureCloud, ChinaCloud, etc.",
"identifier": "8c62a7..53d08c0 (string of 128 characters)",
"platform": "Console / AzureDevOps",
"productVersion": "used Azure Governance Visualizer version",
"psAzAccountsVersion": "used Az.Accounts PS module version",
"psVersion": "used PowerShell version",
"scopeUsage": "childManagementGroup / rootManagementGroup",
"statsCountErrors": "count of encountered errors",
"statsCountSubscriptions": "less than 100 / more than 100 (no exact numbers)",
"statsParametersDoNotIncludeResourceGroupsAndResourcesOnRBAC": "true / false",
"statsParametersDoNotIncludeResourceGroupsOnPolicy": "true / false",
"statsParametersDoNotShowRoleAssignmentsUserData": "true / false",
"statsParametersHierarchyMapOnly": "true / false",
"statsParametersLargeTenant": "true / false",
"statsParametersNoASCSecureScore" "true / false",
"statsParametersNoAzureConsumption": "true / false",
"statsParametersNoJsonExport": "true / false",
"statsParametersNoPolicyComplianceStates": "true / false",
"statsParametersNoResourceProvidersDetailed": "true / false",
"statsParametersNoResources": "true / false",
"statsParametersPolicyAtScopeOnly": "true / false",
"statsParametersRBACAtScopeOnly": "true / false",
"statsTry": "count of try sending to Application Insights"

Azure Application Insights data:

Stats

If you do not want to contribute to stats for Azure Governance Visualizer then you can use the parameter: -StatsOptOut

If you have any concerns or see a risk sending stats please file an issue.

Thank you for your support!

Security

Take care: Azure Governance Visualizer creates very detailed information about your Azure Governance setup. In your organization's best interest the outputs should be protected from not authorized access!

Be aware: Any member user of the tenant can execute/run the script against the management group (and below) if the member user has the Azure RBAC role 'Reader' assigned at management froup (this of course also applies for the root management group). More important: also guest users can execute/run the script if your tenant is not hardened (and has the RBAC role 'Reader' assigned at management group) Microsoft Entra Id | External Identities | External collaboration settings | Guest user access ref

🛡️ Collaborate with the security team: Azure Defender for Cloud may alert Azure Governance Visualizer resource queries as suspicious activity:

Microsoft defender for Cloud security alert

Known issues

Working with Git and Windows cloning from your AzDO repository you may experience the following error:

fatal: cannot create directory at 'output/JSON_...': Filename too long

To work around that issue you may want to enable longpaths support. Note the caveats!

git config --system core.longpaths true

Facts

Disabled Azure subscriptions and subscriptions where Quota ID starts with with "AAD_" are being skipped, all others are queried. More information on Subscription Quota ID / Offer numbers: Supported Microsoft Azure offers.

ARM Limits are not acquired programmatically, these are hardcoded. The links used to check related limits are commented in the param section of the script.

Contribution

You are welcome to contribute to the project. Contribution Guide

Thanks to so many supporters - testing, giving feedback, making suggestions, presenting use-case, posting/blogging articles, refactoring code - THANK YOU!

Thanks Stefan Stranger (Microsoft) for providing me with his Azure Governance Visualizer outputs executed on his implementation of EnterpriseScale. Make sure you read Stefan's blog article: Enterprise-Scale - Policy Driven Governance

Thanks Frank Oltmanns-Mack (Microsoft) for providing me with his Azure Governance Visualizer outputs executed on his implementation of EnterpriseScale.

Carlos Mendible (Microsoft) gracias por tu contribución on the project - run Azure Governance Visualizer with GitHub Codespaces.

Special thanks to Tim Wanierke, Brooks Vaughn and Friedrich Weinmann (Microsoft).

And another big thanks to Wayne Meyer (Microsoft) for constant support and building bridges.

Kudos to the TableFilter Project Team!

Kudos to LorDOniX for JSON-viewer!

Kudos to Bernie White and PSRule for Azure team!

Kudos to @dolevshor for Azure Orphan Resources - GitHub ARG queries and workbooks!

Kudos to @ElanShudnow for AzSubnetAvailability - GitHub

AzAdvertizer

AzAdvertizer logo

Also check https://www.azadvertizer.net - AzAdvertizer helps you to keep up with the pace by providing overview and insights on new releases and changes/updates for Azure governance capabilities such as Azure Policy's policy definitions, initiatives (set definitions), aliases, and Azure RBAC's role definitions and resource provider operations.

AzADServicePrincipalInsights

Also check https://aka.ms/AzADServicePrincipalInsights - What about your Microsoft Entra ID service principals? Get deep insights and track your service principals with AzADServicePrincipalInsights. Create an HTML overview, export to CSV and JSON and use it for further processing.

example output

Closing Note

Please note that while being developed by a Microsoft employee, Azure Governance Visualizer is not a Microsoft service or product. Azure Governance Visualizer is a personal/community driven project, there are no implicit or explicit obligations related to this project, it is provided 'as is' with no warranties and confer no rights.