Skip to main content

Creating an Azure Service Principal

A Service Principal is an Azure app registration that allows CloudYali to securely access your cost data with read-only permissions. This guide provides step-by-step instructions for creating a Service Principal for your Azure account type.


Step 1: Create App Registration

  1. Go to Azure Portal
  2. Navigate to Azure Active DirectoryApp registrations
  3. Click + New registration
  4. Enter name: CloudYali-Billing
  5. Click Register

Step 2: Get Credentials

  1. Copy Application (client) ID from the Overview page
  2. Copy Directory (tenant) ID from the Overview page
  3. Go to Certificates & secrets+ New client secret
  4. Description: CloudYali Integration
  5. Expiration: 12 months
  6. Click Add and copy the secret Value (shown once only!)

Step 3: Assign Permissions

Choose your account type below and follow the appropriate steps:

For PAYG Subscriptions:

  1. Go to your SubscriptionAccess control (IAM)
  2. Click + AddAdd role assignment
  3. Select Cost Management Reader role (search for "Cost Management Reader")
  4. Assign to CloudYali-Billing
  5. Click Review + assign

Also assign Storage access:

  1. Go to your Storage AccountAccess control (IAM)
  2. Click + AddAdd role assignment
  3. Select Storage Blob Data Reader role
  4. Assign to CloudYali-Billing
  5. Click Review + assign

For MCA Billing Accounts:

⚠️ Prerequisite: Ensure "Azure charges" is set to "Yes"

  • Go to Cost Management + Billing → Billing account properties
  • Verify "Azure charges" is enabled

Assign Cost Management Role:

  1. Go to Cost Management + BillingBilling account properties
  2. Go to Billing accountAccess control (IAM)
  3. Click + AddAdd role assignment
  4. Select Billing Account Reader role
  5. Assign to CloudYali-Billing
  6. Click Review + assign

Assign Storage Role:

  1. Go to your Storage AccountAccess control (IAM)
  2. Click + AddAdd role assignment
  3. Select Storage Blob Data Reader role
  4. Assign to CloudYali-Billing
  5. Click Review + assign

For EA Enrollments:

⚠️ Prerequisite: Enterprise Admin must enable "Account Owner (AO) view charges"

  • Contact your Enterprise Admin to enable this at enrollment level

Assign Cost Management Role:

  1. Go to your Management Group or EnrollmentAccess control (IAM)
  2. Click + AddAdd role assignment
  3. Select Cost Management Reader role (or Enrollment Reader for enrollment scope)
  4. Assign to CloudYali-Billing
  5. Click Review + assign

Assign Storage Role:

  1. Go to your Storage AccountAccess control (IAM)
  2. Click + AddAdd role assignment
  3. Select Storage Blob Data Reader role
  4. Assign to CloudYali-Billing
  5. Click Review + assign

Save Your Credentials

Save these credentials - you'll need them in CloudYali:

  • ✅ Application (Client) ID
  • ✅ Directory (Tenant) ID
  • ✅ Client Secret
  • ✅ Subscription ID (for PAYG/EA)

Option B: Using Azure CLI

For Pay-as-You-Go (PAYG):

# Login to Azure
az login

# Get your subscription ID
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
echo "Subscription ID: $SUBSCRIPTION_ID"

# Create Service Principal with minimal Cost Management permissions
az ad sp create-for-rbac \
--name "CloudYali-Billing" \
--role "Cost Management Reader" \
--scopes /subscriptions/$SUBSCRIPTION_ID

# Save the output:
# {
# "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", ← Client ID
# "password": "zzzz...", ← Client Secret
# "tenant": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" ← Tenant ID
# }

Also assign Storage access:

STORAGE_ACCOUNT_NAME="your-storage-account-name"
RESOURCE_GROUP="your-resource-group"

az role assignment create \
--assignee "CloudYali-Billing" \
--role "Storage Blob Data Reader" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"

For Microsoft Customer Agreement (MCA):

⚠️ Prerequisites:

  • Your billing account must have "Azure charges" setting enabled
  • Go to Azure Portal → Cost Management + Billing → Billing account properties
  • Verify "Azure charges" is set to "Yes"
