Skip to content

An accelerator to help you deploy AzGovViz in your own environments quickly.

License

Notifications You must be signed in to change notification settings

Naglafarn/Azure-Governance-Visualizer-Accelerator

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

58 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure Governance Visualizer (AzGovViz) accelerator

Azure Governance Visualizer is a PowerShell based script that iterates your Azure tenant's management group hierarchy down to the subscription level. It captures most relevant Azure governance capabilities such as Azure Policy, role-based access control (RBAC), Blueprints, and a lot more. From the collected data Azure Governance Visualizer provides visibility on your HierarchyMap, creates a TenantSummary, creates DefinitionInsights and builds granular ScopeInsights on management groups and subscriptions.

This accelerator speeds up the adoption of Azure Governance Visualizer into your environment.

Table of contents

🚀 Deployment guide

Follow these steps to deploy the Azure Governance Visualizer accelerator into your own Azure and Microsoft Entra ID tenant. Most steps have both portal based ( 🖱️ ) and PowerShell based ( ⌨️ ) instructions. Use whichever you feel is appropriate for your situation, they both produce the same results.

1. Create a service principal (Microsoft Entra ID app registration) to run Azure Governance Visualizer

NOTE: To grant API permissions and grant admin consent for the directory, you must have 'Privileged Role Administrator' or 'Global Administrator' role assigned. See Assign Microsoft Entra roles to users for instructions.

🖱️ Use the Microsoft Entra admin center to create the service principal:

  1. Navigate to the Microsoft Entra admin center
  2. Click on 'App registrations'
  3. Click on 'New registration'
  4. Name your application (e.g. AzureGovernanceVisualizer_SP)
  5. Click 'Register'
  6. Your App registration has been created. In the 'Overview' copy the 'Application (client) ID' as you will need it later to setup the secrets in GitHub.
  7. Under 'Manage' click on 'API permissions'
    1. Click on 'Add a permissions'
    2. Click on 'Microsoft Graph'
    3. Click on 'Application permissions'
    4. Select the following set of permissions and click 'Add permissions'
      • Application / Application.Read.All
      • Group / Group.Read.All
      • User / User.Read.All
      • PrivilegedAccess / PrivilegedAccess.Read.AzureResources
    5. Click on 'Add a permissions'
  8. Back in the main 'API permissions' menu you will find permissions with status 'Not granted for...'. Click on 'Grant admin consent for TenantName' and confirm by click on 'Yes'. Now you will find the permissions with status 'Granted for TenantName'

