Skip to content

Commit 6bec31b

Browse files
committed
Update with new sample app
1 parent 4d79c04 commit 6bec31b

File tree

1 file changed

+156
-85
lines changed

1 file changed

+156
-85
lines changed

articles/aks/workload-identity-cross-tenant.md

Lines changed: 156 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,35 @@ ms.author: schaffererin
1010

1111
# Configure cross-tenant workload identity on Azure Kubernetes Service (AKS)
1212

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.
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. In this example, you will create an Azure Service Bus in one tenant and send messages to it from a workload running in an AKS cluster in another tenant.
1414

1515
For more information on workload identity, see the [Workload identity overview][workload-identity-overview].
1616

1717
## Prerequisites
1818

1919
* ***Two Azure subscriptions***, each in a separate tenant. In this article, we refer to these as *Tenant A* and *Tenant B*.
2020
* 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
21+
* Bash shell environment. This article uses Bash shell syntax.
22+
23+
In order to complete the steps in this article, you need to have the following information:
24+
25+
* *Tenant A* tenant ID
26+
* *Tenant A* subscription ID
27+
* *Tenant B* tenant ID
28+
* *Tenant B* subscription ID
2429

2530
## Configure resources in Tenant A
2631

2732
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*.
2833

29-
1. Log in to your *Tenant A* subscription using the [`az account set`][az-account-set] command.
34+
1. Log into your *Tenant A* subscription using the [`az login`][az-login-interactively] command and pass in the tenant ID of *Tenant A*.
35+
36+
```azurecli-interactive
37+
TENANT_A_ID=<tenant-id>
38+
az login --tenant $TENANT_A_ID
39+
```
40+
41+
1. Ensure you are working with the correct subscription in *Tenant A* by using the [`az account set`][az-account-set] command.
3042
3143
```azurecli-interactive
3244
# Set environment variable
@@ -36,7 +48,7 @@ In *Tenant A*, you create an AKS cluster with workload identity and OIDC issuer
3648
az account set --subscription $TENANT_A_SUBSCRIPTION_ID
3749
```
3850
39-
2. Create a resource group in *Tenant A* to host the AKS cluster using the [`az group create`][az-group-create] command.
51+
1. Create a resource group in *Tenant A* to host the AKS cluster using the [`az group create`][az-group-create] command.
4052
4153
```azurecli-interactive
4254
# Set environment variables
@@ -47,27 +59,45 @@ In *Tenant A*, you create an AKS cluster with workload identity and OIDC issuer
4759
az group create --name $RESOURCE_GROUP --location $LOCATION
4860
```
4961
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.
62+
1. Create an AKS cluster in *Tenant A* with workload identity and OIDC issuer enabled using the [`az aks create`][az-aks-create] command.
5163
5264
```azurecli-interactive
5365
# Set environment variables
5466
CLUSTER_NAME=<cluster-name>
5567
5668
# Create an AKS cluster
57-
az aks create --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --enable-oidc-issuer --enable-workload-identity --generate-ssh-keys
69+
az aks create \
70+
--resource-group $RESOURCE_GROUP \
71+
--name $CLUSTER_NAME \
72+
--enable-oidc-issuer \
73+
--enable-workload-identity \
74+
--generate-ssh-keys
5875
```
5976
60-
4. Get the OIDC issuer URL from the cluster in *Tenant A* using the [`az aks show`][az-aks-show] command.
77+
1. Get the OIDC issuer URL from the cluster in *Tenant A* using the [`az aks show`][az-aks-show] command.
6178
6279
```azurecli-interactive
6380
OIDC_ISSUER_URL=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" --output tsv)
6481
```
6582
6683
## Configure resources in Tenant B
6784
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*.
85+
In *Tenant B*, you create an Azure Service Bus, a managed identity and assign it permissions to read and write messages to the service bus, and establish the trust between the managed identity and the AKS cluster in *Tenant A*.
86+
87+
1. Log out of your *Tenant A* subscription using the [`az logout`][az-logout] command.
88+
89+
```azurecli-interactive
90+
az logout
91+
```
92+
93+
1. Log into your *Tenant B* subscription using the [`az login`][az-login-interactively] command and pass in the tenant ID of *Tenant B*.
94+
95+
```azurecli-interactive
96+
TENANT_B_ID=<tenant-id>
97+
az login --tenant $TENANT_B_ID
98+
```
6999
70-
1. Log in to your *Tenant B* subscription using the [`az account set`][az-account-set] command.
100+
1. Ensure you are working with the correct subscription in *Tenant A* by using the [`az account set`][az-account-set] command.
71101
72102
```azurecli-interactive
73103
# Set environment variable
@@ -77,7 +107,7 @@ In *Tenant B*, you create a managed identity, assign it permissions to read subs
77107
az account set --subscription $TENANT_B_SUBSCRIPTION_ID
78108
```
79109
80-
2. Create a resource group in *Tenant B* to host the managed identity using the [`az group create`][az-group-create] command.
110+
1. Create a resource group in *Tenant B* to host the managed identity using the [`az group create`][az-group-create] command.
81111
82112
```azurecli-interactive
83113
# Set environment variables
@@ -87,33 +117,75 @@ In *Tenant B*, you create a managed identity, assign it permissions to read subs
87117
# Create a resource group
88118
az group create --name $RESOURCE_GROUP --location $LOCATION
89119
```
120+
1. Create a service bus and queue in *Tenant B* using the [`az servicebus namespace create`][az-servicebus-namespace-create] and [`az servicebus queue create`][az-servicebus-queue-create] commands.
90121
91-
3. Create a user-assigned managed identity in *Tenant B* using the [`az identity create`][az-identity-create] command.
122+
```azurecli-interactive
123+
# Set a unique name for the servicebus
124+
SERVICEBUS_NAME=sb-crosstenantdemo-$RANDOM
125+
126+
# Create a new service bus namespace and and return the service bus hostname
127+
SERVICEBUS_HOSTNAME=$(az servicebus namespace create \
128+
--name $SERVICEBUS_NAME \
129+
--resource-group $RESOURCE_GROUP \
130+
--disable-local-auth \
131+
--query serviceBusEndpoint \
132+
--output tsv | sed -e 's/https:\/\///' -e 's/:443\///')
133+
134+
# Create a new queue in the service bus namespace
135+
az servicebus queue create \
136+
--name myqueue \
137+
--namespace $SERVICEBUS_NAME \
138+
--resource-group $RESOURCE_GROUP
139+
```
140+
141+
1. Create a user-assigned managed identity in *Tenant B* using the [`az identity create`][az-identity-create] command.
92142
93143
```azurecli-interactive
94-
# Set environment variable
95-
IDENTITY_NAME=<identity-name>
144+
# Set user-assigned managed identity name
145+
IDENTITY_NAME=${SERVICEBUS_NAME}-identity
96146
97147
# Create a user-assigned managed identity
98148
az identity create --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME
99149
```
150+
1. Get the principal ID of the managed identity in *Tenant B* using the [`az identity show`][az-identity-show] command.
100151
101-
4. Get the client ID of the managed identity in *Tenant B* using the [`az identity show`][az-identity-show] command.
152+
```azurecli-interactive
153+
# Get the user-assigned managed identity principalId
154+
PRINCIPAL_ID=$(az identity show \
155+
--resource-group $RESOURCE_GROUP \
156+
--name $IDENTITY_NAME \
157+
--query principalId \
158+
--output tsv)
159+
```
160+
161+
1. Get the client ID of the managed identity in *Tenant B* using the [`az identity show`][az-identity-show] command.
102162
103163
```azurecli-interactive
104-
CLIENT_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME --query clientId --output tsv)
164+
CLIENT_ID=$(az identity show \
165+
--resource-group $RESOURCE_GROUP \
166+
--name $IDENTITY_NAME \
167+
--query clientId \
168+
--output tsv)
105169
```
106170
107-
5. Get the principal ID of the managed identity in *Tenant B* using the [`az identity show`][az-identity-show] command.
171+
1. Get the resource ID of the service bus namespace in *Tenant B* using the [`az servicebus namespace show`][az-servicebus-namespace-show] command.
108172
109173
```azurecli-interactive
110-
PRINCIPAL_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $IDENTITY_NAME --query principalId --output tsv)
174+
SERVICEBUS_ID=$(az servicebus namespace show \
175+
--name $SERVICEBUS_NAME \
176+
--resource-group $RESOURCE_GROUP \
177+
--query id \
178+
--output tsv)
111179
```
112180
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.
181+
6. Assign the managed identity in *Tenant B* permissions to read and write service bus messages using the [`az role assignment create`][az-role-assignment-create] command.
114182
115183
```azurecli-interactive
116-
az role assignment create --role "Reader" --assignee $PRINCIPAL_ID --scope /subscriptions/$TENANT_A_SUBSCRIPTION_ID
184+
az role assignment create \
185+
--role "Azure Service Bus Data Owner" \
186+
--assignee-object-id $PRINCIPAL_ID \
187+
--assignee-principal-type ServicePrincipal \
188+
--scope $SERVICEBUS_ID
117189
```
118190
119191
## Establish trust between AKS cluster and managed identity
@@ -123,121 +195,115 @@ In this section, you create the federated identity credential needed to establis
123195
* Create a federated identity credential using the [`az aks federated-identity add`][az-aks-federated-identity-add] command.
124196
125197
```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
198+
az identity federated-credential create \
199+
--name $IDENTITY_NAME-$RANDOM \
200+
--identity-name $IDENTITY_NAME \
201+
--resource-group $RESOURCE_GROUP \
202+
--issuer $OIDC_ISSUER_URL \
203+
--subject system:serviceaccount:default:myserviceaccount
127204
```
128205
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-
```
206+
`--subject system:serviceaccount:default:myserviceaccount` 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 Microsoft Entra ID as the `subject` in the authorization request. Microsoft Entra ID 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.
144207
145-
2. Check if the `Microsoft.Quota` resource provider is registered in your subscription using the [`az provider show`][az-provider-show] command.
208+
## Deploy application to send messages to Azure Service Bus queue
146209
147-
```azurecli-interactive
148-
az provider show --namespace Microsoft.Quota
149-
```
210+
In this section, you deploy an application to your AKS cluster in *Tenant A* that sends messages to the Azure Service Bus queue in *Tenant B*.
150211
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.
212+
1. Log out of your *Tenant B* subscription using the [`az logout`][az-logout] command.
152213
153214
```azurecli-interactive
154-
az provider register --namespace Microsoft.Quota
215+
az logout
155216
```
156217
157-
3. Once the registration state is `Registered`, you can test the application locally using the following commands:
218+
1. Log into your *Tenant A* subscription using the [`az login`][az-login-interactively] command and pass in the tenant ID of *Tenant A*.
158219
159220
```azurecli-interactive
160-
XYZ
221+
az login --tenant $TENANT_A_ID
161222
```
162223
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
224+
1. Ensure you are working with the correct subscription in *Tenant A* by using the [`az account set`][az-account-set] command.
168225
169226
```azurecli-interactive
170-
XYZ
227+
az account set --subscription $TENANT_A_SUBSCRIPTION_ID
171228
```
172229
173-
2. Get the cluster credentials for the AKS cluster in *Tenant A* using the [`az aks get-credentials`][az-aks-get-credentials] command.
230+
1. Get the cluster credentials for the AKS cluster in *Tenant A* using the [`az aks get-credentials`][az-aks-get-credentials] command.
174231
175232
```azurecli-interactive
176233
az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
177234
```
178235
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*.
236+
1. Create a new Kubernetes ServiceAccount in the `default` namespace and pass in the client ID of your managed identity in *Tenant B* to the `kubectl apply` command. The client ID is used to authenticate the pod to the Azure Service Bus.
180237
181238
```azurecli-interactive
182239
kubectl apply -f - <<EOF
183240
apiVersion: v1
184241
kind: ServiceAccount
185242
metadata:
186243
annotations:
187-
azure.workload.identity/client-id: <YOUR_USER_ASSIGNED_MANAGED_IDENTITY_CLIENT_ID>
188-
name: wi-demo-account
189-
namespace: default
244+
azure.workload.identity/client-id: $CLIENT_ID
245+
name: myserviceaccount
190246
EOF
191247
```
192248
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.
249+
4. Create a new Kubernetes Job in the `default` namespace to send 100 messages to your Azure Service Bus queue. The Pod template is configured to use workload identity and the service account you created in the previous step. Also note that the `AZURE_TENANT_ID` environment variable is set to the tenant ID of *Tenant B*. This is required as workload identity defaults to the tenant of the AKS cluster, so you need to explicitly set the tenant ID of *Tenant B*.
194250
195251
```azurecli-interactive
196252
kubectl apply -f - <<EOF
197-
apiVersion: v1
198-
kind: Pod
253+
apiVersion: batch/v1
254+
kind: Job
199255
metadata:
200-
name: wi-demo-app
201-
namespace: default
202-
labels:
203-
azure.workload.identity/use: "true"
256+
name: myproducer
204257
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
258+
template:
259+
metadata:
260+
labels:
261+
azure.workload.identity/use: "true"
262+
spec:
263+
serviceAccountName: myserviceaccount
264+
containers:
265+
- image: ghcr.io/azure-samples/aks-app-samples/servicebusdemo:latest
266+
name: myproducer
267+
resources: {}
268+
env:
269+
- name: OPERATION_MODE
270+
value: "producer"
271+
- name: MESSAGE_COUNT
272+
value: "100"
273+
- name: AZURE_SERVICEBUS_QUEUE_NAME
274+
value: myqueue
275+
- name: AZURE_SERVICEBUS_HOSTNAME
276+
value: $SERVICEBUS_HOSTNAME
277+
- name: AZURE_TENANT_ID
278+
value: $TENANT_B_ID
279+
restartPolicy: Never
221280
EOF
222281
```
223282
224-
5. Verify that the pod is running using the `kubectl get pods` command.
283+
5. Verify that the pod is configured correctly to interact with the Azure Service Bus queue in *Tenant B* by checking the status of the pod using the `kubectl describe pod` command.
225284
226285
```azurecli-interactive
227-
kubectl get pods
286+
# Get the dynamically generated pod name
287+
POD_NAME=$(kubectl get po --selector job-name=myproducer -o jsonpath='{.items[0].metadata.name}')
288+
289+
# Get the tenant ID environment variable
290+
kubectl describe pod $POD_NAME | grep AZURE_TENANT_ID
228291
```
229292
230-
6. Check the logs of the pod to see if the application was able to read subscription information using the `kubectl logs` command.
293+
6. Check the logs of the pod to see if the application was able to send messages across tenants using the `kubectl logs` command.
231294
232295
```azurecli-interactive
233-
kubectl logs wi-demo-app
296+
kubectl logs $POD_NAME
234297
```
235298
236299
Your output should look similar to the following example output:
237300
238301
```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"}
302+
...
303+
Adding message to batch: Hello World!
304+
Adding message to batch: Hello World!
305+
Adding message to batch: Hello World!
306+
Sent 100 messages
241307
```
242308
243309
## Next steps
@@ -251,6 +317,8 @@ In this article, you learned how to configure cross-tenant workload identity on
251317
[workload-identity-overview]: ./workload-identity-overview.md
252318
[configure-workload-identity]: ./workload-identity-deploy-cluster.md
253319
[install-azure-cli]: /cli/azure/install-azure-cli
320+
[az-login-interactively]: cli/azure/authenticate-azure-cli-interactively#interactive-login
321+
[az-logout]: cli/azure/authenticate-azure-cli-interactively#logout
254322
[az-account-set]: /cli/azure/account#az_account_set
255323
[az-group-create]: /cli/azure/group#az_group_create
256324
[az-aks-create]: /cli/azure/aks#az_aks_create
@@ -262,3 +330,6 @@ In this article, you learned how to configure cross-tenant workload identity on
262330
[az-provider-show]: /cli/azure/provider#az_provider_show
263331
[az-provider-register]: /cli/azure/provider#az_provider_register
264332
[az-aks-get-credentials]: /cli/azure/aks#az_aks_get_credentials
333+
[az-servicebus-namespace-create]: cli/azure/servicebus/namespace?view=azure-cli-latest#az-servicebus-namespace-create
334+
[az-servicebus-namespace-show]: cli/azure/servicebus/namespace?view=azure-cli-latest#az-servicebus-namespace-show
335+
[az-servicebus-queue-create]: cli/azure/servicebus/queue?view=azure-cli-latest#az-servicebus-queue-create

0 commit comments

Comments
 (0)