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:
| Role | Scope | Purpose |
|---|---|---|
| Cost Management Reader | Subscription | Read cost exports and billing data |
| Reader | Subscription | Query Azure Resource Graph for inventory sync |
| Monitoring Reader | Subscription | Collect metrics from Azure Monitor |
| Storage Blob Data Reader | Storage Account | Download 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"
doneManagement 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 tableExpected output:
Principal Role Scope
------------------------------------- ------------------------ ----------------------------------
Verdaro-Cloud-Connector Cost Management Reader /subscriptions/xxx
Verdaro-Cloud-Connector Reader /subscriptions/xxx
Verdaro-Cloud-Connector Monitoring Reader /subscriptions/xxxSecurity Best Practices
- Rotate secrets regularly - Set calendar reminders before expiry
- Use short-lived secrets - 1-2 year expiry maximum
- Principle of least privilege - Only assign roles to subscriptions you need to monitor
- Audit access - Review role assignments quarterly
- 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.