Skip to main content

Instructions

Overview

This article outlines the steps to integrate your Azure tenant and its subscriptions with Upwind. Choose the approach that matches your role and requirements:

  • Global Admin - Full Tenant: Complete tenant integration with all subscriptions and automatic discovery of new ones
  • Global Admin - Limited Scope: Selective integration of specific subscriptions using scoping parameters
  • Subscription Owner: Integration using pre-created application registrations for users without Global Admin privileges

Integration Approaches

Choose the approach that matches your role and access level:

Approach 1: Global Admin - Full Tenant Integration

Who this is for: Global Administrators who want to integrate all subscriptions in the tenant with automatic discovery of new subscriptions. Application Administrators and other privileged users can also use this approach if a Global Administrator grants them Owner role over the root tenant management group.

Prerequisites

Option A: Global Administrator

  • Azure Global Administrator role
  • Ability to elevate access to all Azure resources

Option B: Application Administrator (or other privileged users)

  • Application Administrator role (or equivalent role with app registration permissions)
  • Owner role over root tenant management group (granted by Global Administrator)
  • No need for elevated access - the Owner role provides necessary permissions

Required Permissions Setup

Option 1: Self-Elevate Access (Recommended)

Use the "elevate access" feature to temporarily grant yourself User Access Administrator role at the root scope:

elevate-access_1.png elevate-access_2.png

Option 2: Request Owner Role Assignment

Have someone with appropriate permissions assign you the Owner role over the root tenant management group.

After gaining elevated access, you should be able to view the root tenant management group in Azure Portal:

management-groups_1.png management-groups_2.png

Integration Steps

  1. Elevate Access: Use one of the options above to gain tenant-wide permissions
  2. Run Terraform: Execute the Terraform configuration (no scoping variables needed)
  3. Grant Admin Consent: A Global Administrator must provide consent for the Microsoft Graph API permissions requested by Terraform
  4. Revoke Elevated Access: Remove the elevated permissions after successful deployment
  5. Optional: Assign yourself Owner role for ongoing management, then revoke elevated access
Terraform Enterprise / CI/CD Integration

For automated Terraform operations (Terraform Enterprise, CI/CD pipelines), you can reduce the service principal's permissions after initial deployment:

  • After initial apply: Downgrade the Terraform runner's service principal to Reader role over the root tenant management group
  • For routine operations: Reader permissions allow subsequent terraform apply operations as long as no new RBAC changes are needed
  • For structural changes: Temporarily elevate the service principal back to Owner when making changes that affect tenant-level role assignments or permissions

This approach balances security best practices with operational requirements for automated infrastructure management.

Note: If using App Registration authentication for Terraform, see the App Registration Authentication prerequisite.

Terraform Configuration

Use the standard configuration without scoping variables:

locals {
azure_tenant_id = "your-azure-tenant-id"
azure_orchestrator_subscription_id = "your-azure-orchestrator-subscription-id"
}

provider "azurerm" {
# For detailed instructions on configuring the Azure provider, please refer to:
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
subscription_id = local.azure_orchestrator_subscription_id
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
key_vault {
recover_soft_deleted_keys = true
recover_soft_deleted_secrets = true
}
}
}

provider "azuread" {
tenant_id = local.azure_tenant_id
}

module "upwind_integration_azure_onboarding" {
source = "upwindsecurity/onboarding/azurerm//modules/tenant"

# Upwind Credentials
upwind_client_id = "your-unique-upwind-client-id"
upwind_client_secret = "your-unique-upwind-client-secret"

# Cloud Scanner Credentials
scanner_client_id = "your-unique-upwind-scanner-id"
scanner_client_secret = "your-unique-upwind-scanner-secret"

# Upwind Details
upwind_organization_id = "your-upwind-organization-id"

# Azure Details
azure_tenant_id = local.azure_tenant_id
azure_orchestrator_subscription = local.azure_orchestrator_subscription_id

# Optional customization
resource_suffix = "upwind"
azure_cloudscanner_location = "eastus"
}

Approach 2: Global Admin - Limited Scope Integration

Who this is for: Global Administrators who want to integrate only specific subscriptions using scoping parameters.