⌨️ Use PowerShell to create the service principal:

  1. Install AzAPICall and connect to Azure

    $module = Get-Module -Name "AzAPICall" -ListAvailable
    if ($module) {
      Update-Module -Name "AzAPICall" -Force
    } else {
      Install-Module -Name AzAPICall
    }
    Connect-AzAccount
  2. Initialize AzAPICall

    $parameters4AzAPICallModule = @{
      #SubscriptionId4AzContext = $null #specify Subscription Id
      #DebugAzAPICall = $true
      #WriteMethod = 'Output' #Debug, Error, Host, Information, Output, Progress, Verbose, Warning (default: host)
      #DebugWriteMethod = 'Warning' #Debug, Error, Host, Information, Output, Progress, Verbose, Warning (default: host)
      #SkipAzContextSubscriptionValidation = $true #Use if the account doesn´t have any permissions on Management Groups,  Subscriptions, Resource Groups or Resources
    }
    
    $azAPICallConf = initAzAPICall @parameters4AzAPICallModule
  3. Define variables

    $MicrosoftGraphAppId = "00000003-0000-0000-c000-000000000000"
    $AzGovVizAppName = "<App registration name that will be used to run AzGovViz>"
  4. Get Microsoft Graph permissions role IDs and the create app registration

    $apiEndPoint = $azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph
    $apiEndPointVersion = '/v1.0'
    $api = '/servicePrincipals'
    $optionalQueryParameters = "?`$filter=(displayName eq 'Microsoft Graph')&$count=true&"
    
    $uri = $apiEndPoint + $apiEndPointVersion + $api + $optionalQueryParameters
    
    $azAPICallPayload = @{
        uri= $uri
        method= 'GET'
        currentTask= "'$($azAPICallConf['azAPIEndpoints'].($apiEndPoint.split('/')[2])) API: Get - Groups'"
        consistencyLevel= 'eventual'
        noPaging= $true
        AzAPICallConfiguration = $azAPICallConf
    }
    
    $graphApp = AzAPICall @azAPICallPayload
    $appRole = $graphApp.appRoles | Where-Object { $_.value -eq 'Application.Read.All' } | Select-Object -ExpandProperty id
    $userRole = $graphApp.appRoles | Where-Object { $_.value -eq 'User.Read.All' } | Select-Object -ExpandProperty id
    $groupRole = $graphApp.appRoles | Where-Object { $_.value -eq 'Group.Read.All' } | Select-Object -ExpandProperty id
    $pimRole = $graphApp.appRoles | Where-Object { $_.value -eq 'PrivilegedAccess.Read.AzureResources' } | Select-Object  -ExpandProperty id
    
    $body = @"
    {
      "DisplayName":"$AzGovVizAppName",
      "requiredResourceAccess" : [
        {
          "resourceAppId" : "$MicrosoftGraphAppId",
          "resourceAccess": [
            {
              "id": "$appRole",
              "type": "Role"
            },
            {
              "id": "$userRole",
              "type": "Role"
            },
            {
              "id": "$groupRole",
              "type": "Role"
            },
            {
              "id": "$pimRole",
              "type": "Role"
            }
          ]
        }
      ]
    }
    "@
    
    $AzGovVizAppObjectId = (AzAPICall -method POST -body $body -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel 'eventual').id
    
    do {
      Write-Host "Waiting for the AzGovViz service principal to get created..."
      Start-Sleep -seconds 20
      $AzGovVizAppId = (AzAPICall -method GET -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications/$AzGovVizAppObjectId" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel  'eventual' -skipOnErrorCode 404).appId
    } until ($null -ne $AzGovVizAppId)
    
    Write-host "AzGovViz service principal created successfully."
  5. Grant admin consent using the Microsoft Entra admin center.

Result: A service principal is created with the necessary API permissions and admin consent granted. The following screenshot shows the API permissions and granted status.

A screenshot showing API permissions assigned to the application registration you created.

2. Create copy of the Azure Governance Visualizer accerlator in your own GitHub repository

🖱️ Use the GitHub website:

  1. Navigate to the accelerator GitHub repository.

  2. Create a new repository from the accelerator template.

    • Ensure the new repository is set to Private.

    Screenshot showing creating a new repository from a template on GitHub.com

    Screenshot showing creating a private repository

⌨️ Use PowerShell and the GitHub CLI:

  1. Install the GitHub CLI

  2. Login to your GitHub account.

    gh auth login
  3. Create a private repository from the accelerator template

    $directoryToCloneAccelerator = "<Local directory to clone the Accelerator's repository>"
    $GitHubOrg = "<GitHub organization to use>"
    $GitHubRepository = "Azure-Governance-Visualizer"
    
    ### Create a new repository from template
    gh repo create $GitHubRepository --template Azure/Azure-Governance-Visualizer-Accelerator --private
    New-Item -ItemType Directory -Path $directoryToCloneAccelerator -Force
    cd $directoryToCloneAccelerator
    gh repo clone "$GitHubOrg/$GitHubRepository"
    Set-Location $GitHubRepository

3. Configure federated credentials for the service principal created in the first step

🖱️ Use the Microsoft Entra admin center:

  1. Navigate to the Microsoft Entra admin center
  2. Click on 'App registrations'
  3. Search for the Application that you created earlier and click on it
  4. Under 'Manage' click on 'Certificates & Secrets'
  5. Click on 'Federated credentials'
  6. Click 'Add credential'
  7. Select Federation credential scenario 'GitHub Actions deploying Azure Resources'
  8. Fill the field 'Organization' with your GitHub organization name
  9. Fill the field 'Repository' with your GitHub repository name
  10. For the entity type select 'Branch'
  11. Fill the field 'GitHub branch name' with your branch name
  12. Fill the field 'Name' with a name (e.g. AzureGovernanceVisualizer_GitHub_Actions)
  13. Click 'Add'

⌨️ Use PowerShell and the GitHub CLI:

$gitHubRef= ":ref:refs/heads/main"
$subject = "repo:$gitHubOrg/$GitHubRepository$gitHubRef"
$body = @"
{
  "audiences": [
    "api://AzureADTokenExchange"
  ],
  "subject":"$subject",
  "issuer":"https://token.actions.githubusercontent.com",
  "name":"AzGovVizCreds"
}
"@


AzAPICall -method POST -body $body -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications/$AzGovVizAppObjectId/federatedIdentityCredentials" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel 'eventual'

4. Grant permissions in Azure for the AzGovViz service principal created in the first step

NOTE: To assign roles, you must have 'Microsoft.Authorization/roleAssignments/write' permissions on the target management group scope (such as the built-in RBAC role 'User Access Administrator' or 'Owner')

🖱️ From the Azure portal:

Create a 'Reader' RBAC role assignment on the target management group scope for the service principal that will run Azure Governance Visualizer.

⌨️ Use PowerShell:

$managementGroupId = "<managementGroupId>"
New-AzRoleAssignment `
-ApplicationId $AzGovVizAppId `
-RoleDefinitionName "Reader" `
-Scope /providers/Microsoft.Management/managementGroups/$managementGroupId

5. Create a Microsoft Entra application for user authentication to the Azure Web App that will host AzGovViz

🖱️ From the Microsoft Entra admin center:

  1. Create an app registration in Microsoft Entra ID for your Azure App Web App.

    In the Redirect URIs section, select Web for platform and type the URI in the following format: "https://<webapp_name>.azurewebsites.net/.auth/login/aad/callback"

  2. Click on Authentication and under Implicit grant and hybrid flows, enable ID tokens to allow OpenID Connect user sign-ins from App Service. Select Save.

    Screenshot showing enabling Open ID in app registration

  3. From the left navigation, select Expose an API > Add > Save.

    Screenshot showing exposing an API

    Screenshot showing exposing an API

  4. Click on Add a scope and provide the values as the screenshot.

    Screenshot showing adding a scope to the API

⌨️ Use PowerShell:

# 2-60 Alphanumeric, hyphens and Unicode characters. Can't start or end with hyphen. A web site must have a globally unique name.
$webAppName = "<Azure Web App name to publish AzGovViz>"
$WebApplicationAppName = "<App registration name that will be used to add Microsoft Entra ID-based authentication to the web app>"

$body = @"
{
  "DisplayName":"$WebApplicationAppName",
  "web": {
    "redirectUris": [
      "https://$webAppName.azurewebsites.net/.auth/login/aad/callback"
    ],
    "implicitGrantSettings": {
      "enableIdTokenIssuance": true
    }
  }
}
"@


$webAppSP = AzAPICall -method POST -body $body -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel 'eventual'
$webAppSPAppId = $webAppSP.appId
$webAppSPObjectId = $webAppSP.Id

do {
  Write-Host "Waiting for the Azure WebApp app registration to get created..."
  Start-Sleep -seconds 30
  $webApp = AzAPICall -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications/$webAppSPObjectId" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel 'eventual'
} until ( $null -ne $webApp)

Write-host "Azure Web App app registration created successfully."

# Add an API scope for the Web App
$body = @"
{
  "identifierUris" : [
    "api://$webAppSPAppId"
  ],
  "api": {
    "oauth2PermissionScopes": [
      {
        "value": "user_impersonation",
        "adminConsentDescription": "AzGovViz Web App Microsoft Entra ID authentication",
        "adminConsentDisplayName": "AzGovViz Web App Microsoft Entra ID authentication",
        "type": "User",
        "id": "$webAppSPAppId"
      }
    ]
  }
}
"@

AzAPICall -method PATCH -body $body -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications/$webAppSPObjectId" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel 'eventual'

# Generate client secret
$body = @"
{
  "passwordCredential":{
    "displayName": "AzGovVizWebAppSecret"
  }
}
"@

$webAppSPAppSecret = (AzAPICall -method POST -body $body -uri "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/v1.0/applications/$webAppSPObjectId/addPassword" -AzAPICallConfiguration $azAPICallConf -listenOn 'Content' -consistencyLevel 'eventual').secretText

6. Create a resource group and assign necessary RBAC roles

NOTES:

To assign roles, you must have 'Microsoft.Authorization/roleAssignments/write' permissions on the target management group scope (such as the built-in RBAC role 'User Access Administrator' or 'Owner').

Make sure that the resource provider Microsoft.Web is registered on the subscription where the Azure Web App hosting AzGovViz will be deployed.

🖱️ From the Azure portal:

  1. Create a new resource group in Azure.
  2. Assign the following roles to the AzGovViz service principal the on the newly created resource group.

⌨️ Use PowerShell:

$subscriptionId = "<Subscription Id>"
$resourceGroupName = "Name of the resource group where the Azure Web App will be created>"
$location = "<Azure Region for the Azure Web App>"

Select-AzSubscription -SubscriptionId $subscriptionId
New-AzResourceGroup -Name $resourceGroupName -Location $location
New-AzRoleAssignment -ApplicationId $AzGovVizAppId -RoleDefinitionName "Web Plan Contributor" -ResourceGroupName $resourceGroupName
New-AzRoleAssignment -ApplicationId $AzGovVizAppId -RoleDefinitionName "WebSite Contributor" -ResourceGroupName $resourceGroupName

7. Create the GitHub secrets, variables, and permissions

🖱️ From the GitHub website:

  1. Create the following GitHub secrets on the repository.

    Secret Value
    CLIENT_ID Application ID of the identity that will run Azure Governance Visualizer
    ENTRA_CLIENT_ID Application ID of the identity that will be used to configure user authentication to the Azure Web App
    ENTRA_CLIENT_SECRET Secret of the identity that will be used to configure user authentication to the Azure Web App
    SUBSCRIPTION_ID Azure subscription ID
    TENANT_ID Microsoft Entra tenant ID
    MANAGEMENT_GROUP_ID Azure management group ID
  2. Create the following GitHub variables on the repository.

    Variable Value
    RESOURCE_GROUP_NAME Name of the pre-created resource group to host the Azure Web App
    WEB_APP_NAME Globally unique name of the Azure Web App
  3. Enable GitHub actions to create and approve pull requests on the repository.

⌨️ Use PowerShell and the GitHub CLI:

$subscriptionId = "<Azure subscription ID>"
$tenantId = "<Microsoft Entra tenant ID>"
$managementGroupId = $managementGroupId
$resourceGroupName = $resourceGroupName
$clientId = $AzGovVizAppId
$webAppClientId = $webAppSPAppId
$webAppClientSecret = $webAppSPAppSecret

# Create GitHub repository secrets and variables
gh secret set 'CLIENT_ID' -b $clientId
gh secret set 'ENTRA_CLIENT_ID' -b $webAppClientId
gh secret set 'ENTRA_CLIENT_SECRET' -b $webAppClientSecret
gh secret set 'SUBSCRIPTION_ID' -b $subscriptionId
gh secret set 'TENANT_ID' -b $tenantId
gh secret set 'MANAGEMENT_GROUP_ID' -b $managementGroupId
gh variable set 'RESOURCE_GROUP_NAME' -b $resourceGroupName
gh variable set 'WEB_APP_NAME' -b $webAppName

# Configure GitHub actions permissions
gh api -X PUT /repos/$GitHubOrg/$GitHubRepository/actions/permissions/workflow -F can_approve_pull_request_reviews=true

8. Deploy Azure Governance Visualizer Azure resources and application

  1. Navigate to Actions in your newly created repository.

    Screenshot showing the GitHub actions pane

  2. Run the DeployAzGovVizAccelerator workflow to initialize the accelerator, deploy the Azure Web App and configure Microsoft Entra authentication for it.

    Screenshot showing deploying the DeployAzGovVizAccelerator workflow

    Screenshot showing the DeployAzGovVizAccelerator workflow executing

    This workflow will trigger another workflow to sync the latest AzGovViz code to your repository.

    Screenshot showing the SyncAzGovViz workflow

    You will have to add the AzGovViz parameters you need into the DeployAzGovViz workflow and enable the schedule option if you want to continuously run Azure Governance Visualizer.

    Screenshot showing the path of the deployAzGovViz workflow

    Screenshot showing editing the AzGovViz parameters

    Screenshot showing editing the AzGovViz schedule

    As an example, you can add the NoPIMEligibility parameter if you don't have PIM.

    Screenshot showing editing the AzGovViz parameters

  3. Then, run the DeployAzGovViz workflow to deploy AzGovViz and publish it to the Azure Web App

    Screenshot showing deploying AzGovViz

    Screenshot showing the AzGovViz workflow completion

    Screenshot showing the AzGovViz web app

    Screenshot showing the AzGovViz web app published

🏁 Try it out!

Once the DeployAzGovViz workflow has been ran successfully, navigate to the Azure Web App on the Azure portal and click Browse to access the visualizer. You'll notice that you'll need to be authenticated with Microsoft Entra ID.

🧹 Clean up resources

If you were deploying the Azure Governance Visualizer for exploratory purposes, you'll want to delete the created Azure resources to prevent undesired costs from accruing and remove the related Microsoft Entra ID objects. Follow these steps to delete all resources created as part of this reference implementation.

  1. Delete the create resource group.
  2. Delete the private GitHub repository.
  3. Delete the local copy of the GitHub repository created on your machine.
  4. Delete the two service principals created for the AzGovViz authorization and the Azure Web App Entra ID authentication.

Additional topics

Azure Web App configuration

You can configure some aspects of the Azure Web application where AzGovViz is published by editing the webApp.parameters.json file in the bicep folder.

Screenshot showing the Azure Web app parameters file

Keep the Azure Governance Visualizer code up-to-date

To keep the Azure Governance Visualizer's code up-to-date, the workflow SyncAzGovViz runs on a schedule to check for new versions. The default setting is that this is enabled to push updates automatically to your repository. If you need to control those new version updates, you will have to set AutoUpdateAzGovViz to false so you would get a pull request every time there is a new version to review.

Screenshot showing syncAzGovViz workflow code with autoupdate set to true

Keep the Azure Governance Visualizer Accelerator code up-to-date

To keep the Azure Governance Visualizer Accelerator code up-to-date, the workflow SyncAccelerator runs on a schedule to check for new versions. Everytime there is a new update to the accelerator's code, you would get a pull request submitted to your repository and the new release will be merged to a releases folder where you can move to newer versions of this accelerator at your own pace.

Sources to documentation

For more information on Azure Governance Visualizer, please visit the official docs and the Azure landing zone documentation.

About

An accelerator to help you deploy AzGovViz in your own environments quickly.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Bicep 100.0%