Skip to content

Commit 4d79c04

Browse files
committed
New doc: Configure cross-tenant workload identity on AKS
1 parent b7decdc commit 4d79c04

File tree

2 files changed

+266
-0
lines changed

2 files changed

+266
-0
lines changed

articles/aks/TOC.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@
479479
href: workload-identity-overview.md
480480
- name: Deploy and configure workload identity for a cluster
481481
href: workload-identity-deploy-cluster.md
482+
- name: Configure cross-tenant workload identity
483+
href: workload-identity-cross-tenant.md
482484
- name: Migrate your app from pod identity to workload identity
483485
href: workload-identity-migrate-from-pod-identity.md
484486
- name: Microsoft Entra pod identity
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
---
2+
title: Configure cross-tenant workload identity on Azure Kubernetes Service (AKS)
3+
description: Learn how to configure cross-tenant workload identity on Azure Kubernetes Service (AKS).
4+
author: schaffererin
5+
ms.topic: article
6+
ms.subservice: aks-security
7+
ms.date: 06/11/2024
8+
ms.author: schaffererin
9+
---
10+
11+
# Configure cross-tenant workload identity on Azure Kubernetes Service (AKS)
12+
13+
In this article, you learn how to configure cross-tenant workload identity on Azure Kubernetes Service (AKS). Cross-tenant workload identity allows you to access resources in another tenant from your AKS cluster.
14+
15+
For more information on workload identity, see the [Workload identity overview][workload-identity-overview].
16+
17+
## Prerequisites
18+
19+
* ***Two Azure subscriptions***, each in a separate tenant. In this article, we refer to these as *Tenant A* and *Tenant B*.
20+
* Azure CLI installed on your local machine. If you don't have the Azure CLI installed, see [Install the Azure CLI][install-azure-cli].
21+
* X
22+
* Y
23+
* Z
24+
25+
## Configure resources in Tenant A
26+
27+
In *Tenant A*, you create an AKS cluster with workload identity and OIDC issuer enabled. You use this cluster to deploy an application that attempts to access resources in *Tenant B*.
28+
29+
1. Log in to your *Tenant A* subscription using the [`az account set`][az-account-set] command.
30+
31+
```azurecli-interactive
32+
# Set environment variable
33+
TENANT_A_SUBSCRIPTION_ID=<subscription-id>
34+
35+
# Log in to your Tenant A subscription
36+
az account set --subscription $TENANT_A_SUBSCRIPTION_ID
37+
```
38+
39+
2. Create a resource group in *Tenant A* to host the AKS cluster using the [`az group create`][az-group-create] command.
40+
41+
```azurecli-interactive
42+
# Set environment variables
43+
RESOURCE_GROUP=<resource-group-name>
44+
LOCATION=<location>
45+
46+
# Create a resource group
47+
az group create --name $RESOURCE_GROUP --location $LOCATION
48+
```
49+
50+
3. Create an AKS cluster in *Tenant A* with workload identity and OIDC issuer enabled using the [`az aks create`][az-aks-create] command.
51+
52+
```azurecli-interactive
53+
# Set environment variables
54+
CLUSTER_NAME=<cluster-name>
55+
56+
# Create an AKS cluster
57+
az aks create --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --enable-oidc-issuer --enable-workload-identity --generate-ssh-keys
58+
```
59+
60+
4. Get the OIDC issuer URL from the cluster in *Tenant A* using the [`az aks show`][az-aks-show] command.
61+
62+
```azurecli-interactive
63+
OIDC_ISSUER_URL=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" --output tsv)
64+
```
65+
66+
## Configure resources in Tenant B
67+
68+
In *Tenant B*, you create a managed identity, assign it permissions to read subscription information, and establish the trust between the managed identity and the AKS cluster in *Tenant A*.
69+
70+
1. Log in to your *Tenant B* subscription using the [`az account set`][az-account-set] command.
71+
72+
```azurecli-interactive
73+
# Set environment variable
74+
TENANT_B_SUBSCRIPTION_ID=<subscription-id>
75+
76+
# Log in to your Tenant B subscription
77+
az account set --subscription $TENANT_B_SUBSCRIPTION_ID
78+
```
79+
80+
2. Create a resource group in *Tenant B* to host the managed identity using the [`az group create`][az-group-create] command.
81+
82+
```azurecli-interactive
83+
# Set environment variables
84+
RESOURCE_GROUP=<resource-group-name>
85+
LOCATION=<location>
86+
87+
# Create a resource group
88+
az group create --name $RESOURCE_GROUP --location $LOCATION
89+
```
90+
91+
3. Create a user-assigned managed identity in *Tenant B* using the [`az identity create`][az-identity-create] command.
92+
93+
```azurecli-interactive
94+
# Set environment variable
95+
IDENTITY_NAME=<identity-name>
96+
97+
# Create a user-assigned managed identity
98+
az identity create --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME
99+
```
100+
101+
4. Get the client ID of the managed identity in *Tenant B* using the [`az identity show`][az-identity-show] command.
102+
103+
```azurecli-interactive
104+
CLIENT_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME --query clientId --output tsv)
105+
```
106+
107+
5. Get the principal ID of the managed identity in *Tenant B* using the [`az identity show`][az-identity-show] command.
108+
109+
```azurecli-interactive
110+
PRINCIPAL_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME --query principalId --output tsv)
111+
```
112+
113+
6. Assign the managed identity in *Tenant B* permissions to read subscription information using the [`az role assignment create`][az-role-assignment-create] command.
114+
115+
```azurecli-interactive
116+
az role assignment create --role "Reader" --assignee $PRINCIPAL_ID --scope /subscriptions/$TENANT_A_SUBSCRIPTION_ID
117+
```
118+
119+
## Establish trust between AKS cluster and managed identity
120+
121+
In this section, you create the federated identity credential needed to establish trust between the AKS cluster in *Tenant A* and the managed identity in *Tenant B*. You use the OIDC issuer URL from the AKS cluster in *Tenant A* and the name of the managed identity in *Tenant B*.
122+
123+
* Create a federated identity credential using the [`az aks federated-identity add`][az-aks-federated-identity-add] command.
124+
125+
```azurecli-interactive
126+
az identity federated-credential create --name $FEDERATED_CREDENTIAL_NAME --identity-name $IDENTITY_NAME --resource-group $RESOURCE_GROUP --issuer $OIDC_ISSUER_URL --subject system:serviceaccount:default:wi-demo-account
127+
```
128+
129+
`--subject system:serviceaccount:default:wi-demo-account` is the name of the Kubernetes service account that you will create later in *Tenant A*. When your application pod makes authentication requests, this value is sent to Azure AD as the `subject` in the authorization request. Azure AD determines eligibility based on whether this value matches what you set when you created the federated identity credential, so it's important to ensure the value matches.
130+
131+
## Create application to read subscription information
132+
133+
XYZ
134+
135+
## Test application
136+
137+
Before you deploy the application to your AKS cluster, you test the application locally to make sure it works. Since your application will read subscription quota information using [Azure Quota API](/rest/api/reserved-vm-instances/quotaapi), you also need to make sure the `Microsoft.Quota` resource provider is registered in your subscription.
138+
139+
1. Log in to either *Tenant A* or *Tenant B* using the [`az account set`][az-account-set] command.
140+
141+
```azurecli-interactive
142+
az account set --subscription $TENANT_A_SUBSCRIPTION_ID
143+
```
144+
145+
2. Check if the `Microsoft.Quota` resource provider is registered in your subscription using the [`az provider show`][az-provider-show] command.
146+
147+
```azurecli-interactive
148+
az provider show --namespace Microsoft.Quota
149+
```
150+
151+
If the `registrationState` is `Registered`, the resource provider is registered. If it's not registered, you can register it using the [`az provider register`][az-provider-register] command.
152+
153+
```azurecli-interactive
154+
az provider register --namespace Microsoft.Quota
155+
```
156+
157+
3. Once the registration state is `Registered`, you can test the application locally using the following commands:
158+
159+
```azurecli-interactive
160+
XYZ
161+
```
162+
163+
## Deploy application to AKS cluster
164+
165+
Now that you confirmed the application works locally, you can push it to a container registry so that it can be pulled from within your AKS cluster.
166+
167+
1. XYZ
168+
169+
```azurecli-interactive
170+
XYZ
171+
```
172+
173+
2. Get the cluster credentials for the AKS cluster in *Tenant A* using the [`az aks get-credentials`][az-aks-get-credentials] command.
174+
175+
```azurecli-interactive
176+
az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
177+
```
178+
179+
3. Create a new Kubernetes service account in the `default` namespace with the client ID of your managed identity using the `kubectl apply` command. Make sure to replace the `<YOUR_USER_ASSIGNED_MANAGED_IDENTITY>` placeholder with the client ID of your managed identity in *Tenant B*.
180+
181+
```azurecli-interactive
182+
kubectl apply -f - <<EOF
183+
apiVersion: v1
184+
kind: ServiceAccount
185+
metadata:
186+
annotations:
187+
azure.workload.identity/client-id: <YOUR_USER_ASSIGNED_MANAGED_IDENTITY_CLIENT_ID>
188+
name: wi-demo-account
189+
namespace: default
190+
EOF
191+
```
192+
193+
4. Create a new pod in the `default` namespace with the image name, the *Tenant B* tenant ID, and the *Tenant B* subscription ID using the `kubectl apply` command. Make sure to replace the placeholders with your own values.
194+
195+
```azurecli-interactive
196+
kubectl apply -f - <<EOF
197+
apiVersion: v1
198+
kind: Pod
199+
metadata:
200+
name: wi-demo-app
201+
namespace: default
202+
labels:
203+
azure.workload.identity/use: "true"
204+
spec:
205+
serviceAccountName: wi-demo-account
206+
containers:
207+
- name: wi-demo-app
208+
image: <YOUR_IMAGE_NAME>
209+
env:
210+
- name: AZURE_TENANT_ID
211+
value: <TENANT_B_ID>
212+
- name: AZURE_SUBSCRIPTION_ID
213+
value: <TENANT_B_SUBSCRIPTION_ID>
214+
- name: AZURE_REGION
215+
value: eastus
216+
- name: AZURE_RESOURCE_NAME
217+
value: cores
218+
resources: {}
219+
dnsPolicy: ClusterFirst
220+
restartPolicy: Always
221+
EOF
222+
```
223+
224+
5. Verify that the pod is running using the `kubectl get pods` command.
225+
226+
```azurecli-interactive
227+
kubectl get pods
228+
```
229+
230+
6. Check the logs of the pod to see if the application was able to read subscription information using the `kubectl logs` command.
231+
232+
```azurecli-interactive
233+
kubectl logs wi-demo-app
234+
```
235+
236+
Your output should look similar to the following example output:
237+
238+
```output
239+
2023/08/24 17:48:03 clientResponse: {"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/eastus/providers/Microsoft.Quota/quotas/cores","name":"cores","properties":{"isQuotaApplicable":true,"limit":{"limitObjectType":"LimitValue","limitType":"Independent","value":20},"name":{"localizedValue":"Total Regional vCPUs","value":"cores"},"properties":{},"unit":"Count"},"type":"Microsoft.Quota/Quotas"}
240+
2023/08/24 17:48:04 usagesClientResponse: {"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Compute/locations/eastus/providers/Microsoft.Quota/usages/cores","name":"cores","properties":{"isQuotaApplicable":true,"name":{"localizedValue":"Total Regional vCPUs","value":"cores"},"properties":{},"unit":"Count","usages":{}},"type":"Microsoft.Quota/Usages"}
241+
```
242+
243+
## Next steps
244+
245+
In this article, you learned how to configure cross-tenant workload identity on Azure Kubernetes Service (AKS). To learn more about workload identity, see the following articles:
246+
247+
* [Workload identity overview][workload-identity-overview]
248+
* [Configure workload identity on Azure Kubernetes Service (AKS)][configure-workload-identity]
249+
250+
<!-- LINKS -->
251+
[workload-identity-overview]: ./workload-identity-overview.md
252+
[configure-workload-identity]: ./workload-identity-deploy-cluster.md
253+
[install-azure-cli]: /cli/azure/install-azure-cli
254+
[az-account-set]: /cli/azure/account#az_account_set
255+
[az-group-create]: /cli/azure/group#az_group_create
256+
[az-aks-create]: /cli/azure/aks#az_aks_create
257+
[az-aks-show]: /cli/azure/aks#az_aks_show
258+
[az-identity-create]: /cli/azure/identity#az_identity_create
259+
[az-identity-show]: /cli/azure/identity#az_identity_show
260+
[az-role-assignment-create]: /cli/azure/role/assignment#az_role_assignment_create
261+
[az-aks-federated-identity-add]: /cli/azure/aks/federated-identity#az_aks_federated_identity_add
262+
[az-provider-show]: /cli/azure/provider#az_provider_show
263+
[az-provider-register]: /cli/azure/provider#az_provider_register
264+
[az-aks-get-credentials]: /cli/azure/aks#az_aks_get_credentials

0 commit comments

Comments
 (0)