Prerequisites

  • Azure Global Administrator role
  • Application Developer role (minimum) or Application Administrator role for creating app registrations
  • Owner role in the subscriptions you want to include in scope

Integration Steps

  1. No elevated access required - you only need Owner permissions on target subscriptions
  2. Configure scoping variables in Terraform to limit integration scope
  3. Run Terraform with the scoped configuration
  4. Grant Admin Consent: A Global Administrator must provide consent for the Microsoft Graph API permissions requested by Terraform

Terraform Configuration

Use scoping variables to limit integration to specific subscriptions:

locals {
azure_tenant_id = "your-azure-tenant-id"
azure_orchestrator_subscription_id = "your-azure-orchestrator-subscription-id"
}

provider "azurerm" {
# For detailed instructions on configuring the Azure provider, please refer to:
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
subscription_id = local.azure_orchestrator_subscription_id
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
key_vault {
recover_soft_deleted_keys = true
recover_soft_deleted_secrets = true
}
}
}

provider "azuread" {
tenant_id = local.azure_tenant_id
}

module "upwind_integration_azure_onboarding" {
source = "upwindsecurity/onboarding/azurerm//modules/tenant"

# Upwind Credentials
upwind_client_id = "your-unique-upwind-client-id"
upwind_client_secret = "your-unique-upwind-client-secret"

# Cloud Scanner Credentials
scanner_client_id = "your-unique-upwind-scanner-id"
scanner_client_secret = "your-unique-upwind-scanner-secret"

# Upwind Details
upwind_organization_id = "your-upwind-organization-id"

# Azure Details
azure_tenant_id = local.azure_tenant_id
azure_orchestrator_subscription = local.azure_orchestrator_subscription_id

# Subscription Scoping - Include specific subscriptions
cloudapi_include_subscriptions = [
"subscription-id-1",
"subscription-id-2",
"your-orchestrator-subscription-id"
]
# Cloud Scanner will only scan the subscriptions specified here
cloudscanner_include_subscriptions = [
"subscription-id-1"
]

# Optional customization
resource_suffix = "upwind"
azure_cloudscanner_location = "eastus"
}
Scoping Rules
  • Do not mix include and exclude: Use either include OR exclude variables, never both together
  • Cloud API superset requirement: Subscriptions scoped for Cloud API must be a superset of subscriptions scoped for Cloud Scanner
  • Orchestrator subscription requirement: The orchestrator subscription must always be included in the Cloud API scope

Approach 3: Subscription Owner - Pre-Created App Registration

Who this is for: Users who own specific subscriptions but don't have Global Administrator privileges or permissions to create application registrations.

About the App Registration

This approach uses a pre-created App Registration that Upwind will use for authentication to access your Azure resources. This is different from an App Registration used to run Terraform itself. If you're using an App Registration to run Terraform (e.g., in CI/CD), see the note in Approach 1 about required Entra roles for the Terraform runner.

Prerequisites

  • Owner role in the subscriptions you want to integrate
  • Pre-created application registration (created by your IT admin)
  • Client secret for the application registration
  • Required Microsoft Graph API permissions granted to the application

Required Application Setup (Done by IT Admin)

Your IT administrator needs to create an application registration with:

  1. Application Registration: Create a new app registration in Entra ID
  2. Owner Assignment: Make you an owner of the application registration (so you can configure it)
  3. Client Secret: Generate a client secret for the application (or allow you to generate it as owner)
  4. API Permissions: Grant the following Microsoft Graph permissions:
    • User.Read.All
    • Group.Read.All
    • RoleManagement.Read.All
    • Directory.Read.All
    • Policy.Read.All
    • UserAuthenticationMethod.Read.All
  5. Admin Consent: A Global Administrator must provide consent for these permissions

Integration Steps

  1. Obtain credentials from your IT administrator
  2. Configure Terraform with the pre-created application details
  3. Run Terraform with subscription scoping

Terraform Configuration

Use the pre-created application registration:

locals {
azure_tenant_id = "your-azure-tenant-id"
azure_orchestrator_subscription_id = "your-azure-orchestrator-subscription-id"
}

provider "azurerm" {
# For detailed instructions on configuring the Azure provider, please refer to:
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
subscription_id = local.azure_orchestrator_subscription_id
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
key_vault {
recover_soft_deleted_keys = true
recover_soft_deleted_secrets = true
}
}
}

