Action: Configure Identity
Use this action to add passwordless Azure access to a workload.
Step 1 - identify the runtime and target operation
Capture these values before writing code or assigning roles:
runtime="container-app" # app-service | function | container-app | vm | aks | azure-devops | github-actions
operation="read-key-vault-secret"
resource_scope="/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault>"
environment_name="prod"Step 2 - enable or create the identity
System-assigned identity
# App Service
az webapp identity assign --name "$app_name" --resource-group "$resource_group_name"
# Function App
az functionapp identity assign --name "$app_name" --resource-group "$resource_group_name"
# Container App
az containerapp identity assign \
--name "$app_name" \
--resource-group "$resource_group_name" \
--system-assignedUser-assigned identity
az identity create \
--name "id-${service_name}-${environment_name}" \
--resource-group "$identity_resource_group_name" \
--location "$location"
az containerapp identity assign \
--name "$app_name" \
--resource-group "$resource_group_name" \
--user-assigned "/subscriptions/$subscription_id/resourceGroups/$identity_resource_group_name/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-${service_name}-${environment_name}"Set the client ID when the runtime has more than one possible identity:
client_id=$(az identity show \
--name "id-${service_name}-${environment_name}" \
--resource-group "$identity_resource_group_name" \
--query clientId -o tsv)
az containerapp update \
--name "$app_name" \
--resource-group "$resource_group_name" \
--set-env-vars "AZURE_CLIENT_ID=$client_id"Step 3 - assign least-privilege permissions
principal_id=$(az containerapp show \
--name "$app_name" \
--resource-group "$resource_group_name" \
--query identity.principalId -o tsv)
az role assignment create \
--assignee-object-id "$principal_id" \
--assignee-principal-type ServicePrincipal \
--role "Key Vault Secrets User" \
--scope "$resource_scope"Use service-native permissions when Azure RBAC is not the data-plane model. For Azure SQL and Cosmos DB, see:
references/azure-sql.mdreferences/cosmos-db.md
Step 4 - disable local authentication
Prefer IaC at resource creation. For existing resources, use CLI remediation carefully after confirming no active consumer still needs local authentication.
# Storage account shared key
az storage account update \
--name "$storage_account_name" \
--resource-group "$resource_group_name" \
--allow-shared-key-access false
# Service Bus namespace
az servicebus namespace update \
--name "$service_bus_namespace" \
--resource-group "$resource_group_name" \
--disable-local-auth true
# Event Hubs namespace
az eventhubs namespace update \
--name "$event_hubs_namespace" \
--resource-group "$resource_group_name" \
--disable-local-auth true
# Cosmos DB account: disable key/local authentication
az resource update \
--resource-group "$resource_group_name" \
--name "$cosmos_account_name" \
--resource-type "Microsoft.DocumentDB/databaseAccounts" \
--set properties.disableLocalAuth=trueStep 5 - update application code
Replace credential-bearing connection strings with resource URI + credential.
// Bad: embeds a storage account key.
// var client = new BlobServiceClient("DefaultEndpointsProtocol=https;AccountKey=...");
using Azure.Identity;
using Azure.Storage.Blobs;
var credential = new ManagedIdentityCredential();
var client = new BlobServiceClient(
new Uri("https://<account>.blob.core.windows.net"),
credential);Step 6 - verify
az role assignment list \
--assignee "$principal_id" \
--all \
--query "[].{role:roleDefinitionName, scope:scope}" \
-o table
# Secret/key paths should fail after local auth is disabled.
./scripts/scan-secrets.sh .Completion criteria
- Effective identity is known and captured in deployment notes.
- Least-privilege role or service-native permission is assigned at the smallest practical scope.
- Local authentication is disabled where supported and safe.
- Application code uses a deterministic credential in production.
- No credential-bearing connection strings, secrets, or SAS tokens remain.
- Verification proves identity-based access works and secret-based access fails.