Azure Discovery
The Infracast Azure plugin authenticates using a service principal with read-only access assigned via Azure RBAC. It uses the Azure Resource Manager API and Microsoft Graph API to enumerate resources across your subscriptions.
How It Works
- Infracast authenticates as a service principal using client credentials (client ID + secret, or certificate)
- The plugin queries Azure Resource Manager for all resource types in scope
- Microsoft Graph is queried for Azure Active Directory objects (users, groups, apps)
- Resources are normalized and written to the Infracast graph
Service Principal Setup
Step 1: Create the Service Principal
Option A: Azure CLI (recommended)
# Log in to Azure
az login
# Create a service principal for Infracast
az ad sp create-for-rbac \
--name "infracast-discovery" \
--skip-assignment \
--output json
This outputs:
{
"appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"displayName": "infracast-discovery",
"password": "your-client-secret",
"tenant": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
}
Save the appId (client ID), password (client secret), and tenant (tenant ID). The client secret is shown only once.
Option B: Azure Portal
- Go to Azure Active Directory → App registrations → New registration
- Name:
infracast-discovery, leave other settings as defaults - Click Register
- Go to Certificates & secrets → New client secret
- Set expiry (recommend 24 months) and save the secret value
Step 2: Note Your IDs
# Get your tenant ID
az account show --query tenantId -o tsv
# Get the service principal object ID (needed for role assignments)
az ad sp show --id YOUR_APP_ID --query id -o tsv
Step 3: Assign RBAC Roles
Infracast needs the Reader role on each subscription, plus Directory Readers in Azure AD for identity discovery.
Assign Reader role per subscription:
# Assign Reader role to the service principal on a subscription
az role assignment create \
--assignee YOUR_APP_ID \
--role "Reader" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID"
Assign Directory Readers for Azure AD:
# Assign Directory Readers role in Azure AD
az rest --method POST \
--uri "https://graph.microsoft.com/v1.0/directoryRoles/roleTemplateId=88d8e3e3-8f55-4a1e-953a-9b9898b8876b/members/\$ref" \
--body "{\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/SP_OBJECT_ID\"}"
Or via Portal: Azure AD → Roles and administrators → Directory Readers → Add assignments → Search for infracast-discovery
Required RBAC Roles Summary
| Role | Scope | Purpose |
|---|---|---|
Reader | Subscription (each) | Read all ARM resources |
Directory Readers | Azure AD tenant | Read users, groups, apps, devices |
Security Reader | Subscription (optional) | Read Defender for Cloud findings |
Key Vault Reader | Key Vaults (optional) | Read Key Vault metadata |
The Reader role is sufficient for most discovery use cases. Directory Readers is required if you want Azure AD identity discovery. Security Reader adds Defender for Cloud findings to the graph.
Step 4: Grant Microsoft Graph API Permissions (for AD discovery)
In Azure AD → App registrations → infracast-discovery → API permissions:
- Click Add a permission → Microsoft Graph → Application permissions
- Add the following permissions:
| Permission | Purpose |
|---|---|
Directory.Read.All | Read users, groups, OUs, devices |
Group.Read.All | Read group memberships |
User.Read.All | Read all user profiles |
Application.Read.All | Read app registrations and service principals |
Policy.Read.All | Read conditional access policies |
AuditLog.Read.All | Read sign-in and audit logs |
- Click Grant admin consent (requires Global Admin or Privileged Role Admin)
What Gets Discovered
| Service | Resource Types |
|---|---|
| Compute | Virtual Machines, VM Scale Sets, Availability Sets, Proximity Placement Groups |
| Networking | Virtual Networks, Subnets, Network Security Groups, Route Tables, Public IPs, Load Balancers, Application Gateways, VPN Gateways, ExpressRoute Circuits, Private Endpoints |
| Storage | Storage Accounts, Blob containers (metadata), File shares, Queue/Table services |
| Databases | Azure SQL servers/databases, Cosmos DB accounts, PostgreSQL/MySQL Flexible Servers |
| AKS | Kubernetes clusters, Node pools, Add-ons |
| App Service | App Service Plans, Web Apps, Function Apps, API Apps |
| Azure AD | Users, Groups, Service Principals, App Registrations, Managed Identities, Conditional Access Policies |
| Security | Key Vaults, Defender for Cloud findings, Security contacts |
| Identity | Managed Identities (system and user-assigned), Role assignments |
| Subscriptions | Subscriptions, Management Groups, Resource Groups |
Registering the Credential in Infracast
# Register using client secret
infracast creds add \
--plugin azure \
--name "contoso-subscription" \
--type service-principal \
--tenant-id "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" \
--client-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
--client-secret-file /run/secrets/azure-sp-secret
# Register using certificate (more secure)
infracast creds add \
--plugin azure \
--name "contoso-subscription-cert" \
--type service-principal-cert \
--tenant-id "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" \
--client-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
--certificate-file /run/secrets/azure-sp-cert.pem
Configuring the Discovery Job
discovery:
jobs:
- name: azure-contoso
plugin: azure
credential: contoso-subscription
schedule: "0 */6 * * *"
config:
tenant_id: "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
subscriptions:
- id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
name: "production"
- id: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
name: "development"
# Discover Azure AD objects (requires Directory Readers)
discover_azure_ad: true
# Include specific resource types only (optional)
include_resource_types:
- Microsoft.Compute/virtualMachines
- Microsoft.Network/virtualNetworks
- Microsoft.Storage/storageAccounts
Multi-Subscription Setup
Option 1: Single Service Principal, Multiple Subscriptions
Assign the Reader role to the same service principal on multiple subscriptions. List all subscription IDs in the job config:
# Assign Reader to multiple subscriptions with a loop
for SUB_ID in sub-id-1 sub-id-2 sub-id-3; do
az role assignment create \
--assignee YOUR_APP_ID \
--role "Reader" \
--scope "/subscriptions/$SUB_ID"
done
config:
subscriptions:
- id: "sub-id-1"
name: "production"
- id: "sub-id-2"
name: "staging"
- id: "sub-id-3"
name: "development"
Option 2: Management Group Scope
Assign the Reader role at the Management Group level to cover all child subscriptions automatically:
az role assignment create \
--assignee YOUR_APP_ID \
--role "Reader" \
--scope "/providers/Microsoft.Management/managementGroups/YOUR_MGMT_GROUP_ID"
config:
mode: management-group
management_group_id: "your-mgmt-group-id"
discover_azure_ad: true
Management Group scope is the recommended approach for large organizations. New subscriptions added under the management group are automatically picked up without any Infracast configuration changes.
Troubleshooting
AuthenticationFailed: AADSTS7000215
Symptom: Invalid client secret provided
Cause: The client secret has expired or was entered incorrectly.
Fix:
# Create a new secret
az ad app credential reset --id YOUR_APP_ID --years 2
# Update the credential in Infracast
infracast creds update --name "contoso-subscription" \
--client-secret-file /run/secrets/new-azure-sp-secret
AuthorizationFailed on specific resource types
Symptom: Some resources appear but others are missing; logs show 403 AuthorizationFailed
Cause: The Reader role may not cover certain resource types (e.g., Key Vaults with access policies).
Fix: Add specific role assignments:
# Example: Add Key Vault Reader
az role assignment create \
--assignee YOUR_APP_ID \
--role "Key Vault Reader" \
--scope "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.KeyVault/vaults/VAULT_NAME"
Azure AD objects not discovered
Symptom: No users/groups in the Infracast graph from Azure AD
Checks:
- Verify
Directory Readersrole is assigned to the service principal in Azure AD - Verify Microsoft Graph API permissions are granted (admin consent required)
- Check that
discover_azure_ad: trueis set in the job config - Verify the service principal has
Directory.Read.Allpermission (not just delegated)
# Check current app permissions
az ad app permission list --id YOUR_APP_ID
Too many requests / throttling
Symptom: Discovery runs partially complete before failing with HTTP 429
Fix: Adjust the rate limiting config:
config:
api_rate_limit_rps: 5 # reduce from default 20
retry_on_throttle: true
retry_max_attempts: 5
retry_backoff_seconds: 30
Service principal expiry warnings
Symptom: Infracast UI shows warning about expiring credentials
Infracast monitors client secret expiry dates and warns 30 days before expiration. Rotate secrets before they expire:
az ad app credential reset \
--id YOUR_APP_ID \
--years 2 \
--display-name "infracast-$(date +%Y)"