Azure Setup
App Registration

App Registration

Create a Service Principal with least-privilege permissions for Cost Management, Resource Inventory, and Metrics collection.

Azure CLI

# Sign in
az login
 
# Set your subscription ID
SUBSCRIPTION_ID="your-subscription-id-here"
 
# Create Service Principal (initially with no role assignments)
SP_OUTPUT=$(az ad sp create-for-rbac \
  --name "Verdaro-Cloud-Connector" \
  --skip-assignment \
  --output json)
 
# Extract credentials
CLIENT_ID=$(echo $SP_OUTPUT | jq -r '.appId')
CLIENT_SECRET=$(echo $SP_OUTPUT | jq -r '.password')
TENANT_ID=$(echo $SP_OUTPUT | jq -r '.tenant')
 
echo "Client ID: $CLIENT_ID"
echo "Tenant ID: $TENANT_ID"
echo "Client Secret: $CLIENT_SECRET"
 
# Assign required roles
# 1. Cost Management Reader - for cost data exports
az role assignment create \
  --assignee $CLIENT_ID \
  --role "Cost Management Reader" \
  --scope "/subscriptions/$SUBSCRIPTION_ID"
 
# 2. Reader - for Resource Graph queries (inventory sync)
az role assignment create \
  --assignee $CLIENT_ID \
  --role "Reader" \
  --scope "/subscriptions/$SUBSCRIPTION_ID"
 
# 3. Monitoring Reader - for Azure Monitor metrics
az role assignment create \
  --assignee $CLIENT_ID \
  --role "Monitoring Reader" \
  --scope "/subscriptions/$SUBSCRIPTION_ID"

Record the output values:

  • appId → Client ID
  • tenant → Tenant ID
  • password → Client Secret

PowerShell

Connect-AzAccount
 
$SubscriptionId = "your-subscription-id-here"
 
# Create Service Principal
$sp = New-AzADServicePrincipal -DisplayName "Verdaro-Cloud-Connector"
 
# Create a client secret
$secret = New-AzADAppCredential -ObjectId $sp.Id -EndDate (Get-Date).AddYears(2)
 
Write-Host "Client ID: $($sp.AppId)"
Write-Host "Tenant ID: $((Get-AzContext).Tenant.Id)"
Write-Host "Client Secret: $($secret.SecretText)"
 
# Assign required roles
# 1. Cost Management Reader
New-AzRoleAssignment `
  -ObjectId $sp.Id `
  -RoleDefinitionName "Cost Management Reader" `
  -Scope "/subscriptions/$SubscriptionId"
 
# 2. Reader (for Resource Graph)
New-AzRoleAssignment `
  -ObjectId $sp.Id `
  -RoleDefinitionName "Reader" `
  -Scope "/subscriptions/$SubscriptionId"
 
# 3. Monitoring Reader (for Azure Monitor)
New-AzRoleAssignment `
  -ObjectId $sp.Id `
  -RoleDefinitionName "Monitoring Reader" `
  -Scope "/subscriptions/$SubscriptionId"

Required Permissions Summary

Verdaro requires these Azure RBAC roles for full functionality:

RoleScopePurpose
Cost Management ReaderSubscriptionRead cost exports and billing data
ReaderSubscriptionQuery Azure Resource Graph for inventory sync
Monitoring ReaderSubscriptionCollect metrics from Azure Monitor
Storage Blob Data ReaderStorage AccountDownload cost export files

Permission Details

Cost Management Reader

  • Allows reading Cost Management exports
  • Required for cost data ingestion (FOCUS format)
  • Minimum scope: Subscription level

Reader

  • Enables Azure Resource Graph queries
  • Used to discover and inventory all resources in the subscription
  • Provides read access to resource metadata, tags, and properties
  • Required for: Resource inventory sync, relationship mapping, tag compliance

Monitoring Reader

  • Access to Azure Monitor metrics API
  • Collects 30-day performance metrics for resources
  • Metrics collected: CPU, memory, disk I/O, network throughput
  • Required for: Rightsizing recommendations, idle resource detection

Multi-Subscription Setup

To connect multiple subscriptions with a single Service Principal:

# Assign roles to additional subscriptions
for SUB_ID in "sub-id-1" "sub-id-2" "sub-id-3"; do
  az role assignment create \
    --assignee $CLIENT_ID \
    --role "Cost Management Reader" \
    --scope "/subscriptions/$SUB_ID"
  
  az role assignment create \
    --assignee $CLIENT_ID \
    --role "Reader" \
    --scope "/subscriptions/$SUB_ID"
  
  az role assignment create \
    --assignee $CLIENT_ID \
    --role "Monitoring Reader" \
    --scope "/subscriptions/$SUB_ID"
done

Management Group Scope (Enterprise)

For organization-wide access, assign roles at the Management Group level:

MANAGEMENT_GROUP_ID="your-management-group-id"
 
az role assignment create \
  --assignee $CLIENT_ID \
  --role "Cost Management Reader" \
  --scope "/providers/Microsoft.Management/managementGroups/$MANAGEMENT_GROUP_ID"
 
az role assignment create \
  --assignee $CLIENT_ID \
  --role "Reader" \
  --scope "/providers/Microsoft.Management/managementGroups/$MANAGEMENT_GROUP_ID"
 
az role assignment create \
  --assignee $CLIENT_ID \
  --role "Monitoring Reader" \
  --scope "/providers/Microsoft.Management/managementGroups/$MANAGEMENT_GROUP_ID"

Verify Role Assignments

# List all role assignments for the Service Principal
az role assignment list --assignee $CLIENT_ID --output table

Expected output:

Principal                              Role                      Scope
-------------------------------------  ------------------------  ----------------------------------
Verdaro-Cloud-Connector                Cost Management Reader    /subscriptions/xxx
Verdaro-Cloud-Connector                Reader                    /subscriptions/xxx
Verdaro-Cloud-Connector                Monitoring Reader         /subscriptions/xxx

Security Best Practices

  1. Rotate secrets regularly - Set calendar reminders before expiry
  2. Use short-lived secrets - 1-2 year expiry maximum
  3. Principle of least privilege - Only assign roles to subscriptions you need to monitor
  4. Audit access - Review role assignments quarterly
  5. Store secrets securely - Never commit to source control

Note: Role assignments can take 5-10 minutes to propagate. If Verdaro's "Test Connection" fails immediately after setup, wait a few minutes and try again.