How to configure Azure credentials using workload identity

Learn how to configure Azure credentials using workload identity in the Radius control plane

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:

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:

  1. When prompted with “Add cloud providers for cloud resources?”, select Yes.
  2. Select Azure, then Workload Identity.
  3. Enter the client ID (appId) and tenant ID recorded in Step 1.
  4. Enter the Azure subscription ID and resource group to use for the default Environment. 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 dashboard