How to configure Azure credentials using workload identity
❗️ Preview Release: This documentation covers a preview of Radius which uses different Resource Types from the current release. Enable it by passing the --preview to the Radius CLI or settingRADIUS_PREVIEW=true.
Azure workload identity lets Radius deploy and connect to Azure resources without storing secrets by federating Kubernetes service account tokens with an Entra ID application. This guide sets up workload identity and registers it as an Azure credential in the Radius control plane.
Before you begin
Before configuring workload identity, verify that:
- A supported Kubernetes cluster with its OIDC issuer URL is available. See the AKS example.
- Azure AD Workload Identity is installed in the cluster, including the Mutating Admission Webhook.
Step 1: Set up Azure workload identity
To authorize Radius to connect to Azure using workload identity, set up an Entra ID application with access to your resource group. Using the OIDC issuer for your Kubernetes cluster, create one federated credential for each Radius service (applications-rp, bicep-de, ucp, and dynamic-rp) in the radius-system namespace.
The following script creates an Entra ID application and the federated credentials Radius needs to authenticate with Azure using workload identity:
if [ "$#" -ne 4 ]; then
echo "Usage: $0 <K8S_CLUSTER_NAME> <AZURE_RESOURCE_GROUP> <AZURE_SUBSCRIPTION_ID> <OIDC_ISSUER_URL>"
exit 1
fi
export K8S_CLUSTER_NAME=$1
export AZURE_RESOURCE_GROUP=$2
export AZURE_SUBSCRIPTION_ID=$3
export SERVICE_ACCOUNT_ISSUER=$4
# Create the Entra ID Application
export APPLICATION_NAME="${K8S_CLUSTER_NAME}-radius-app"
az ad app create --display-name "${APPLICATION_NAME}"
# Get the client ID and object ID of the application
export APPLICATION_CLIENT_ID="$(az ad app list --display-name "${APPLICATION_NAME}" --query [].appId -o tsv)"
export APPLICATION_OBJECT_ID="$(az ad app show --id "${APPLICATION_CLIENT_ID}" --query id -otsv)"
# Create the applications-rp federated credential for the application
cat <<EOF > params-applications-rp.json
{
"name": "radius-applications-rp",
"issuer": "${SERVICE_ACCOUNT_ISSUER}",
"subject": "system:serviceaccount:radius-system:applications-rp",
"description": "Kubernetes service account federated credential for applications-rp",
"audiences": [
"api://AzureADTokenExchange"
]
}
EOF
az ad app federated-credential create --id "${APPLICATION_OBJECT_ID}" --parameters @params-applications-rp.json
# Create the bicep-de federated credential for the application
cat <<EOF > params-bicep-de.json
{
"name": "radius-bicep-de",
"issuer": "${SERVICE_ACCOUNT_ISSUER}",
"subject": "system:serviceaccount:radius-system:bicep-de",
"description": "Kubernetes service account federated credential for bicep-de",
"audiences": [
"api://AzureADTokenExchange"
]
}
EOF
az ad app federated-credential create --id "${APPLICATION_OBJECT_ID}" --parameters @params-bicep-de.json
# Create the ucp federated credential for the application
cat <<EOF > params-ucp.json
{
"name": "radius-ucp",
"issuer": "${SERVICE_ACCOUNT_ISSUER}",
"subject": "system:serviceaccount:radius-system:ucp",
"description": "Kubernetes service account federated credential for ucp",
"audiences": [
"api://AzureADTokenExchange"
]
}
EOF
az ad app federated-credential create --id "${APPLICATION_OBJECT_ID}" --parameters @params-ucp.json
# Create the dynamic-rp federated credential for the application
cat <<EOF > params-dynamic-rp.json
{
"name": "radius-dynamic-rp",
"issuer": "${SERVICE_ACCOUNT_ISSUER}",
"subject": "system:serviceaccount:radius-system:dynamic-rp",
"description": "Kubernetes service account federated credential for dynamic-rp",
"audiences": [
"api://AzureADTokenExchange"
]
}
EOF
az ad app federated-credential create --id "${APPLICATION_OBJECT_ID}" --parameters @params-dynamic-rp.json
# Set the permissions for the application
az ad sp create --id ${APPLICATION_CLIENT_ID}
az role assignment create --assignee "${APPLICATION_CLIENT_ID}" --role "Owner" --scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}/resourceGroups/${AZURE_RESOURCE_GROUP}"
Record the application’s client ID (appId) and tenant ID (tenant).
Step 2a: Interactively via rad initialize
If Radius has not been installed already, rad initialize --full can be used to interactively install Radius and configure Azure workload identity at the same time.
rad initialize --full --preview
Follow the prompts:
- When prompted with “Add cloud providers for cloud resources?”, select Yes.
- Select Azure, then Workload Identity.
- Enter the client ID (
appId) and tenant ID recorded in Step 1. - Enter the Azure subscription ID and resource group to use for the
defaultEnvironment. The resource group must already exist.
Step 2b: Manual configuration
Workload identity must be enabled on the Radius control plane. If Radius has not been installed, enable it by installing Radius with the global.azureWorkloadIdentity.enabled Helm value set to true:
rad install kubernetes --set global.azureWorkloadIdentity.enabled=true
If Radius is already installed, enable workload identity with an upgrade instead of reinstalling. This restarts the Radius control plane pods with the token mounted:
rad upgrade kubernetes --set global.azureWorkloadIdentity.enabled=true
Then create the Azure credential in the Radius control plane with rad credential register azure wi:
rad credential register azure wi --client-id myClientId --tenant-id myTenantId
Radius will use the provided client ID for all interactions with Azure.
Step 3: Update existing Environments
If you have existing Environments, you must also update your Environments with your Azure subscription ID and resource group:
rad environment update myEnvironment \
--azure-subscription-id myAzureSubscriptionId \
--azure-resource-group myAzureResourceGroup \
--preview
This command updates the configuration of an environment for properties that are able to be changed. For more information visit rad environment update.
Next steps
Once AWS or Azure credentials are configured, set up access to the Radius Dashboard.
Next step: How to configure access to the Radius dashboardFeedback
Was this page helpful?
Glad to hear it! Please feel free to star our repo and join our Discord server to stay up to date with the project.
Sorry to hear that. If you would like to also contribute a suggestion visit and tell us how we can improve.