Skip to content

Azure Cloud Discovery

Discover all Azure resources across your subscriptions, identify unmanaged infrastructure, and bring it under Terraform management.

Prerequisites

  1. Azure credentials configured in Settings > Cloud
  2. Self-hosted runner (required) — must be online and connected to your organization
  3. Reader role on each subscription you want to scan

Self-Hosted Runner Required

Azure cloud discovery requires a self-hosted runner running inside your Azure network. Cloud runners cannot access network-restricted resources like storage accounts with firewall rules. The runner scans your Terraform state files from Azure Blob Storage and reports results back to Controlinfra.

Set up a runner in Settings > Runners before running an Azure discovery scan.

Required Permissions

The identity used for discovery needs:

RoleScopePurpose
ReaderSubscription(s)Enumerate all resources via Resource Graph
Storage Blob Data ReaderState storage accountScan Terraform state files
bash
# Assign Reader on a subscription
az role assignment create \
  --assignee YOUR_PRINCIPAL_ID \
  --role "Reader" \
  --scope /subscriptions/YOUR_SUBSCRIPTION_ID

# Assign blob reader on state storage (optional)
az role assignment create \
  --assignee YOUR_PRINCIPAL_ID \
  --role "Storage Blob Data Reader" \
  --scope /subscriptions/YOUR_SUB/resourceGroups/YOUR_RG/providers/Microsoft.Storage/storageAccounts/YOUR_STORAGE

Multi-Subscription Access

Grant the Reader role on each subscription you want to discover. Controlinfra automatically detects all subscriptions your credential has access to — no need to configure them individually.

Running a Discovery Scan

  1. Go to Cloud Discovery in the sidebar
  2. Click Run Discovery
  3. Select Azure as the provider
  4. Configure:
    • Subscriptions — select which Azure subscriptions to scan (all accessible subscriptions are shown automatically)
    • Services — choose which Azure services to scan (Compute, Networking, Storage, Database, etc.)
    • Locations — select Azure regions to include
    • State Files (optional) — enter your Azure Storage account and container where .tfstate files are stored
  5. Click Start Scan

INFO

The Subscriptions tab lists every subscription your Azure credential (OIDC or Service Principal) can access. If a subscription is missing, ensure the service principal has the Reader role assigned on it.

How It Works

Phase 1: Resource Discovery

Controlinfra uses Azure Resource Graph to enumerate all resources across your selected subscriptions in a single query. Resource Graph natively supports multi-subscription queries, so scanning multiple subscriptions is just as fast as scanning one.

Phase 2: Enrichment

For key resource types, Controlinfra makes additional API calls to capture detailed configuration:

ServiceDetails Captured
VMsVM size, OS, disks, NICs, zones, identity
AKSKubernetes version, node pools (sizes, scaling), network profile
NetworkingNSG rules, public IP allocation, load balancer config
StorageAccount tier, replication, encryption, network rules
SQL/PostgreSQLSKU, capacity, HA, backup settings
Key VaultSKU, RBAC, soft delete, network ACLs

Phase 3: State Matching

If you provided a state file location, Controlinfra downloads and parses .tfstate files from Azure Blob Storage. Each discovered resource is matched against the state index using Azure resource IDs.

Phase 4: Cost Estimation

Orphaned (unmanaged) resources are priced using the Azure Retail Prices API with static fallbacks for common VM sizes.

Phase 5: AI Analysis

Claude AI analyzes orphaned resources to identify:

  • Cleanup priorities and cost savings
  • Security risks (exposed resources, missing encryption)
  • Patterns (e.g., abandoned resource groups, orphaned disks)

Supported Resource Types

Controlinfra maps 100+ Azure resource types to their Terraform equivalents:

CategoryResource Types
ComputeVMs, Scale Sets, Disks, Images, Snapshots
ContainersAKS, ACR, Container Instances
NetworkingVNets, Subnets, NSGs, Public IPs, Load Balancers, App Gateways, Front Door, Firewall, Bastion, VPN Gateway, ExpressRoute
StorageStorage Accounts
DatabaseSQL Server/DB, PostgreSQL Flexible, MySQL Flexible, CosmosDB, Redis Cache
App ServiceService Plans, Web Apps, Static Web Apps, Function Apps
SecurityKey Vault (secrets, keys, certificates)
IdentityManaged Identities, Role Assignments
MonitoringLog Analytics, Application Insights, Alerts
MessagingService Bus, Event Hub
AnalyticsDatabricks, Synapse, Data Factory
AICognitive Services, ML Workspaces
IntegrationLogic Apps, API Management, SignalR

Terraform Code Generation

For orphaned resources, Controlinfra generates:

  1. HCL resource blocks with actual configuration from the discovered resource
  2. terraform import commands using the Azure resource ID
  3. Provider configuration with azurerm backend pointing to your state storage

Troubleshooting

"Azure credentials not configured"

Add Azure credentials in Settings > Cloud > Add Account with the OIDC or Service Principal auth method.

"AccessDenied" or "Reader role required"

The identity needs Reader on each subscription you want to scan. Assign via Azure CLI:

bash
az role assignment create --assignee YOUR_ID --role Reader --scope /subscriptions/YOUR_SUB

Subscription not showing in the dropdown

The Subscriptions dropdown only shows subscriptions where your credential has at least Reader access. To add a subscription:

  1. Go to the Azure Portal > Subscriptions > select the target subscription
  2. Click Access control (IAM) > Add role assignment
  3. Assign the Reader role to your service principal or app registration
  4. Wait ~1 minute for propagation, then re-open the scan modal

OIDC issuer mismatch (AADSTS700211)

If you see No matching federated identity record found for presented assertion issuer, the OIDC issuer URL in your server environment doesn't match the issuer configured in your Azure federated credential. Ensure OIDC_ISSUER matches what you set in az ad app federated-credential create.

Empty state file results

Ensure the storage account name and container are correct, and the identity has Storage Blob Data Reader on the storage account.

Missing resource types

Not all Azure resource types have Terraform equivalents. Resources without a mapping are still discovered but shown as "unknown" type.