Task 01: Bootstrap
DOCUMENT CATEGORY: Runbook Step SCOPE: CI/CD service principal bootstrap PURPOSE: Create an Entra ID app registration and service principal for CI/CD pipeline authentication
Status: Active Applies To: All Azure Local deployments Last Updated: 2026-03-19
Objective
Create an Entra ID app registration and service principal in the target tenant so CI/CD pipelines can authenticate to Azure and manage resources.
Prerequisites
- Azure CLI installed and authenticated (
az login) - Signed in to the target tenant (verify with
az account show) - Application Administrator or Global Administrator role in Entra ID
- Owner or User Access Administrator on each target subscription
- Target subscription ID(s) available
Variables from variables.yml
| Variable | Config Path | Example |
|---|---|---|
| Tenant ID | azure.tenant_id | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| Target Subscription ID | azure.subscription.id | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
Procedure
Step 1: Create the App Registration and Service Principal
# Set variables
APP_NAME="azurelocal-cicd"
SUBSCRIPTION_IDS=("subscription-id-1" "subscription-id-2")
# Create app registration with a 2-year secret
az ad app create --display-name "$APP_NAME"
APP_ID=$(az ad app list --display-name "$APP_NAME" --query "[0].appId" -o tsv)
# Create service principal
az ad sp create --id "$APP_ID"
# Create client secret (2-year expiry)
SECRET=$(az ad app credential reset --id "$APP_ID" --years 2 --query "password" -o tsv)
# Get tenant ID
TENANT_ID=$(az account show --query "tenantId" -o tsv)
echo "ARM_CLIENT_ID: $APP_ID"
echo "ARM_CLIENT_SECRET: $SECRET"
echo "ARM_TENANT_ID: $TENANT_ID"
Important: Save the
ARM_CLIENT_SECRETimmediately — it cannot be retrieved again.
Step 2: Assign RBAC Roles
Assign roles on each target subscription:
for SUB_ID in "${SUBSCRIPTION_IDS[@]}"; do
# Contributor — manage resources
az role assignment create \
--assignee "$APP_ID" \
--role "Contributor" \
--scope "/subscriptions/$SUB_ID"
# User Access Administrator — manage RBAC assignments
az role assignment create \
--assignee "$APP_ID" \
--role "User Access Administrator" \
--scope "/subscriptions/$SUB_ID"
done
Step 3: Register Providers and Features
for SUB_ID in "${SUBSCRIPTION_IDS[@]}"; do
az account set --subscription "$SUB_ID"
# Register the Compute provider
az provider register --namespace "Microsoft.Compute"
# Enable EncryptionAtHost feature
az feature register \
--namespace "Microsoft.Compute" \
--name "EncryptionAtHost"
done
Step 4: Add API Permissions
# Add Microsoft Graph — RoleManagement.ReadWrite.Directory (Application)
GRAPH_APP_ID="00000003-0000-0000-c000-000000000000"
ROLE_MGMT_ID="9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8"
az ad app permission add \
--id "$APP_ID" \
--api "$GRAPH_APP_ID" \
--api-permissions "$ROLE_MGMT_ID=Role"
Step 5: Grant Admin Consent
Grant admin consent via the Azure Portal or CLI:
- Portal
- Azure CLI
- Navigate to Entra ID → App registrations → azurelocal-cicd
- Select API permissions
- Click Grant admin consent for <tenant>
az ad app permission admin-consent --id "$APP_ID"
Verification
- App registration
azurelocal-cicdexists in Entra ID - Service principal created
-
ContributorandUser Access Administratorroles assigned on all target subscriptions -
Microsoft.Computeprovider registered -
EncryptionAtHostfeature enabled - Admin consent granted for API permissions
- Credentials saved securely (will be stored in CI/CD platform in Task 05)
Troubleshooting
App already exists:
An app registration with the name "azurelocal-cicd" already exists.
→ Delete the existing app registration first: az ad app delete --id <APP_ID>
Insufficient permissions:
Insufficient privileges to complete the operation.
→ Ensure you have Application Administrator role in Entra ID and Owner on the target subscription(s)
Feature registration pending:
Feature "EncryptionAtHost" is in "Registering" state.
→ Wait a few minutes, then check status: az feature show --namespace Microsoft.Compute --name EncryptionAtHost
References
- Register an application with Microsoft Entra ID
- Assign Azure roles using Azure CLI
- Azure CLI — az ad app