Skip to main content
Version: 1.0.0

Task 01: Bootstrap

Runbook Azure

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 MASTER REFERENCE: Azure Pipelines Agent Documentation

Status: Active

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

VariableConfig PathExample
Tenant IDazure.tenant_idxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Target Subscription IDazure.subscription.idxxxxxxxx-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_SECRET immediately — 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"

Grant admin consent via the Azure Portal or CLI:

  1. Navigate to Entra IDApp registrationsazurelocal-cicd
  2. Select API permissions
  3. Click Grant admin consent for <tenant>

Verification

  • App registration azurelocal-cicd exists in Entra ID
  • Service principal created
  • Contributor and User Access Administrator roles assigned on all target subscriptions
  • Microsoft.Compute provider registered
  • EncryptionAtHost feature enabled
  • Admin consent granted for API permissions
  • Credentials saved securely (will be stored in CI/CD platform in Task 05)


When to use: Use if running GitHub Actions pipeline.

See the procedure steps above for GitHub-specific configuration.

Toolkit Reference

Scripts for this task are located in the azurelocal-toolkit repository under scripts/deploy/ in the appropriate task folder.


Alternatives

The procedures in this task use the scripted methods shown in the tabs above. Additional deployment methods including Azure CLI and Bash scripts are available in the azurelocal-toolkit repository under scripts/deploy/.

MethodDescription
Azure CLIPowerShell-based Azure CLI scripts for Azure resource operations
BashLinux/macOS compatible shell scripts for pipeline environments
PreviousUpNext
---Phase 01: CI/CD SetupTask 02: Create source control project ->

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


Next Steps

Create Source Control Project


Version Control

VersionDateAuthorChanges
1.0.02025-03-25Azure Local CloudInitial release