|
| 1 | +--- |
| 2 | +title: Configure Workload Identity on an AKS Edge Essentials cluster (preview) |
| 3 | +description: Learn how to configure an AKS Edge Essentials cluster with workload identity. |
| 4 | +author: sethmanheim |
| 5 | +ms.author: sethm |
| 6 | +ms.topic: how-to |
| 7 | +ms.date: 11/15/2024 |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +# Configure Workload Identity on an AKS Edge Essentials cluster (preview) |
| 12 | + |
| 13 | +Azure Kubernetes Service (AKS) Edge Essentials is an on-premises Kubernetes implementation of Azure Kubernetes Service (AKS) that automates running containerized applications at scale. This article describes how to perform the following tasks: |
| 14 | + |
| 15 | +- Create a Kubernetes service account and bind it to the Azure Managed Identity. |
| 16 | +- Create a federated credential on the managed identity to trust the OIDC issuer. |
| 17 | +- Deploy your application. |
| 18 | +- Example: Grant a pod in the cluster access to secrets in an Azure key vault. |
| 19 | + |
| 20 | +> [!IMPORTANT] |
| 21 | +> These preview features are available on a self-service, opt-in basis. Previews are provided "as is" and "as available," and they're excluded from the service-level agreements and limited warranty. Azure Kubernetes Service Edge Essentials previews are partially covered by customer support on a best-effort basis. |
| 22 | +
|
| 23 | +> [!NOTE] |
| 24 | +> In this public preview, AKS Edge Essentials allows you to enable workload identity during the initial deployment of the Azure IoT Operations quickstart script. This feature is not available for other AKS Edge Essentials scenarios. |
| 25 | +
|
| 26 | +## Prerequisites |
| 27 | + |
| 28 | +Before using workload identity federation for an AKS Edge Essentials cluster, you must deploy the Azure IoT Operation quickstart script as described in [Create and configure an AKS Edge Essentials cluster that can run Azure IoT Operations](aks-edge-howto-deploy-azure-iot.md). The script automatically enables the workload identity federation feature on the AKS Edge Essentials cluster. |
| 29 | + |
| 30 | +After you deploy the AKS Edge Essentials cluster, you can use the following command to check the status of the workload identity extension: |
| 31 | + |
| 32 | +```azurecli |
| 33 | +az connectedk8s show -n $aks_cluster_name -g $resource_group_name |
| 34 | +``` |
| 35 | + |
| 36 | +```output |
| 37 | +# agentState = "Succeeded" |
| 38 | +"agentPublicKeyCertificate": "", |
| 39 | + "agentVersion": "1.21.10", |
| 40 | + "arcAgentProfile": { |
| 41 | + "agentAutoUpgrade": "Enabled", |
| 42 | + "agentErrors": [], |
| 43 | + "agentState": "Succeeded", |
| 44 | + "desiredAgentVersion": "", |
| 45 | + "systemComponents": null |
| 46 | +
|
| 47 | +# oidcIssuerProfile "enabled": true and "issuerUrl" present |
| 48 | +"oidcIssuerProfile": { |
| 49 | + "enabled": true, |
| 50 | + "issuerUrl": "https://oidcdiscovery-{location}-endpoint-1111111111111111.000.azurefd.net/00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111/", |
| 51 | +
|
| 52 | +# workloadIdentity "enabled": true |
| 53 | +"securityProfile": { |
| 54 | + "workloadIdentity": { |
| 55 | + "enabled": true |
| 56 | +``` |
| 57 | + |
| 58 | +In the Azure portal, you can view the `wiextension` extension under the **Properties** section of your Kubernetes cluster. |
| 59 | + |
| 60 | +### Export environment variables |
| 61 | + |
| 62 | +To help simplify the steps to configure the required identities, the following steps define environment variables that are referenced in the examples in this article. Remember to replace the values shown with your own values: |
| 63 | + |
| 64 | +```azurecli |
| 65 | +$AZSubscriptionID = "00000000-0000-0000-0000-000000000000" |
| 66 | +$Location = "westeurope" |
| 67 | +$resource_group_name = "myResourceGroup" |
| 68 | +
|
| 69 | +$aks_cluster_name = "myAKSCluster" |
| 70 | +
|
| 71 | +$SERVICE_ACCOUNT_NAMESPACE = "default" |
| 72 | +$SERVICE_ACCOUNT_NAME = "workload-identity-sa" |
| 73 | +
|
| 74 | +$FedIdCredentialName = "myFedIdentity" |
| 75 | +$MSIName = "myIdentity" |
| 76 | +
|
| 77 | +# Include these variables to access key vault secrets from a pod in the cluster. |
| 78 | +$KVName = "KV-workload-id" |
| 79 | +$KVSecretName= "KV-secret" |
| 80 | +``` |
| 81 | + |
| 82 | +### Save the OIDC issuer URL to an environment variable |
| 83 | + |
| 84 | +To get the OIDC issuer URL and save it to an environment variable, run the following command: |
| 85 | + |
| 86 | +```azurecli |
| 87 | +$SERVICE_ACCOUNT_ISSUER =$(az connectedk8s show --n $aks_cluster_name --resource-group $resource_group_name --query "oidcIssuerProfile.issuerUrl" --output tsv) |
| 88 | +``` |
| 89 | + |
| 90 | +## Step 1: Create a Kubernetes service account and bind it to the Azure Managed Identity |
| 91 | + |
| 92 | +First, call the [az identity create](/cli/azure/identity#az-identity-create) command to create a managed identity: |
| 93 | + |
| 94 | +```azurecli |
| 95 | +az identity create --name $MSIName --resource-group $resource_group_name --location $Location --subscription $AZSubscriptionID |
| 96 | +``` |
| 97 | + |
| 98 | +Next, create variables for the managed identity's client ID: |
| 99 | + |
| 100 | +```azurecli |
| 101 | +$MSIId=$(az identity show --resource-group $resource_group_name --name $MSIName --query 'clientId' --output tsv) |
| 102 | +$MSIPrincipalId=$(az identity show --resource-group $resource_group_name --name $MSIName --query 'principalId' --output tsv) |
| 103 | +``` |
| 104 | + |
| 105 | +### Create a Kubernetes service account |
| 106 | + |
| 107 | +Create a Kubernetes service account and annotate it with the client ID of the managed identity you created in the previous step. Copy and paste the following Azure CLI commands: |
| 108 | + |
| 109 | +```azurecli |
| 110 | +$yaml = @" |
| 111 | +apiVersion: v1 |
| 112 | +kind: ServiceAccount |
| 113 | +metadata: |
| 114 | + annotations: |
| 115 | + azure.workload.identity/client-id: $MSIId |
| 116 | + name: $SERVICE_ACCOUNT_NAME |
| 117 | + namespace: $SERVICE_ACCOUNT_NAMESPACE |
| 118 | +"@ |
| 119 | +
|
| 120 | +# Replace variables within the YAML content |
| 121 | +$yaml = $yaml -replace '\$MSIId', $MSIId ` |
| 122 | + -replace '\$SERVICE_ACCOUNT_NAME', $SERVICE_ACCOUNT_NAME ` |
| 123 | + -replace '\$SERVICE_ACCOUNT_NAMESPACE', $SERVICE_ACCOUNT_NAMESPACE |
| 124 | +
|
| 125 | +# Apply the YAML content to Kubernetes |
| 126 | +$yaml | kubectl apply -f - |
| 127 | +``` |
| 128 | + |
| 129 | +The following output shows the workload identity created successfully: |
| 130 | + |
| 131 | +```output |
| 132 | +serviceaccount/workload-identity-sa created |
| 133 | +``` |
| 134 | + |
| 135 | +## Step 2: Create a federated credential on the managed identity to trust the OIDC issuer |
| 136 | + |
| 137 | +To create the federated identity credential between the managed identity, the service account issuer, and the subject, call the [az identity federated-credential create](/cli/azure/identity/federated-credential#az-identity-federated-credential-create) command. For more information about federated identity credentials in Microsoft Entra, see [Overview of federated identity credentials in Microsoft Entra ID](/cli/azure/identity/federated-credential#az-identity-federated-credential-create). |
| 138 | + |
| 139 | +```azurecli |
| 140 | +# Create a federated credential |
| 141 | +az identity federated-credential create --name $FedIdCredentialName --identity-name $MSIName --resource-group $resource_group_name --issuer $SERVICE_ACCOUNT_ISSUER --subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}" |
| 142 | +
|
| 143 | +# Show the federated credential |
| 144 | +az identity federated-credential show --name $FedIdCredentialName --resource-group $resource_group_name --identity-name $MSIName |
| 145 | +``` |
| 146 | + |
| 147 | +> [!NOTE] |
| 148 | +> After you add a federated identity credential, it takes a few seconds to propagate. Token requests made immediately afterward might fail until the cache refreshes. To prevent this issue, consider adding a brief delay after creating the federated identity credential. |
| 149 | +
|
| 150 | +## Step 3: Deploy your application |
| 151 | + |
| 152 | +When you deploy your application pods, the manifest should reference the service account created in the **Create Kubernetes service account** step. The following manifest shows how to reference the account, specifically the `metadata\namespace` and `spec\serviceAccountName` properties. Make sure to specify an image for `image` and a container name |
| 153 | +for `containerName`: |
| 154 | + |
| 155 | +```azurecli |
| 156 | +$image = "<image>" # Replace <image> with the actual image name |
| 157 | +$containerName = "<containerName>" # Replace <containerName> with the actual container name |
| 158 | +
|
| 159 | +$yaml = @" |
| 160 | +apiVersion: v1 |
| 161 | +kind: Pod |
| 162 | +metadata: |
| 163 | + name: sample-quick-start |
| 164 | + namespace: $SERVICE_ACCOUNT_NAMESPACE |
| 165 | + labels: |
| 166 | + azure.workload.identity/use: "true" # Required. Only pods with this label can use workload identity. |
| 167 | +spec: |
| 168 | + serviceAccountName: $SERVICE_ACCOUNT_NAME |
| 169 | + containers: |
| 170 | + - image: $image |
| 171 | + name: $containerName |
| 172 | +"@ |
| 173 | +
|
| 174 | +# Replace variables within the YAML content |
| 175 | +$yaml = $yaml -replace '\$SERVICE_ACCOUNT_NAMESPACE', $SERVICE_ACCOUNT_NAMESPACE ` |
| 176 | + -replace '\$SERVICE_ACCOUNT_NAME', $SERVICE_ACCOUNT_NAME |
| 177 | +
|
| 178 | +# Apply the YAML configuration |
| 179 | +$yaml | kubectl apply -f - |
| 180 | +``` |
| 181 | + |
| 182 | +> [!IMPORTANT] |
| 183 | +> Ensure that the application pods using workload identity include the label `azure.workload.identity/use: "true"` in the pod spec. Otherwise the pods fail after they restart. |
| 184 | +
|
| 185 | +## Example: Grant permissions to access Azure Key Vault |
| 186 | + |
| 187 | +The instructions in this step describe how to access secrets, keys, or certificates in an Azure key vault from the pod. The examples in this section configure access to secrets in the key vault for the workload identity, but you can perform similar steps to configure access to keys or certificates. |
| 188 | + |
| 189 | +The following example shows how to use the Azure role-based access control (Azure RBAC) permission model to grant the pod access to the key vault. For more information about the Azure RBAC permission model for Azure Key Vault, see [Grant permission to applications to access an Azure key vault using Azure RBAC](/azure/key-vault/general/rbac-guide). |
| 190 | + |
| 191 | +1. Create a key vault with purge protection and RBAC authorization enabled. You can also use an existing key vault if it is configured for both purge protection and RBAC authorization: |
| 192 | + |
| 193 | + ```azurecli |
| 194 | + az keyvault create --name $KVName --resource-group $resource_group_name --location $Location --enable-purge-protection --enable-rbac-authorization |
| 195 | +
|
| 196 | + # retrieve the key vault ID for role assignment |
| 197 | + $KVId=$(az keyvault show --resource-group $resource_group_name --name $KVName --query id --output tsv) |
| 198 | + ``` |
| 199 | + |
| 200 | +1. Assign the RBAC [Key Vault Secrets Officer](/azure/role-based-access-control/built-in-roles/security#key-vault-secrets-officer) role to yourself so that you can create a secret in the new key vault. New role assignments can take up to five minutes to propagate and be updated by the authorization server. |
| 201 | + |
| 202 | + ```azurecli |
| 203 | + az role assignment create --assignee-object-id $MSIPrincipalId --role "Key Vault Secrets Officer" --scope $KVId --assignee-principal-type ServicePrincipal |
| 204 | + ``` |
| 205 | + |
| 206 | +1. Create a secret in the key vault: |
| 207 | + |
| 208 | + ```azurecli |
| 209 | + az keyvault secret set --vault-name $KVName --name $KVSecretName --value "Hello!" |
| 210 | + ``` |
| 211 | + |
| 212 | +1. Assign the [Key Vault Secrets User](/azure/role-based-access-control/built-in-roles/security#key-vault-secrets-user) role to the user-assigned managed identity that you created previously. This step gives the managed identity permission to read secrets from the key vault: |
| 213 | + |
| 214 | + ```azurecli |
| 215 | + az role assignment create --assignee-object-id $MSIPrincipalId --role "Key Vault Secrets User" --scope $KVId --assignee-principal-type ServicePrincipal |
| 216 | + ``` |
| 217 | + |
| 218 | +1. Create an environment variable for the key vault URL: |
| 219 | + |
| 220 | + ```azurecli |
| 221 | + $KVUrl=$(az keyvault show --resource-group $resource_group_name --name $KVName --query properties.vaultUri --output tsv) |
| 222 | + ``` |
| 223 | + |
| 224 | +1. Deploy a pod that references the service account and key vault URL: |
| 225 | + |
| 226 | + ```azurecli |
| 227 | + $yaml = @" |
| 228 | + apiVersion: v1 |
| 229 | + kind: Pod |
| 230 | + metadata: |
| 231 | + name: sample-quick-start |
| 232 | + namespace: $SERVICE_ACCOUNT_NAMESPACE |
| 233 | + labels: |
| 234 | + azure.workload.identity/use: "true" |
| 235 | + spec: |
| 236 | + serviceAccountName: $SERVICE_ACCOUNT_NAME |
| 237 | + containers: |
| 238 | + - image: ghcr.io/azure/azure-workload-identity/msal-go |
| 239 | + name: oidc |
| 240 | + env: |
| 241 | + - name: KEYVAULT_URL |
| 242 | + value: $KVUrl |
| 243 | + - name: SECRET_NAME |
| 244 | + value: $KVSecretName |
| 245 | + nodeSelector: |
| 246 | + kubernetes.io/os: linux |
| 247 | + "@ |
| 248 | +
|
| 249 | + # Replace variables within the YAML content |
| 250 | + $yaml = $yaml -replace '\$SERVICE_ACCOUNT_NAMESPACE', $SERVICE_ACCOUNT_NAMESPACE ` |
| 251 | + -replace '\$SERVICE_ACCOUNT_NAME', $SERVICE_ACCOUNT_NAME ` |
| 252 | + -replace '\$KVUrl', $KVUrl ` |
| 253 | + -replace '\$KVSecretName', $KVSecretName |
| 254 | +
|
| 255 | + # Apply the YAML configuration |
| 256 | + $yaml | kubectl --kubeconfig $aks_cluster_name apply -f - |
| 257 | + ``` |
| 258 | + |
| 259 | +## Next steps |
| 260 | + |
| 261 | +In this article, you configured it to use a workload identity in preparation for application workloads to authenticate with that credential. Now you're ready to deploy your application and configure it to use the workload identity with the latest version of the [Azure Identity client library](/azure/active-directory/develop/reference-v2-libraries). |
0 commit comments