1475 words
7 minutes
Impersonating as other users and auditing impersonation actions in AAD-enabled AKS

Impersonating users in an AAD-enabled Azure Kubernetes Service (AKS) enables administrators to act on behalf of other users, making management easier and operations smoother. When teams use impersonation effectively, they can simulate user roles, test access controls, and troubleshoot permission-related issues, all of which help ensure a secure and efficient Kubernetes environment. Additionally, auditing impersonation actions is crucial for organizations to track user activities, promoting transparency and accountability.

This article shows you how to:

  • How to impersonate other users in AAD-enabled AKS cluster, including both ABAC and non-ABAC scenario.
  • Use Log Analytics Workspace to check impersonation history.

Prerequisites#

  • kubectl version needs to be gerater than or equal to 1.35.

TL;DR#

  • Use --as ${externalUserId} --as-user-extra oid=${externalUserId} for ABAC-enabled AKS cluster.
  • Use --as ${externalUserId} for non ABAC-enabled AKS cluster.
  • Impersonation messages can be found in AKSControlPlane table, but you need to combine them with AKSAudit or AKSAuditAdmin tables to perform auditing.

Before you begin#

Kubernetes v1.35.0 was released on Dec 18, 2025. As of now (Jan 16, 2026), your client version is likely not upgraded to the latest version required to meet the requirement.
Version 1.35.0 introduces --as-user-extra flag in kubectl, which is mandatory for impersonation in ABAC-enabled AKS cluster. So, be sure to check your kubectl version using the command below:

Terminal window
kubectl version

If you are using Azure Cloud Shell, you can use the following command to overwrite the embedded kubectl:

Terminal window
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
install -m 0755 kubectl ~/.local/bin/kubectl && bash

If you need to uninstall non-embedded kubectl from Cloud Shell, use the command below:

Terminal window
rm ~/.local/bin/kubectl && bash

For general environment, follow official documentation to upgrade your kubectl version.

Preparing environment#

Before practicing impersonation, we will need to pre-define some parameters and create a secondary account for comparison.

  1. Create secondary account

Modify the following parameters according to your environment:

Terminal window
NAME=aksreadonlyuser
DOMAIN=contoso.com
PASSWORD=Password1

Then, create a new account:

Terminal window
az ad user create -o none \
--display-name ${NAME} \
--password ${PASSWORD} \
--user-principal-name ${NAME}@${DOMAIN}
CAUTION

Remember to delete this secondary account after practising.

  1. Retrieve the AKS ID and the user object ID
Terminal window
aksId=$(az resource list -n ${aks} -g ${rG} \
--resource-type Microsoft.ContainerService/managedClusters \
--query [0].id -o tsv)
externalUserId=$(az ad user show -o tsv --query id \
--id ${NAME}@${DOMAIN})

Impersonation#

Before performing impersonation, you may want to verify the type of AKS cluster you are using.

To check if your AKS cluster is AAD-enabled, use the command below:

Terminal window
az aks show -n ${aks} -g ${rG} --query aadProfile

If the result is null (empty, nothing), this article is not applicable to your AKS cluster, as it is not AAD-enabled. If the result is anything else, then your AKS cluster is AAD-enabled.

To check if your AKS cluster is ABAC-enabled, use the command below:

Terminal window
az aks show -n ${aks} -g ${rG} --query aadProfile.enableAzureRbac

If the result is true, then your AKS cluster is ABAC-enabled; otherwise, it is ABAC-disabled.

After that, remember to retrieve your kubeconfig:

Terminal window
az aks get-credentials -n ${aks} -g ${rG}

Impersonating in ABAC-enabled AKS cluster#

  1. Assign RBAC Reader role to newly-create account
Terminal window
az role assignment create --role "Azure Kubernetes Service RBAC Reader" \
--assignee-object-id ${externalUserId} -o none \
--scope ${aksId} --assignee-principal-type User
TIP

If you are practising this on a newly created AKS cluster and haven’t granted yourself permission, remember to assign RBAC Cluster Admin role to yourself:

Terminal window
userObjectId=$(az ad signed-in-user show --query id -o tsv)
az role assignment create --role "Azure Kubernetes Service RBAC Cluster Admin" \
--assignee-object-id ${userObjectId} -o none \
--scope ${aksId} --assignee-principal-type User

You also need to run the command kubelogin remove-cache-dir to clear the cached token and force a refresh of the token to update permissions, especially after granting yourself permissions recently.

Terminal window
kubelogin remove-cache-dir
  1. Impersonating as the newly-create account
Terminal window
kubectl auth can-i get pod --as ${externalUserId} --as-user-extra oid=${externalUserId}
kubectl auth can-i get secret --as ${externalUserId} --as-user-extra oid=${externalUserId}

Output:

