create serviceaccounts/token
A bound token for any ServiceAccount in scope, minted through the TokenRequest API with no existing Secret and a caller-specified expiry.
Targeting a kube-system controller ServiceAccount is T0.
The caller also chooses the audience.
Where the cluster is federated to a cloud identity provider, the same call mints an assertion that trades for a cloud credential outside the cluster.
Contextual upgrade to T0:
Targeting a kube-system SA such as kube-controller-manager that carries cluster-admin-equivalent permissions
- API Group
- (core)
- Scope
- namespaced
- Audit Level
- RequestResponse
Escalation Paths
Identify a high-privilege ServiceAccount in scope.
The clusterrole-aggregation-controller SA in kube-system has effective cluster-admin rights and is a prime target.
Mint a bound token through the TokenRequest API with an extended lifetime, for example --duration=87600h for ten years.
The API server honors the request unless --service-account-max-token-expiration is set.
kubeadm does not set it, so the full 87600h is issued.
Managed providers commonly do set it.
Authenticate as the ServiceAccount with the minted token.
T0 when targeting kube-system controller service accounts such as clusterrole-aggregation-controller or kube-controller-manager.
The audience is caller specified, so on a cluster federated to a cloud identity provider the same call mints an assertion that exchanges for a cloud credential outside the cluster
Additional rights needed:
Note:
The serviceaccounts/token subresource (TokenRequest API) was promoted to stable in 1.22, making this path available without alpha flags.
No patch exists.
Keep token TTLs short and audit all uses of this verb.
An IAM role must already exist whose trust policy names the cluster OIDC provider and conditions on sub system:serviceaccount:<namespace>:<name> plus aud sts.amazonaws.com
The IAM role trusts the cluster OIDC provider and evaluates whatever token claims its trust policy names, most commonly the subject and the audience
Those conditions are policy specific rather than built into IRSA, and the ServiceAccount annotation takes no part in the authorization decision
A pod running under that ServiceAccount, projecting a serviceAccountToken with audience sts.amazonaws.com, receives an assertion STS accepts
AssumeRoleWithWebIdentity is unauthenticated, so the exchange needs no AWS credentials and returns whatever the role itself grants
create serviceaccounts/token mints the same assertion with no pod involved, and the credentials work from outside the cluster
The eks.amazonaws.com/role-arn annotation only drives the pod-identity-webhook, which injects at admission and so never reaches running pods
That annotation is also the discovery path, since it names the role and the ServiceAccount it trusts, and reading it needs only list serviceaccounts
Additional rights needed:
Note:
Not a defect and nothing to patch.
The IAM trust policy is the anchor, so an audit that looks only for the eks.amazonaws.com/role-arn annotation misses every variant that bypasses the webhook.
A federated identity credential must already exist on the managed identity, naming the cluster OIDC issuer and system:serviceaccount:<namespace>:<name> as its subject
Entra matches that credential on issuer and subject alone, so the ServiceAccount name is the whole secret and no annotation takes part in the trust decision
A pod running under that ServiceAccount, projecting a serviceAccountToken with audience api://AzureADTokenExchange, receives an assertion Entra accepts
Exchanging the assertion returns an access token for the managed identity, carrying every Azure role assigned to it
create serviceaccounts/token mints the same assertion with no pod involved, and the token it buys is usable from outside the cluster
The pod label azure.workload.identity/use and the ServiceAccount client-id annotation only drive the addon webhook, a convenience for applications rather than the control
Additional rights needed:
Note:
Not a defect and nothing to patch.
The federated credential is the trust anchor, so an audit that looks only for the azure.workload.identity annotation misses every variant that does not use the addon webhook.

