Azure Configurations

Microsoft Azure Integration – Step-by-Step Requirements

To integrate this project with Microsoft Azure, specific permissions must be granted to the application. This guide outlines how to grant these permissions using the Azure Portal, as well as an optional PowerShell script alternative.

Step 1: Register the Application in Azure AD (if not already registered)

App registrations
New Registration
Register
After App Registration
New Client Secret
Add a client secret
Client secret value
Azure configuration page

Step 2: Assign Required API Permissions

API Permissions
Microsoft Graph
Application permissions
Add Permissions
Grant admin consent
Grant admin consent confirmation

These permissions allow the integration to securely access directory, audit, policy, role, and hybrid sync data.

(Optional Step 1): Use PowerShell Script to Automate Permission Assignment

If you prefer to automate the process or deploy across multiple tenants, you can use the following PowerShell script (requires admin privileges and AzureAD or Microsoft Graph modules).

PowerShell Script: Assign Microsoft Graph Permissions to an App

Preconditions:

  • You must be a Global Administrator

  • The application must be registered and you must have its App ID (Client ID)

Steps:

Cloud Shell
PowerShell

# Basic settings
$appName = "forestall-collector"

$graphApiId = "00000003-0000-0000-c000-000000000000"
$permissions = @{
    "Directory.Read.All"                      = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
    "AuditLog.Read.All"                       = "b0afded3-3588-46d8-8b3d-9842eff778da"
    "Policy.Read.All"                         = "246dd0d5-5bd0-4def-940b-0421030a5b68"
    "RoleManagement.Read.All"                 = "c7fbd983-d9aa-4fa7-84b8-17382c103bc4"
    "OnPremDirectorySynchronization.Read.All" = "bb70e231-92dc-4729-aff5-697b3f04be95"
}

if (!(Get-Command az -ErrorAction SilentlyContinue)) {
    Write-Error "Azure CLI is not installed. Install it from https://aka.ms/installazurecli and rerun the script."
    exit 1
}

$tenantId = az account show --query tenantId -o tsv --only-show-errors
if (-not $?) {
    Write-Error "Not logged in to Azure CLI. Run 'az login' and rerun the script."
    exit 1
}

$existingAppId = az ad app list --display-name $appName --query "[0].appId" -o tsv --only-show-errors
if ($existingAppId) {
    Write-Host "App registration '$appName' already exists. Reusing existing app."
    $appId = $existingAppId
} else {
    Write-Host "Creating app registration '$appName'..."
    $appId = az ad app create --display-name $appName --query appId -o tsv --only-show-errors
    if (-not $?) { Write-Error "App registration failed."; exit 1 }
}

foreach ($permName in $permissions.Keys) {
    $permId = $permissions[$permName]
    Write-Host "Adding permission $permName"
    az ad app permission add --id $appId --api $graphApiId --api-permissions "$permId=Role" --only-show-errors | Out-Null
    if (-not $?) { Write-Error "Failed to add $permName"; exit 1 }
}

$existingSpId = az ad sp list --filter "appId eq '$appId'" --query "[0].id" -o tsv --only-show-errors
if ($existingSpId) {
    Write-Host "Service principal already exists. Skipping creation."
} else {
    Write-Host "Creating service principal..."
    az ad sp create --id $appId --only-show-errors | Out-Null
    if (-not $?) { Write-Error "Service principal creation failed."; exit 1 }
}

Write-Host "Generating client secret..."
$clientSecret = az ad app credential reset --id $appId --append --display-name "$appName-secret" --query password -o tsv --only-show-errors
if (-not $?) { Write-Error "Client secret creation failed."; exit 1 }

Write-Host "Granting admin consent (requires Global Admin)..."
$adminConsentNote = "Admin consent still pending. Grant it manually."

az ad app permission admin-consent --id $appId --only-show-errors | Out-Null
if ($?) {
    $adminConsentNote = "Admin consent granted."
} else {
    Write-Warning "Admin consent failed. Use a Global Admin account or grant consent manually in the Azure Portal."
    $retry = Read-Host "Login with a Global Admin now and retry? (Y/N)"
    if ($retry -match '^[Yy]') {
        az login --use-device-code
        if ($?) {
            az ad app permission admin-consent --id $appId --only-show-errors | Out-Null
            if ($?) {
                $adminConsentNote = "Admin consent granted."
            } else {
                Write-Warning "Admin consent retry failed. Grant consent manually in the Azure Portal."
            }
        } else {
            Write-Warning "Login cancelled or failed. Admin consent remains pending."
        }
    }
}

$summary = @"
App Name   : $appName
Tenant ID  : $tenantId
App ID     : $appId
Secret     : $clientSecret
Consent    : $adminConsentNote

Save the client secret now; it cannot be retrieved again.
"@

Write-Host $summary
Upload PowerShell Script

Notes:

  • You can find your App ID in App registrations > [Your App] > Overview.

  • After assigning permissions via script you need to copy Secret Value.

Client Secret needs to copy
  • If using script without global admin account, admin consent still needs to be granted manually in the portal (go to optional step 2).

  1. Go back to App registrations > [Your App] > API permissions.

  2. Click Grant admin consent to activate the permissions.

Required Microsoft Azure Permissions for Integration

To ensure secure and comprehensive functionality between your systems and Microsoft Azure (Azure Active Directory), the following permissions are required:

1. Directory.Read.All

What it does: Grants read-only access to all directory objects in Microsoft Azure, including users, groups, devices, and administrative units.

Why it's needed: This permission allows the integration to retrieve essential identity data, enabling user mapping, group membership evaluation, and device information access for reporting or policy decisions.


2. AuditLog.Read.All

What it does: Provides read access to the directory’s audit logs, which record configuration changes and administrative actions across the tenant.

Why it's needed: Required to track configuration changes and user activity for auditing, compliance, and forensic analysis within the integration.


3. Policy.Read.All

What it does: Allows the application to read conditional access policies, authentication policies, and other security-related configurations.

Why it's needed: Essential for understanding and visualizing how security policies are configured across the tenant, helping administrators identify risks or configuration issues.


4. RoleManagement.Read.All

What it does: Grants read-only access to directory roles, role assignments, and role eligibility settings.

Why it's needed: Enables the integration to provide visibility into privileged roles, who holds them, and how administrative permissions are structured—critical for role governance and least-privilege assessments.


5. OnPremDirectorySynchronization.Read.All

What it does: Allows reading of the on-premises directory synchronization configuration and related metadata.

Why it's needed: Required to understand hybrid identity configurations, sync status, and directory health—ensuring that on-prem AD and Azure are working in harmony and fully visible to administrators.

Last updated

Was this helpful?