KubernetesLX · ServiceAccountsServiceAccounts
External token issuers — IRSA, Workload Identity, SPIFFE
What you'll learn
- Explain how AWS IRSA, GCP Workload Identity, and Azure Workload Identity exchange SA tokens for cloud credentials
- Configure each provider for production use
- Identify the failure modes (wrong audience, missing annotation, trust policy)
- Recognise when SPIFFE/SPIRE is the right pattern for cross-cloud workload identity
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
External token issuers are cloud-provider integrations that exchange a Kubernetes-issued SA token for provider-native credentials. AWS IRSA exchanges for IAM role credentials; GCP Workload Identity exchanges for a GCP service account token; Azure Workload Identity exchanges for an Azure AD token. SPIFFE/SPIRE is the cross-cloud pattern for organisations that span providers. This lesson covers each integration, the configuration, and the production patterns.
AWS IRSA
IAM Roles for Service Accounts (IRSA) is the AWS mechanism for workload identity. The flow:
- A Kubernetes Pod projects an SA token with
audience
sts.amazonaws.com. - The AWS SDK (or a sidecar) presents the token to
AWS STS via the
AssumeRoleWithWebIdentityAPI. - STS verifies the token’s signature against the cluster’s OIDC issuer URL and the role’s trust policy.
- STS returns temporary IAM credentials (access key, secret key, session token).
- The workload uses the credentials to access AWS APIs (S3, SQS, DynamoDB, etc.).
sequenceDiagram
participant Pod
participant K8s as Kubernetes API
participant STS as AWS STS
participant AWS as AWS API
Pod->>K8s: TokenRequest (audience: sts.amazonaws.com)
K8s->>Pod: JWT signed by cluster OIDC issuer
Pod->>STS: AssumeRoleWithWebIdentity (JWT, role ARN)
STS->>STS: Verify signature, audience, trust policy
STS->>Pod: IAM credentials
Pod->>AWS: Access with IAM credentials
The configuration:
- Create an IAM role with a trust policy that trusts the cluster’s OIDC issuer:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT:oidc-provider/OIDC_ISSUER_URL"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"OIDC_ISSUER_URL:sub": "system:serviceaccount:prod:api-sa"
}
}
}
]
}
The sub condition restricts the role to a specific
SA in a specific namespace.
- Annotate the SA with the role ARN:
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-sa
namespace: prod
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/myapp-role
- Project the token with audience
sts.amazonaws.com:
spec:
serviceAccountName: api-sa
volumes:
- name: aws-token
projected:
sources:
- serviceAccountToken:
path: aws-token
audience: sts.amazonaws.com
expirationSeconds: 900
containers:
- name: api
volumeMounts:
- name: aws-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount # EKS expects this path
readOnly: true
The AWS SDK (or pod identity webhook) reads the token, exchanges it with STS, and uses the resulting credentials.
GCP Workload Identity
GCP Workload Identity is the GCP equivalent. The flow:
- A Kubernetes SA is bound to a GCP service account (GSA) via an IAM policy binding.
- A Pod projects an SA token with audience
https://iam.googleapis.com/. - The GCP client library presents the token to the metadata server (or to the IAM credentials API directly).
- IAM verifies the token and returns a GSA access token.
- The workload uses the token to access GCP APIs.
The configuration:
- Bind the KSA to a GSA:
gcloud iam service-accounts add-iam-policy-binding \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:PROJECT.svc.id.goog[prod/api-sa]" \
myapp-gsa@PROJECT.iam.gserviceaccount.com
- Annotate the KSA with the GSA email:
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-sa
namespace: prod
annotations:
iam.gke.io/gcp-service-account: myapp-gsa@PROJECT.iam.gserviceaccount.com
- Project the token with audience
https://iam.googleapis.com/.
The metadata server (in GKE) or the client library handles the exchange.
Azure Workload Identity
Azure Workload Identity is the Azure equivalent:
- A Kubernetes SA is federated with an Azure AD application.
- A Pod projects an SA token with audience
api://AzureADTokenExchange. - The Azure SDK presents the token to the AAD token exchange endpoint.
- AAD returns an Azure AD token for the federated identity.
The configuration uses a azure-workload-identity
annotation and a federated credential on the Azure AD
application.
SPIFFE/SPIRE
For organisations that span multiple cloud providers or need a provider-agnostic workload identity, SPIFFE is the standard. The flow:
- SPIRE (the SPIFFE Runtime Environment) issues SVIDs (SPIFFE Verifiable Identity Documents) to workloads.
- The SVID is a JWT or X.509 document with a
SPIFFE ID (e.g.,
spiffe://example.com/ns/prod/sa/api-sa). - Workloads present the SVID to consumers; consumers verify against SPIRE’s trust bundle.
SPIFFE is the canonical pattern for zero-trust workload identity. It works across clouds, on premises, and at the edge.
Production patterns
- One provider per SA. A SA configured for IRSA should not also be configured for Workload Identity. Each SA has one identity per cloud.
- Trust policies scope by SA. The trust policy
for an IAM role should restrict the
subto a specific SA in a specific namespace. - Annotate with the role ARN / GSA email. The annotation is the link between the KSA and the cloud identity.
- Project the token with the right audience. IRSA
uses
sts.amazonaws.com; Workload Identity useshttps://iam.googleapis.com/; Azure usesapi://AzureADTokenExchange. - Use the EKS pod identity webhook or equivalent. The webhook handles the token exchange automatically; the workload sees IAM credentials at the metadata server.
Production failure modes
- Wrong audience. The token’s audience is the API server’s; STS rejects. The fix is to set the audience to the provider’s.
- Missing trust policy. The IAM role’s trust policy does not include the cluster’s OIDC issuer. STS rejects. The fix is to register the issuer with IAM.
- Trust policy too broad. The trust policy
accepts any SA in any namespace. A compromised SA
in
devcan assume the prod role. The fix is to restrict bysub. - No annotation on the SA. The SA is not bound to the IAM role. The token is rejected. The fix is to add the annotation.
- Mixed providers. A Pod runs AWS IRSA and GCP Workload Identity in the same container. The providers’ tokens are mixed; one SDK reads the other’s token. The fix is one provider per Pod.
Cross-course references
- The Linux course covers JWT and JWKS — the primitives that all of these integrations use.
- The Observability course covers the audit log entries for token exchange operations.
Quiz
Knowledge check · 4 questions
Q1. What audience must a ServiceAccount token have for AWS IRSA to work?
Q2. The IAM role's trust policy for IRSA should accept any SA in any namespace; a tight policy would prevent legitimate use cases.
Q3. Your Pod assumes an IAM role via IRSA. The STS call returns `InvalidIdentityToken: Wrong audience`. Why, and how do you fix it?
The Pod's projected token has the default audience (`https://kubernetes.default.svc`) instead of `sts.amazonaws.com`. The Pod spec uses the default mount (API server audience) and does not have an explicit projection with the IRSA audience. STS verifies the token's audience against `sts.amazonaws.com` and rejects.
Q4. Name three cloud-provider workload identity integrations and the audience each one requires.
Passing score: 75%. Answers are checked in this browser.
Production discipline
External token issuers are the right primitive for cloud-provider workload identity. AWS IRSA, GCP Workload Identity, and Azure Workload Identity each exchange a Kubernetes-issued SA token for provider-native credentials. The discipline is one provider per SA, tight trust policies, correct audiences, and the right annotations. A cluster that runs multiple providers in the same Pod has a configuration failure; a cluster that runs each provider in its own Pod with the right configuration has a workload identity programme that is auditable across providers. SPIFFE is the canonical pattern for organisations that span providers.