Kubetier
  1. 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

  2. The IAM role trusts the cluster OIDC provider and evaluates whatever token claims its trust policy names, most commonly the subject and the audience

  3. Those conditions are policy specific rather than built into IRSA, and the ServiceAccount annotation takes no part in the authorization decision

  4. A pod running under that ServiceAccount, projecting a serviceAccountToken with audience sts.amazonaws.com, receives an assertion STS accepts

  5. AssumeRoleWithWebIdentity is unauthenticated, so the exchange needs no AWS credentials and returns whatever the role itself grants

  6. create serviceaccounts/token mints the same assertion with no pod involved, and the credentials work from outside the cluster

  7. The eks.amazonaws.com/role-arn annotation only drives the pod-identity-webhook, which injects at admission and so never reaches running pods

  8. That annotation is also the discovery path, since it names the role and the ServiceAccount it trusts, and reading it needs only list serviceaccounts

Rights needed, any one set:

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.

K8s docs ↗