provider "azuread" {
tenant_id = local.azure_tenant_id
}

module "upwind_integration_azure_onboarding" {
source = "upwindsecurity/onboarding/azurerm//modules/tenant"

# Upwind Credentials
upwind_client_id = "your-unique-upwind-client-id"
upwind_client_secret = "your-unique-upwind-client-secret"

# Cloud Scanner Credentials
scanner_client_id = "your-unique-upwind-scanner-id"
scanner_client_secret = "your-unique-upwind-scanner-secret"

# Upwind Details
upwind_organization_id = "your-upwind-organization-id"

# Azure Details
azure_tenant_id = local.azure_tenant_id
azure_orchestrator_subscription = local.azure_orchestrator_subscription_id

# Pre-created Application Registration
azure_application_client_id = "your-pre-created-app-client-id"
azure_application_client_secret = "your-pre-created-app-client-secret"

# Subscription Scoping - Include only your subscriptions
cloudapi_include_subscriptions = [
"your-subscription-id-1",
"your-subscription-id-2",
"your-orchestrator-subscription-id"
]
cloudscanner_include_subscriptions = [
"your-subscription-id-1"
]

# Optional customization
resource_suffix = "upwind"
azure_cloudscanner_location = "eastus"
}

Getting Started

  1. Log in to the Upwind Management Console
  2. Select the + (plus) symbol at the top of the screen and select Connect cloud account
  3. Choose Azure, and from there Connect Azure Tenant
  4. Follow the steps for your chosen approach above

Final Configuration

After running Terraform successfully, complete the integration in the Upwind Management Console:

  1. Define Subscription Scope: Choose which subscriptions should be audited using Cloud APIs or scanned using Upwind Cloud Scanners
  2. Enable Auto-Connect (optional): Automatically connect new subscriptions as they're created
  3. Test Connectivity: Click Test & Save to verify the connection
Scope Dependency

Cloud Scanner scopes are dependent on the Cloud API scope. If you enable the Cloud Scanner scope, the Cloud API scope must also be enabled.

Unsupported Regions

Some regions are not yet supported for Upwind Cloud Scanner deployments, as Azure Container Jobs are not available in those regions:

  • westindia
  • koreasouth
  • israelcentral
  • mexicocentral
  • newzealandnorth
  • qatarcentral

Troubleshooting

If you encounter issues during deployment or operation, consult the Troubleshooting guide for solutions and best practices.

Resources Created

Azure Resource Group

A resource group named upwind-cs-rg-{orgId} is created containing:

Azure Key Vault

  • Contains secrets for scanner authentication (client ID and client secret)

Managed Identities

Three managed identities are created:

  1. VMSS Identity (upwind-cs-vmss-identity-{orgId})

    • Assigned to virtual machine scale sets
    • Manages snapshots and disks
    • Has read and snapshot access across subscriptions
    • Has Key Vault Secrets User access
  2. Scaler Function Identity (upwind-cs-scaler-function-identity-{orgId})

    • Assigned to container app jobs
    • Manages VMSS scaling
    • Manages disks and snapshots cleanup
    • Has Key Vault Secrets User access
  3. Disk Encryption Identity (upwind-cs-disk-encryption-identity-{orgId})

    • Assigned to disk encryption sets
    • Has Key Vault Crypto Service Encryption User access

RBAC Configuration

Service Principal

Tenant-wide roles:

  • Reader
  • Key Vault Reader
  • Security Reader
  • Cosmos DB Account Reader Role
  • Backup Reader
  • Log Analytics Reader
  • Custom role: upwindsecurity-{random-hex}

VMSS Managed Identity

Tenant-wide roles:

  • Storage Blob Data Reader
  • Custom role: CloudScannerTargetRole-{suffix}-{managementGroup}

Scaler Managed Identity

Orchestrator subscription role:

  • Custom role: CloudScannerScalerRole-{suffix}

Disk Encryption Set Managed Identity

Role:

  • Key Vault Crypto Service Encryption User

Troubleshooting

If you encounter issues during deployment or operation, consult the Troubleshooting guide for solutions and best practices.