az login

# Fetch your billing account
BILLING_ACCOUNT=$(az billing account list --query "[0].name" -o tsv)
if [ -z "$BILLING_ACCOUNT" ]; then
echo "Error: No billing accounts found."
exit 1
fi

# Create Service Principal with minimal Billing Account permissions
az ad sp create-for-rbac \
--name "CloudYali-Billing" \
--role "Billing Account Reader" \
--scopes /providers/Microsoft.Billing/billingAccounts/$BILLING_ACCOUNT

# Also assign Storage access (replace with your details)
STORAGE_ACCOUNT_NAME="your-storage-account-name"
RESOURCE_GROUP="your-resource-group"

az role assignment create \
--assignee "CloudYali-Billing" \
--role "Storage Blob Data Reader" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"

For Enterprise Agreement (EA):

⚠️ Prerequisites:

  • Your Enterprise Admin must enable "Account Owner (AO) view charges" at enrollment level
  • Contact your Enterprise Admin to enable this setting if needed
az login

# Option 1: Management Group Scope (for multi-subscription EA - RECOMMENDED)
MANAGEMENT_GROUP_ID="your-mg-id" # Replace with your Management Group ID

az ad sp create-for-rbac \
--name "CloudYali-Billing" \
--role "Cost Management Reader" \
--scopes /providers/Microsoft.Management/managementGroups/$MANAGEMENT_GROUP_ID

# Option 2: Enrollment Scope (for single enrollment)
# ENROLLMENT_ID=$(az billing account list --query "[0].name" -o tsv)
# az ad sp create-for-rbac \
# --name "CloudYali-Billing" \
# --role "Enrollment Reader" \
# --scopes /providers/Microsoft.Billing/billingAccounts/$ENROLLMENT_ID

# Also assign Storage access
STORAGE_ACCOUNT_NAME="your-storage-account-name"
RESOURCE_GROUP="your-resource-group"
SUBSCRIPTION_ID=$(az account show --query id -o tsv)

az role assignment create \
--assignee "CloudYali-Billing" \
--role "Storage Blob Data Reader" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"

Important Notes

Role Propagation Delay

⏱️ After assigning roles, wait 5-10 minutes for Azure to propagate the permissions before testing the connection. This is normal Azure RBAC behavior.

Minimal Permissions Principle

CloudYali uses only the minimal required roles:

  • PAYG: Cost Management Reader (cost data only, no resource access)
  • MCA: Billing Account Reader (billing data only)
  • EA: Cost Management Reader or Enrollment Reader (cost data only)
  • All: Storage Blob Data Reader (read-only access to exported files)

Security Best Practices

  • ✅ Service Principal credentials are encrypted with AES-256
  • ✅ Stored in AWS Secrets Manager (not in application database)
  • ✅ Read-only permissions only (never WRITE access)
  • ✅ Separate credentials for each customer/account

Troubleshooting

"Service Principal Creation Failed"

Solution:

  1. Ensure you have Owner or Contributor role on the subscription
  2. Verify Azure CLI is up to date: az upgrade
  3. Try creating the role in the Azure Portal instead

"Role Assignment Failed"

Solution:

  1. Verify the Service Principal exists: az ad sp show --id {client-id}
  2. Ensure you have permissions to assign roles
  3. Wait 5-10 minutes for role propagation
  4. Try assigning through Azure Portal if CLI fails

"Cannot Find Billing Account"

For MCA:

  1. Verify "Azure charges" is enabled in Cost Management + Billing
  2. Ensure you're looking at the correct billing account
  3. Contact your billing account owner if needed

For EA:

  1. Contact your Enterprise Admin to verify enrollment access
  2. Ensure "Account Owner view charges" is enabled

Next Steps

Once you've created the Service Principal and assigned roles:

  1. ✅ Have credentials saved (Client ID, Tenant ID, Client Secret, Subscription ID)
  2. ✅ Wait 5-10 minutes for role propagation
  3. ➡️ Continue to Configuring Cost Management Exports