Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure Governance Visualizer (AzGovViz) Accelerator

Description

Azure Governance Visualizer is a PowerShell based script that iterates your Azure Tenant´s Management Group hierarchy down to Subscription level. It captures most relevant Azure governance capabilities such as Azure Policy, RBAC and 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 the script into your environment.

Table of Contents

Prerequisites

1. Create a Service Principal (Azure AD app registration) to run AzGovViz

Azure Portal

NOTE To grant API permissions and grant admin consent for the directory, you must have 'Privileged Role Administrator' or 'Global Administrator' role assigned Assign Azure AD roles to users

  • Navigate to 'Azure Active Directory'
  • Click on 'App registrations'
  • Click on 'New registration'
  • Name your application (e.g. AzureGovernanceVisualizer_SP)
  • Click 'Register'
  • Your App registration has been created, in the 'Overview' copy the 'Application (client) ID' as we will need it later to setup the secrets in GitHub
  • Under 'Manage' click on 'API permissions'
    • Click on 'Add a permissions'

      • Click on 'Microsoft Graph'
      • Click on 'Application permissions'
      • 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
      • Click on 'Add a permissions'
      • 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'

      Screenshot showing Azure AD application permissions

PowerShell

NOTE To grant API permissions and grant admin consent for the directory, you must have 'Privileged Role Administrator' or 'Global Administrator' role assigned Assign Azure AD roles to users

  • 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
  • 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
  • Define variables

    $MicrosoftGraphAppId = "00000003-0000-0000-c000-000000000000"
    $AzGovVizAppName = "<App registration name that will be used to run AzGovViz>"
  • Get Microsoft Graph permissions role Ids and 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."
  • Grant admin consent using the Azure AD portal

    Screenshot showing Azure AD application permissions

2. Create the GitHub repository

GitHub

NOTE The new repository's visibility needs to be set as Private.

PowerShell

  • Install GitHub CLI

  • Login to your GitHub account

    gh auth login
  • Create a private repository from the Accelerator template

    ### Define variables
    $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

Azure Portal

Navigate to 'Azure Active Directory'

  • Click on 'App registrations'
  • Search for the Application that we created earlier and click on it
  • Under 'Manage' click on 'Certificates & Secrets'
  • Click on 'Federated credentials'
  • Click 'Add credential'
  • Select Federation credential scenario 'GitHub Actions deploying Azure Resources'
  • Fill the field 'Organization' with your GitHub Organization name
  • Fill the field 'Repository' with your GitHub repository name
  • For the entity type select 'Branch'
  • Fill the field 'GitHub branch name' with your branch name
  • Fill the field 'Name' with a name (e.g. AzureGovernanceVisualizer_GitHub_Actions)
  • Click 'Add'

PowerShell

$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

Azure Portal

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')

  • Create a 'Reader' RBAC Role assignment on the target Management Group scope for the identity that shall run Azure Governance Visualizer

PowerShell

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

5. Create an Azure AD application for AAD authentication for the Azure Web App

Azure Portal

  • Create an app registration in Azure AD 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"

  • 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

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

    Screenshot showing exposing an API

    Screenshot showing exposing an API

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

    Screenshot showing adding a scope to the API

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 Azure AD 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 WebApp 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 Azure AD authentication",
                  "adminConsentDisplayName": "AzGovViz Web App Azure AD 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 the right RBAC Roles

Azure Portal

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')

PowerShell

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')

  $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

NOTE Make sure that the resource provider Microsoft.Web is registered on the subscription where the web app hosting AzGovViz will be hosted.

7. Create the GitHub secrets, variables and permissions

GitHub

Secret Value
CLIENT_ID Application Id of the identity that shall run Azure Governance Visualizer
AAD_CLIENT_ID Application Id of the identity that will be used to configure Azure AD authentication to the Azure Web App
AAD_CLIENT_SECRET Secret of the identity that will be used to configure Azure AD authentication to the Azure Web App
SUBSCRIPTION_ID Subscription Id
TENANT_ID Tenant Id
MANAGEMENT_GROUP_ID Management group Id
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

PowerShell

  • Create the needed secrets, variables and permissions

    ### Define variables
    $subscriptionId = "<Subscription Id>"
    $tenantId = "<Tenant Id>"
    $managementGroupId = $managementGroupId
    $resourceGroupName = $resourceGroupName
    $clientId = $AzGovVizAppId
    $aadClientId = $webAppSPAppId
    $aadClientSecret = $webAppSPAppSecret
    
    ### Create GitHub repository secrets and variables
    gh secret set 'CLIENT_ID' -b $clientId
    gh secret set 'AAD_CLIENT_ID' -b $aadClientId
    gh secret set 'AAD_CLIENT_SECRET' -b $aadClientSecret
    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

How to deploy

To deploy the accelerator after having the pre-requisites ready, you need to perform the following steps:

  • Navigate to Actions in your newly created repository

    Screenshot showing the GitHub actions pane

  • Run the DeployAzGovVizAccelerator workflow to initialize the accelerator, deploy the Azure Web App and configure Azure AD 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, I will add the NoPIMEligibility parameter since I don't have PIM

    Screenshot showing editing the AzGovViz parameters

  • 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

Configuration

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

Keeping 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

keeping 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.

About

AzGovViz-Accelerator with Azure DevOps Pipelines support

Resources

Code of conduct

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages