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

* [ ] Sign in to the Azure Portal.
* [ ] Navigate to **Microsoft Azure** > **App registrations**.

<figure><img src="/files/xPWAn4Bq2k1KSgoEM8Vn" alt=""><figcaption><p>App registrations</p></figcaption></figure>

* [ ] Click **New registration**.

<figure><img src="/files/03jzIqfqo1fn2tHzmhQr" alt=""><figcaption><p>New Registration</p></figcaption></figure>

* [ ] Provide a **name** for the app (e.g., `My Azure Integration`).
* [ ] Set **Supported account types** to *Accounts in this organizational directory only* (unless you require multi-tenant).
* [ ] Set a **Redirect URI** if needed (optional).
* [ ] Click **Register**.

<figure><img src="/files/p2APyDls9xqHP6UnHMCB" alt=""><figcaption><p>Register</p></figcaption></figure>

* [ ] After App Registration you must copy the Application (client) ID and Directory (tenant) ID

<figure><img src="/files/zGnZWHgcXdNRAIgZgS4k" alt=""><figcaption><p>After App Registration</p></figcaption></figure>

* [ ] Set up Azure Active Directory integration in the application for enterprise authentication and Microsoft 365 service access. Configure tenant credentials, client authentication, and API permissions. Please continue with [Login With Client Secret](/fsprotect/settings/azure-configurations/login-with-client-secret.md). But we recommend to continue with [Login With Certificate](/fsprotect/settings/azure-configurations/login-with-certificate.md).

### Step 2: Assign Required API Permissions

* [ ] Open the **App Registration** you just created.

<figure><img src="/files/dLS2p1yHEPgCT13iblDg" alt=""><figcaption><p>API Permissions</p></figcaption></figure>

* [ ] Go to **API permissions** > Click **+ Add a permission**.

<figure><img src="/files/yxJcewxDdpSTryfxVn42" alt=""><figcaption></figcaption></figure>

* [ ] Choose **Microsoft Graph**.

<figure><img src="/files/93eol5QmBIGcu7J1ouBv" alt=""><figcaption><p>Microsoft Graph</p></figcaption></figure>

* [ ] Select **Application permissions**.

<figure><img src="/files/hWekGEWxCw5OHjaFILCo" alt=""><figcaption><p>Application permissions</p></figcaption></figure>

* [ ] Add the following permissions:
  * `Directory.Read.All`
  * `AuditLog.Read.All`
  * `Policy.Read.All`
  * `RoleManagement.Read.All`
  * `OnPremDirectorySynchronization.Read.All`
* [ ] The following permission are required if you scan Teams and Sharepoints:
  * `Teams Reader Role` [#what-is-teams-reader-role](#what-is-teams-reader-role "mention")
  * &#x20;`SharePointTenantSettings.Read.All`
  * `Sites.Read.All`
  * `Sharepoint.Sites.FullControl.All`&#x20;
* [ ] Click **Add permissions**.

<figure><img src="/files/jn5eg2FjRsJo7efANLWe" alt=""><figcaption><p>Add Permissions</p></figcaption></figure>

* To add `Sharepoint.Sites.FullControl.All` permission, select SharePoint instead of Microsoft Graph at Microsoft APIs tab and choose application permissions.

<figure><img src="/files/Ksp60xAKcwdQc2ReSCgC" alt=""><figcaption><p>Sharepoint API Selection</p></figcaption></figure>

* &#x20;Type `Sites.FullControl.All`  to find permission.

<figure><img src="/files/70CShFlFbmySzBztMuQX" alt=""><figcaption><p>Add Permissions</p></figcaption></figure>

* [ ] After adding, click **Grant admin consent for \[Your Tenant Name]**.

<figure><img src="/files/GWwHfngSjDi0LTv7ppbZ" alt=""><figcaption><p>Grant admin consent</p></figcaption></figure>

* [ ] Confirm the prompt to grant consent.

<figure><img src="/files/TzEZBIH0eVlBzYQydE1F" alt=""><figcaption><p>Grant admin consent confirmation</p></figcaption></figure>

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

***

### What is Teams Reader Role?

Teams Reader role lets users view Teams settings and information without being able to change anything.

#### Step 1: Search for Roles

Go to the Microsoft Entra admin center and type "roles" in the search box at the top.

<figure><img src="/files/MqY8uG0cAvRsdMXI6Wby" alt=""><figcaption><p>Search roles</p></figcaption></figure>

Click on **Microsoft Entra roles and administrators** from the Services section.

#### Step 2: Find Teams Reader Role

In the roles page, search for "teams" to find Teams-related roles.

<figure><img src="/files/5u999ljKPajobmb6puNn" alt=""><figcaption><p>Teams Reader Role</p></figcaption></figure>

Look for **Teams Reader** role. The description says: "Read everything in the Teams admin center, but not update anything."

#### Step 3: Add Users or Groups

Click on the Teams Reader role, then go to **Assignments** and click **Add assignments**.

<figure><img src="/files/ljTgCcTmrtDzCmj41OSD" alt=""><figcaption><p>Team Reader Assignments</p></figcaption></figure>

Search for the user, group, or application you want to give this role to. In this example, we searched for "forestall" and found the "forestall-collector" enterprise application.

Select the item from the search results and add it.

***

### (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:**

* [ ] Open Cloud Shell from navbar

<figure><img src="/files/4ZahdSBzg7Pm3eyXlxDA" alt=""><figcaption><p>Cloud Shell</p></figcaption></figure>

* [ ] Select PowerShell from modal

<figure><img src="/files/brXzXggsRxnYNHgUnAEm" alt=""><figcaption><p>PowerShell</p></figcaption></figure>

* [ ] Save powershell script below as permissions.ps1

```
# Basic settings
$appName = "forestall-collector"

# Microsoft Graph API
$graphApiId = "00000003-0000-0000-c000-000000000000"
$graphPermissions = @{
    "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"
    "SharePointTenantSettings.Read.All"       = "83d4163d-a2d8-4d3b-9695-4ae3ca98f888"
    "Sites.Read.All"                          = "332a536c-c7ef-4017-ab91-336970924f0d"
}

# SharePoint Online API
$sharepointApiId = "00000003-0000-0ff1-ce00-000000000000"
$sharepointPermissions = @{
    "Sites.FullControl.All" = "678536fe-1083-478a-9c59-b99265e6b0d3"
}

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 }
}

# Add Microsoft Graph permissions
foreach ($permName in $graphPermissions.Keys) {
    $permId = $graphPermissions[$permName]
    Write-Host "Adding Graph 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 }
}

# Add SharePoint permissions
foreach ($permName in $sharepointPermissions.Keys) {
    $permId = $sharepointPermissions[$permName]
    Write-Host "Adding SharePoint permission $permName"
    az ad app permission add --id $appId --api $sharepointApiId --api-permissions "$permId=Role" --only-show-errors | Out-Null
    if (-not $?) { Write-Error "Failed to add SharePoint $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 file to powershell

<figure><img src="/files/aCxyhe9ov4Zduth6R5EZ" alt=""><figcaption><p>Upload PowerShell Script</p></figcaption></figure>

* [ ] After uploading the file, run it via console `./permissions.ps1`

<figure><img src="/files/27ks9MGxbIiTP6fkNqGq" alt=""><figcaption></figcaption></figure>

#### Notes:

* You can find your App ID in **App registrations** > \[Your App] > **Overview**.
* After assigning permissions via script you need to copy **Secret Value**.&#x20;

<figure><img src="/files/gXMJ6bybrAVoK75zIxJa" alt=""><figcaption><p>Client Secret needs to copy</p></figcaption></figure>

* If using script without **global admin account, admin consent** still needs to be granted manually in the portal (go to optional step 2).&#x20;

### (Optional Step 2): Grant Admin Consent via Portal (if using script)

1. Go back to **App registrations** > \[Your App] > **API permissions**.
2. Click **Grant admin consent** to activate the permissions.
3. Teams Reader Role must be assigned manually. Please check [#what-is-teams-reader-role](#what-is-teams-reader-role "mention")

## Step 3: Azure Configuration in FSProtect

This section allows you to configure Azure Active Directory (Azure AD) authentication and permissions for the application. Use this configuration to grant or revoke access to Azure resources and services.

<figure><img src="/files/bOZINfW6Zc8OAD1qt9Ag" alt=""><figcaption><p>Azure Configuration</p></figcaption></figure>

### Configuration Fields

#### Region

Specifies the Azure environment where your application is deployed. Options typically include:

* **Cloud** - Azure Public Cloud (standard commercial cloud)
* **Government** - Azure Government Cloud (for US government agencies)
* **China** - Azure China Cloud (operated by 21Vianet)

#### Directory (Tenant) ID

**Format:** UUID (e.g., `05588dae-2a80-4f4d-...`)

Your Azure AD tenant identifier. This is a unique GUID that identifies your organization's Azure Active Directory instance. You can find this in the Azure Portal under `Azure Active Directory` > `Overview` > `Tenant ID`.

#### Application (Client) ID

**Format:** UUID (e.g., `07122f25-82ff-496d-...`)

The unique identifier for your registered application in Azure AD. This is generated when you register an application in Azure Portal under App Registrations. This ID is used to identify your application when requesting authentication tokens.

#### Password Writeback Enabled

Determines whether password changes in Azure AD has written back to your on-premises Active Directory. Options:

* **Enabled** - Password changes sync back to on-premises AD
* **Disabled** - Password changes remain only in Azure AD
* **Not Defined** - Feature is not configured

#### Authentication Method

Specifies how your application authenticates with Azure AD. Common methods include:

* **Client Secret** - Uses a client secret for authentication
* **Certificate (recommended)** - Uses a certificate for authentication

#### Client Secret

The secret key used to authenticate your application with Azure AD. This value should be:

* Kept secure and never exposed in code or logs
* Rotated regularly according to your security policy
* Obtained from Azure Portal under `App Registrations` > `Certificates & secrets`

#### Tenant Display Name

A friendly name for your Azure AD tenant. This is typically your organization's name and helps identify the tenant in multi-tenant scenarios.

#### App Display Name

The display name of your registered application in Azure AD. This name appears in consent prompts and admin portals to help identify your application.

### Actions

#### Test

Validates the Azure configuration by attempting to authenticate and verify permissions. Use this to ensure your configuration is correct before saving.

#### Save

Saves the current configuration settings to application. All fields must be properly configured before saving.

#### Delete

Removes the Azure configuration from application. Use with caution as this will disable Azure AD integration.

### Best Practices

1. **Least Privilege Principle** - Only grant the minimum permissions required for application to function
2. **Secret Rotation** - Regularly rotate client secrets (recommended every 90 days or per your security policy)
3. **Permission Review** - Periodically review granted permissions and remove any that are no longer needed
4. **Testing** - Always use the "Test" button to validate configuration before saving changes

### Troubleshooting

**Authentication Fails**

* Verify the Client ID and Client Secret are correct
* Ensure the secret hasn't expired
* Check that the application is registered in the correct tenant

**Permission Denied Errors**

* Confirm all required permissions are granted
* Verify an admin has consented to the permissions
* Check that users have appropriate licenses in Azure AD

**Configuration Won't Save**

* Ensure all required fields are filled
* Verify the Tenant ID and Client ID formats are valid UUIDs
* Check that the Test passes successfully before saving

## Required Microsoft Azure Permissions for Integration <a href="#integration" id="integration"></a>

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.

## Optional Microsoft Azure Permissions for Enhanced Functionality

These permissions enhance functionality but are not required for basic operation. Grant these based on your application's specific needs and use cases.

### 1. Teams Readers Role

**What it does:**&#x20;

Grants read-only access to Microsoft Teams administration data and settings, including team configurations, user assignments, policies, and administrative information without the ability to make any changes.

**Why it's needed:**&#x20;

Required when users or applications need to view Teams administrative settings for monitoring, reporting, compliance audits, or troubleshooting purposes without risking accidental modifications to the Teams environment.

### 2. SharePointTenantSettings.Read.All

**What it does:**&#x20;

Provides read access to SharePoint tenant-level settings, including external sharing policies, site creation settings, and tenant-wide configurations.

**Why it's needed:**&#x20;

Essential for understanding the global SharePoint configuration across your organization, helping administrators audit tenant settings, identify security risks, or ensure compliance with organizational policies.

### 3. Sites.Read.All

**What it does:**&#x20;

Enables the application to read SharePoint site collections, lists, libraries, and their content across the entire organization without user delegation.

**Why it's needed:**&#x20;

Required when your integration needs to analyze SharePoint content, generate reports on site usage, perform content audits, or provide visibility into document repositories for compliance purposes.

### 4. Sharepoint.Sites.FullControl.All

**What it does:**&#x20;

Provides full control over all SharePoint sites, allowing the application to create, read, update, and delete sites, site collections, lists, libraries, and their content.

**Why it's needed:**&#x20;

Necessary for integrations that actively manage SharePoint environments—such as automated site provisioning, content migration tools, backup solutions, or applications that modify site structures and permissions on behalf of administrators.

**⚠️ Security Note:** This is a highly privileged permission that grants extensive control over SharePoint data. Only grant this permission if your application absolutely requires write/modify capabilities, and ensure proper governance and monitoring are in place.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestall.io/fsprotect/settings/azure-configurations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