yes
no - User does not have access to the resource in Azure. Update role assignment to allow access.
TIP

If you still need to use RBAC to control who can impersonate users in ABAC-enabled AKS cluster, here is the ClusterRole manifest that you can refer to:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate-role
rules:
- apiGroups: ["", "authentication.k8s.io"]
resources: ["users", "groups", "userextras/oid"]
verbs: ["impersonate"]

Impersonating in non ABAC-enabled AKS cluster#

  1. Create ClusterRole and ClusterRoleBinding

The command below will grant the newly created account access to pods:

Terminal window
<<EOF kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-access-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: access-to-pod
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: ${externalUserId}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pod-access-role
EOF
TIP

If you are practising this on a newly created AKS cluster and haven’t granted yourself permission, you can first use the “masterclient” admin account by running the following command:

Terminal window
az aks get-credentials -n ${aks} -g ${rG} --admin

Then, grant yourself impersonation and Pod/ClusterRole/ClusterRoleBinding creation permissions by using the following commands:

Terminal window
userObjectId=$(az ad signed-in-user show --query id -o tsv)
Terminal window
<<EOF kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-access-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate-role
rules:
- apiGroups: [""]
resources: ["users", "groups"]
verbs: ["impersonate"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: clusterrole-role
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "clusterrolebindings"]
verbs: ["create", "get", "watch", "list", "update", "delete", "patch"]
EOF
Terminal window
<<EOF kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: access-to-pod-myself
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: ${userObjectId}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pod-access-role
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: action-to-impersonate
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: ${userObjectId}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: impersonate-role
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: permission-to-clusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: ${userObjectId}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: clusterrole-role
EOF

Then, switch back to your logged-in account and retry the steps in this section:

Terminal window
az aks get-credentials -n ${aks} -g ${rG}
  1. Impersonating as the newly-create account
Terminal window
kubectl auth can-i get pod --as ${externalUserId}
kubectl auth can-i get secret --as ${externalUserId}

Output:

yes
no
TIP

Do you notice the difference in impersonation between ABAC and non-ABAC environments? When impersonating in an ABAC-enabled AKS cluster, you need the argument --as-user-extra oid=${externalUserId}; this argument is not required in an non-ABAC AKS cluster.

Audit the impersonation actions#

Auditing impersonation actions in Kubernetes is vital for security, as it tracks user actions on behalf of others, allowing administrators to detect unauthorized access and analyze behavior. In this section, we will use Log Analytics Workspace and resource logs to retrieve control plane logs.

  1. Enable control plane logs for ingestion

Follow the section “Enable Control Plane Logs for Ingestion” in this documentation.
In this article, only KubernetesAudit and KubernetesControlPlane will be utilized. You can adjust these options based on your environment.

  1. Ingestion

The impersonation logs will only appear in the AKSControlPlane table. Use the query below to view the messages:

AKSControlPlane
| where TimeGenerated > ago(10m)
| where Category == "kube-apiserver" and Level =~ "info"
| where Message contains "impersonating"
| project TimeGenerated, Message
| take 3

Output:

TimeGenerated [UTC]Message
1/15/2026, 10:43<06>.536 AM00000000-0000-0000-0000-000000000000[22222222-2222-2222-2222-222222222222,system:authenticated] is impersonating 11111111-1111-1111-1111-111111111111[system:authenticated]
1/15/2026, 10:43<17>.188 AM00000000-0000-0000-0000-000000000000[22222222-2222-2222-2222-222222222222,system:authenticated] is impersonating 11111111-1111-1111-1111-111111111111[system:authenticated]
1/15/2026, 10:43<28>.079 AM00000000-0000-0000-0000-000000000000[22222222-2222-2222-2222-222222222222,system:authenticated] is impersonating 11111111-1111-1111-1111-111111111111[system:authenticated]

In the output:

  • 00000000-0000-0000-0000-000000000000 is representing the person who is impersonating.
  • 11111111-1111-1111-1111-111111111111 is representing the person who is being impersonated.
  • 22222222-2222-2222-2222-222222222222 is representing the group name of “system:authenticated”.
NOTE

The actual output of TimeGenerated should be in the format like “2026-01-15T10:43<06>.536207Z”. Here, the output like “1/15/2026, 10:43<06>.536 AM” is formatted by the Log Analytics Workspace Web.

To combine the message with the actual action, use the following Kusto query:

// Set your time range
let TimeRange = ago(10m);
let binSize = 1ms;
let apiServer = AKSControlPlane
| where TimeGenerated > TimeRange
| where Category == "kube-apiserver" and Level =~ "info"
| where Message contains "impersonating"
| project TimeGenerated, Message, PodName
| extend TimeBin = bin(TimeGenerated, binSize);
let auditLog = AKSAudit
| where TimeGenerated > TimeRange
| where Level =~ "RequestResponse" and User contains "oid"
| project RequestReceivedTime, Verb, RequestUri, User, SourceIps, UserAgent, ObjectRef, ResponseStatus, RequestObject, ResponseObject, Annotations, PodName
| extend TimeBin = bin(RequestReceivedTime, binSize);
apiServer
| join kind=leftouter (auditLog) on TimeBin, PodName
| where TimeGenerated >= RequestReceivedTime
and TimeGenerated <= (RequestReceivedTime + binSize)
| project-away TimeBin, TimeBin1, PodName, PodName1
| take 2

Output:

RequestReceivedTime [UTC]VerbRequestUriMessageUserSourceIpsUserAgentObjectRefResponseStatusRequestObjectResponseObjectAnnotations
1/15/2026, 11:58<17>.431 AMcreate/apis/authorization.k8s.io/v1/selfsubjectaccessreviews00000000-0000-0000-0000-000000000000[22222222-2222-2222-2222-222222222222,system:authenticated] is impersonating 11111111-1111-1111-1111-111111111111[system:authenticated]{"username":"00000000-0000-0000-0000-000000000000", "groups":["22222222-2222-2222-2222-222222222222", "system\:authenticated"], "extra":{"oid":["00000000-0000-0000-0000-000000000000"]}}["4.194.5.74", "172.31.18.164"]kubectl/v1.35.0 (linux/amd64) kubernetes/6645204{"resource":"selfsubjectaccessreviews", "apiGroup":"authorization.k8s.io", "apiVersion":"v1"}{"metadata":{}, "code":201}{"kind":"SelfSubjectAccessReview", "apiVersion":"authorization.k8s.io/v1", "metadata":{"creationTimestamp":null}, "spec":{"resourceAttributes":{"namespace":"default", "verb":"get", "resource":"secrets"}}, "status":{"allowed":false}}{"kind":"SelfSubjectAccessReview", "apiVersion":"authorization.k8s.io/v1", "metadata":{"creationTimestamp":null, "managedFields":[...]}, "spec":{"resourceAttributes":{"namespace":"default", "verb":"get", "resource":"secrets"}}, "status":{"allowed":false}}{"authorization.k8s.io/decision":"allow", "authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"system:basic-user\" of ClusterRole \"system:basic-user\" to Group \"system\:authenticated\""}
1/15/2026, 11:58<06>.595 AMcreate/apis/authorization.k8s.io/v1/selfsubjectaccessreviews00000000-0000-0000-0000-000000000000[22222222-2222-2222-2222-222222222222,system:authenticated] is impersonating 11111111-1111-1111-1111-111111111111[system:authenticated]{"username":"00000000-0000-0000-0000-000000000000", "groups":["22222222-2222-2222-2222-222222222222", "system\:authenticated"], "extra":{"oid":["00000000-0000-0000-0000-000000000000"]}}["4.194.5.74", "172.31.18.164"]kubectl/v1.35.0 (linux/amd64) kubernetes/6645204{"resource":"selfsubjectaccessreviews", "apiGroup":"authorization.k8s.io", "apiVersion":"v1"}{"metadata":{}, "code":201}{"kind":"SelfSubjectAccessReview", "apiVersion":"authorization.k8s.io/v1", "metadata":{"creationTimestamp":null}, "spec":{"resourceAttributes":{"namespace":"default", "verb":"get", "resource":"secrets"}}, "status":{"allowed":false}}{"kind":"SelfSubjectAccessReview", "apiVersion":"authorization.k8s.io/v1", "metadata":{"creationTimestamp":null, "managedFields":[...]}, "spec":{"resourceAttributes":{"namespace":"default", "verb":"get", "resource":"secrets"}}, "status":{"allowed":false}}{"authorization.k8s.io/decision":"allow", "authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"system:basic-user\" of ClusterRole \"system:basic-user\" to Group \"system\:authenticated\""}
NOTE

It may take up to 30 minutes for data in AKSAudit to be collected.

Afterword#

The article starts with a user asking why kubectl auth can-i doesn’t work in the AKS GitHub repository. Following that, the Kubernetes SIG CLI team introduced a new feature that allows users to input --as-user-extra, making it possible to impersonate other users in ABAC-enabled AKS using just the CLI, without modifying any files. This feature was released about a month ago.

Now, I’ve decided to write this article to address the issue. I’ve also included a method for auditing impersonation actions, which lets users review their activities while impersonating others, adding some extra depth to the discussion.

And here’s the article I’ve put together.

Impersonating as other users and auditing impersonation actions in AAD-enabled AKS
https://blog.joeyc.dev/posts/aks-impersonation-audit-aad/
Author
Joey Chen
Published at
2026-01-16
License
CC BY-SA 4.0