Manual Service Principal Setup - Azure CLI Commands
Quick reference for manually creating a service principal for Docker development.
Prerequisites
- Azure CLI installed and logged in (
az login) - Contributor + User Access Administrator role on subscription
- Know your resource group and AI Services resource names
Step 1: Set Variables
# Your Azure resource names
RESOURCE_GROUP="ldfdev-rg" # Your resource group name
AI_RESOURCE_NAME="ldfdev-ai" # Your AI Services resource name
SP_NAME="loan-defenders-docker-dev" # Service principal name
# Get subscription ID (automatic)
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
Step 2: Verify Resources Exist
# Verify resource group
az group show --name "$RESOURCE_GROUP"
# Verify AI Services resource
az cognitiveservices account show \
--name "$AI_RESOURCE_NAME" \
--resource-group "$RESOURCE_GROUP"
Step 3: Create Service Principal with Role Assignment
# Create service principal with Cognitive Services OpenAI User role
# Scoped to specific AI Services resource only (least privilege)
az ad sp create-for-rbac \
--name "$SP_NAME" \
--role "Cognitive Services OpenAI User" \
--scopes "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.CognitiveServices/accounts/$AI_RESOURCE_NAME" \
--query "{appId: appId, password: password, tenant: tenant}" \
-o json
Output will show:
{
"appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
⚠️ IMPORTANT: Save these values immediately - the password cannot be retrieved later!
Step 4: Verify Role Assignment
# Get the client ID from previous step
CLIENT_ID="<appId from previous command>"
# Verify role assignment was created
az role assignment list \
--assignee "$CLIENT_ID" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.CognitiveServices/accounts/$AI_RESOURCE_NAME" \
--query "[].{Role:roleDefinitionName, Scope:scope}" \
-o table
Expected output:
Role Scope
-------------------------------- ----------------------------------------------------------------
Cognitive Services OpenAI User /subscriptions/.../accounts/ldfdev-ai
Step 5: Add to .env File
Add these credentials to your .env file in the repository root:
# ═══════════════════════════════════════════════════════════════════════════
# AZURE AUTHENTICATION - Service Principal for Docker
# ═══════════════════════════════════════════════════════════════════════════
AZURE_TENANT_ID=<tenant from step 3>
AZURE_CLIENT_ID=<appId from step 3>
AZURE_CLIENT_SECRET=<password from step 3>
Troubleshooting
Service Principal Already Exists
If you get "service principal already exists" error:
# Delete existing service principal
az ad sp delete --id $(az ad sp list --display-name "$SP_NAME" --query '[0].appId' -o tsv)
# Then re-run Step 3
Insufficient Permissions Error
You need one of these role combinations:
Option 1: Owner role
az role assignment create \
--assignee "<your-user-email>" \
--role "Owner" \
--scope "/subscriptions/$SUBSCRIPTION_ID"
Option 2: Contributor + User Access Administrator
az role assignment create \
--assignee "<your-user-email>" \
--role "Contributor" \
--scope "/subscriptions/$SUBSCRIPTION_ID"
az role assignment create \
--assignee "<your-user-email>" \
--role "User Access Administrator" \
--scope "/subscriptions/$SUBSCRIPTION_ID"
Option 3: Application Administrator (Azure AD)
# Must be granted via Azure Portal:
# Azure AD → Roles and administrators → Application Administrator → Add assignment
Check Current Permissions
# Check your role assignments
az role assignment list \
--assignee "$(az account show --query user.name -o tsv)" \
--resource-group "$RESOURCE_GROUP" \
--output table
Complete Example (Copy-Paste)
Replace the resource names and run all commands:
# 1. Set variables
RESOURCE_GROUP="ldfdev-rg"
AI_RESOURCE_NAME="ldfdev-ai"
SP_NAME="loan-defenders-docker-dev"
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
# 2. Verify resources
az group show --name "$RESOURCE_GROUP"
az cognitiveservices account show --name "$AI_RESOURCE_NAME" --resource-group "$RESOURCE_GROUP"
# 3. Create service principal (save the output!)
az ad sp create-for-rbac \
--name "$SP_NAME" \
--role "Cognitive Services OpenAI User" \
--scopes "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.CognitiveServices/accounts/$AI_RESOURCE_NAME" \
--query "{appId: appId, password: password, tenant: tenant}" \
-o json
# 4. Verify role assignment (replace CLIENT_ID with appId from step 3)
CLIENT_ID="<replace-with-appId>"
az role assignment list \
--assignee "$CLIENT_ID" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.CognitiveServices/accounts/$AI_RESOURCE_NAME" \
--query "[].{Role:roleDefinitionName, Scope:scope}" \
-o table
# 5. Add to .env file (replace with actual values from step 3)
echo "AZURE_TENANT_ID=<tenant>" >> .env
echo "AZURE_CLIENT_ID=<appId>" >> .env
echo "AZURE_CLIENT_SECRET=<password>" >> .env
Security Notes
✅ Least Privilege: Service principal has read-only inference access ✅ Scoped: Limited to single AI Services resource only ⚠️ Rotate: Change credentials every 90 days minimum ⚠️ Production: Use Managed Identity instead of service principals ⚠️ Never Commit: .env is in .gitignore - keep credentials out of source control
Alternative: Use Automated Script
For a fully automated setup with validation and error handling:
See: create-service-principal.sh
Last Updated: 2025-01-15