Workload identity federation gives keyless authentication to cloud APIs, but it moves the whole security decision into a trust configuration that few teams review as carefully as they once reviewed the key. A federated workload proves who it is with a short-lived token from its own platform, and the cloud swaps it for credentials only if issuer, audience and subject match your configuration. This guide goes deeper than our overview: how the exchange works on AWS, Microsoft Entra ID and Google Cloud, how to scope claims, how Kubernetes and CI/CD federation are wired, and how to monitor the result. For the wider picture see the Cloud Workload Identity Guide. It is written for cloud platform engineers, identity architects and the security teams who review trust policies.
Key takeaways
- The trust condition is the credential. Once federation replaces a key, whoever can mint a token that satisfies your issuer, audience and subject conditions can obtain your cloud credentials.
- Bind to immutable claims. Prefer numeric repository and owner IDs, Kubernetes namespace and service account pairs, and specific environments over names that can be reused or patterns that match more than you intend.
- Each cloud checks differently. AWS evaluates IAM trust policy conditions, Entra ID requires an exact case-sensitive match on issuer, subject and audience, and Google Cloud applies CEL attribute conditions before any IAM binding.
- Kubernetes federation depends on issuer hygiene. The cluster's service account issuer becomes an identity provider, so its signing keys, discovery endpoint and namespace boundaries are now part of your cloud security perimeter.
- Federation needs its own monitoring. Log every token exchange, alert on new providers and federated credentials, and track how many static keys remain after each migration.
How the exchange works
Every federation flow has the same parts. An issuer (GitHub Actions, a Kubernetes API server, another cloud) signs a short-lived JSON Web Token (JWT) for the workload and publishes its discovery document at /.well-known/openid-configuration and its public keys at a JWKS endpoint. The cloud's token service acts as verifier: it fetches those keys, checks signature and expiry, and evaluates your trust configuration. If the claims match, it returns a short-lived cloud credential.
The protocols differ. Google's Security Token Service follows RFC 8693 OAuth 2.0 Token Exchange, with the external JWT as the subject_token and the grant type urn:ietf:params:oauth:grant-type:token-exchange. Entra workload identity federation uses the client credentials flow, accepting the external JWT as a JWT bearer assertion (client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer, from RFC 7523). AWS uses its own AssumeRoleWithWebIdentity API, which needs no AWS credentials: the token alone validates the caller.
| Aspect | AWS | Microsoft Entra ID | Google Cloud |
|---|---|---|---|
| Trust object | IAM OIDC identity provider and role trust policy | Federated identity credential on an app registration or user-assigned managed identity | Workload identity pool and provider |
| Exchange mechanism | sts:AssumeRoleWithWebIdentity | Client credentials flow with the external JWT as client assertion | RFC 8693 token exchange at https://sts.googleapis.com/v1/token |
| Signing algorithms accepted | RS256, RS384, RS512, ES256, ES384, ES512 | RS256 only | RS256 or ES256 |
| Matching model | IAM condition keys such as <issuer>:aud and <issuer>:sub | Exact, case-sensitive issuer, subject and audience; no wildcards (flexible credentials in preview) | Attribute mapping plus CEL attribute condition, then IAM principal bindings |
| Hard limits worth knowing | 100 audiences and 5 thumbprints per provider; session 900 seconds up to the role maximum of 12 hours | 20 federated credentials per identity; 600 characters per issuer, subject and audience | Token exp no more than 24 hours after iat; uploaded JWKS limited to 8 keys |
| Resulting credential | Temporary access key, secret and session token (default one hour) | Entra access token | Federated access token, optionally a service account token |
Configuring trust on each cloud
AWS: IAM OIDC identity provider and trust policy
An IAM OIDC identity provider records the issuer URL (case-sensitive, https://, unique in the account) and up to 100 audiences. AWS verifies the issuer's JWKS endpoint certificate against its trusted root certificate authorities and uses configured thumbprints mainly as a fallback. The provider must sit in the same account as the role that trusts it, so a multi-account estate needs one provider per account, best deployed from one reviewed template.
- OIDC trust policy: names the provider as the single federated principal, allows
sts:AssumeRoleWithWebIdentity, and constrains<issuer>:audand<issuer>:sub. - Platform guardrails: when GitHub's issuer is trusted, IAM refuses a trust policy that lacks a
token.actions.githubusercontent.com:subcondition or sets it solely to a wildcard, and roles trusting HCP Terraform must evaluateapp.terraform.io:sub. - Session controls: session policies can only narrow the role's permissions, and up to 50 session tags can drive attribute-based access control.
- Attribution:
RoleSessionNameappears in CloudTrail, and aSourceIdentityclaim cannot be changed once set and persists across chained sessions, tying actions to the run or pod.
Microsoft Entra ID: federated identity credentials
A federated identity credential is added to an app registration or a user-assigned managed identity. According to Microsoft's considerations page, the recommended audience is api://AzureADTokenExchange, an identity can hold at most 20 federated credentials, and wildcards are not supported in any property. A mistyped subject is accepted at creation and only fails at exchange time with AADSTS70021, which is also the error seen while a new credential propagates.
- Who can add one: anyone who can add a secret or certificate to an app registration can add a federated credential, so application owners and Application Administrators control who can federate into it.
- Preventive policy: an Azure Policy with the deny effect on the resource type
Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentialsblocks creation on managed identities outside approved scopes. - Flexible federated identity credentials: a preview feature that replaces the fixed subject with a
claimsMatchingExpressionusingmatches,eqandand, for a few CI and infrastructure as code issuers including GitHub and Terraform Cloud. For GitHub it must also matchrepository_idorrepository_owner_idwitheq, tying any branch wildcard to one immutable repository. - Not for Entra tokens: the flow does not accept tokens issued by Entra ID itself.
Google Cloud: pools, providers and attribute conditions
A workload identity pool groups external identities; a workload identity pool provider describes one issuer. Google's guidance for OIDC providers requires a mapping to google.subject, which should be a claim that is unique and cannot change (not email, which can be reassigned). The CEL attribute condition must evaluate to true or the token is rejected before any IAM policy is consulted. Google recommends a dedicated project for pools and providers.
- Impersonation: where a product does not support direct grants, the federated identity receives
roles/iam.workloadIdentityUseron a service account and impersonates it. - Principal identifiers:
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECTfor one identity, andprincipalSet://forms for groups, mapped attributes or, for impersonation only, the whole pool. A pool-wide binding is the federation equivalent of a wildcard subject.
Claim scoping: subject, audience and immutable IDs
The OIDC subject claim and audience restriction do most of the work. For GitHub Actions OIDC, one issuer, one issuer, https://token.actions.githubusercontent.com, serves every customer, so the issuer check alone proves only that some GitHub workflow asked for the token. AWS warns that if the subject condition is not limited to your organisation or repository, GitHub Actions from organisations outside your control can assume the role.
| Claim | What it binds | Scoping guidance |
|---|---|---|
iss | Which issuer signed the token | Pin to the exact issuer URL; for Kubernetes, the specific cluster issuer, never a shared one |
aud | Which verifier the token is for | Use a value only your configuration accepts: sts.amazonaws.com, api://AzureADTokenExchange, or the audience configured on the Google provider |
sub | Repository and ref, environment, or namespace and service account | Match one workload; prefer environment-based subjects for deployment roles |
repository_id, repository_owner_id | Immutable GitHub repository and owner | Add to conditions so a deleted and recreated name cannot inherit access |
job_workflow_ref | The reusable workflow file and ref that ran | Pin deployment roles to a reviewed, centrally owned workflow |
ref, environment, event_name | Branch or tag, deployment environment, trigger event | Separate pull request jobs from deploy jobs; give pull request runs read-only roles |
GitHub's OIDC reference lists the subject formats: repo:ORG/REPO:environment:NAME, repo:ORG/REPO:ref:refs/heads/BRANCH, repo:ORG/REPO:ref:refs/tags/TAG and repo:ORG/REPO:pull_request. Repositories created, renamed or transferred after 15 July 2026 use an immutable format that embeds owner and repository IDs; older repositories keep the name-based format until they opt in. Subjects can also be customised with include_claim_keys; change the cloud-side condition first, or exchanges fail as soon as the new format applies.
Kubernetes federation and service account token projection
The Kubernetes API server is an OIDC issuer for its workloads: it signs service account tokens with the issuer set by --service-account-issuer and publishes keys at /openid/v1/jwks (or a public HTTPS location set by --service-account-jwks-uri). Service account token projection, described in the Kubernetes documentation, mounts a token with a configurable audience and lifetime; the kubelet rotates it when it is older than 80% of its time to live or 24 hours, so applications must re-read the file rather than cache it. The federated subject is the standard system:serviceaccount:NAMESPACE:NAME.
Set automountServiceAccountToken: false where pods call no API, and retire legacy secret-based tokens, which Kubernetes deprecates. See the Kubernetes NHI Security Guide.
| Managed service | How pods federate | Points to watch |
|---|---|---|
| Amazon EKS Pod Identity | Role trusts the service principal pods.eks.amazonaws.com once; the EKS service assumes it and delivers credentials with session tags for cluster, namespace and service account | AWS recommends it where possible; no OIDC provider per cluster; EKS only |
| IAM roles for service accounts (IRSA) | Pod presents its projected token to AssumeRoleWithWebIdentity against a per-cluster IAM OIDC provider | Default limit of 100 OIDC providers per account; trust policy size caps you at about 8 trust relationships per role; no session tags, so every pod gets the full role |
| AKS with Microsoft Entra Workload ID (Azure workload identity) | Mutating webhook injects the projected token and sets AZURE_FEDERATED_TOKEN_FILE; service account annotated with azure.workload.identity/client-id; pod label azure.workload.identity/use required | 20 federated credentials per managed identity limits how many clusters and namespaces one identity can serve |
| GKE Workload Identity Federation for GKE | Fixed pool PROJECT_ID.svc.id.goog; the GKE metadata server exchanges the token; principal ends /subject/ns/NAMESPACE/sa/SERVICEACCOUNT | Same namespace and service account in any cluster in the project is the same identity; host network pods are not covered |
Google states that IAM does not distinguish between the clusters making the calls, so put clusters of different trust levels in separate projects. Likewise, a development cluster whose issuer a production role trusts is a production credential path.
CI/CD federation beyond the basics
A job needs permissions: id-token: write to request a token. The CI/CD Pipeline Identity Security Guide covers pipeline identities generally; for federation:
- Environment gates: bind production roles to an environment subject with protection rules (required reviewers, deployment branch restrictions), as AWS also recommends.
- Central deployment workflows: pin
job_workflow_refso only a reviewed reusable workflow reaches production credentials. - Separate identities per stage: a pull request job should never satisfy a deploy role's condition.
- Injection still works: untrusted code injected into a job holding
id-token: writecan request a valid token while the job runs.
Client assertions, external account credentials and token exchange
A client assertion is a signed JWT presented instead of a secret. With a certificate on Entra ID the workload builds it itself: Microsoft's certificate credentials format uses PS256, an x5t#S256 header, the client ID as iss and sub, the tenant token endpoint as aud, and an expiry 5 to 10 minutes after nbf. With federation, the external issuer's JWT replaces that assertion, so there is no private key to protect. RFC 7523 requires the verifier to reject an assertion whose audience is not itself, which is why audience restriction matters as much as subject matching.
Google client libraries consume federation through external account credentials. Google's AIP-4117 defines a JSON file with "type": "external_account", an audience naming the pool provider, a subject_token_type, the token_url for Google STS, a credential_source (a file, a URL or an executable) and an optional service_account_impersonation_url. The file holds no private key, but it decides where a token is read from and which identity is impersonated, and executable sources run only when GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES is 1. Generate these files in your own tooling and never load one supplied by a third party without validation.
Service-to-service token exchange federation follows RFC 8693, which distinguishes impersonation (the actor becomes the subject) from delegation (an act claim records who acts for whom) and warns that without client authentication anyone holding a stolen token could exchange it. See the OAuth 2.0 and OpenID Connect Guide.
Cross-cloud federation patterns
Cross-cloud federation uses the same trust objects with another cloud as issuer:
- Into Google Cloud: a pool provider for AWS or Entra ID accepts their tokens; audit logs show the AWS principal ARN or the managed identity object ID as subject.
- Into Azure: Entra federated credentials support Google Cloud, AWS, any Kubernetes cluster and SPIFFE issuers. See the Guide to SPIFFE and SPIRE.
- Into AWS: an IAM OIDC provider can trust any compliant issuer, including your Entra tenant.
Pin every cross-cloud trust to a specific tenant, account or project issuer, one subject and an audience used nowhere else, and review it like a cross-account role.
Choosing between options
- Native identity versus federation: inside a cloud, use its native identity; federation is for workloads outside it.
- Pod Identity versus IRSA: Pod Identity on EKS; IRSA for EKS Anywhere and self-managed clusters.
- Direct access versus impersonation on Google Cloud: Google recommends direct access, which keeps the federated subject visible as the principal; impersonate only where a product requires it, with one service account per workload.
- User-assigned managed identity versus app registration: a managed identity cannot hold secrets and sits under Azure resource governance; use an app registration where an application object is needed, such as multi-tenant apps.
- Exact versus flexible matching: exact subjects by default; flexible expressions only to stay under the 20-credential limit.
- Small versus large estates: small teams can hand-write trusts with peer review; large estates should generate them from one module per platform, with policy as code rejecting wildcard subjects, missing audiences and pool-wide bindings.
Rolling out federation
- Inventory: list static keys used by external workloads (AWS access keys, Entra client secrets, Google service account keys) and existing providers and federated credentials.
- Design subjects first: fix the subject format per platform (environment, namespace and service account, immutable IDs) in the trust module.
- Pilot one non-production workload: run it alongside its existing key and confirm exchanges in the logs.
- Test negative cases: confirm that tokens from another branch, repository, namespace or cluster are rejected.
- Cut over and deactivate: switch to federation and deactivate (not delete) the old key for an agreed period.
- Roll back if needed: if exchanges fail, re-enable that key only, fix the condition and repeat the negative tests.
- Delete and prevent: delete the key, then block regression with Google's key creation constraints, Entra application management policies and alerts on new AWS access keys.
Detection and measurement
- AWS: CloudTrail records
AssumeRoleWithWebIdentitywithuserIdentity.typeofWebIdentityUser,identityProviderset to the issuer and the token subject. Alert onCreateOpenIDConnectProvider,AddClientIDToOpenIDConnectProvider,UpdateOpenIDConnectProviderThumbprintandUpdateAssumeRolePolicyon federated roles. - Google Cloud:
ExchangeTokenentries appear in the Data Access log only after Data Access audit logs (Admin Read) are enabled for the IAM and Security Token Service APIs; they showprincipalSubjectandmetadata.mapped_principal. Impersonation appears asGenerateAccessToken, and later calls list the federated caller inserviceAccountDelegationInfo. Client errors such as invalid tokens are not logged. - Entra ID: monitor service principal and managed identity sign-in logs for federated sign-ins, and alert on audit and Azure Activity Log events that add or change federated identity credentials on applications and managed identities.
Metrics that show the programme is working:
- Federation coverage: percentage of external workloads authenticating by federation rather than static keys.
- Loose trusts: number of production trusts with wildcard or organisation-wide subjects, missing audience conditions or pool-wide bindings (target zero).
- Residual keys: static keys still active for workloads already migrated (target zero after the agreed grace period).
- Unowned or idle trusts: providers and federated credentials with no owner or no exchange in 90 days.
- Change detection time: time from creation of a new provider or federated credential to review.
Framework mapping
| Framework | Reference | How federation applies |
|---|---|---|
| NIST CSF 2.0 | PR.AA-01, PR.AA-03, PR.AA-04, PR.AA-05 | Service identities and credentials managed; services authenticated; identity assertions protected, conveyed and verified; least privilege through claim scoping |
| NIST SP 800-53 Rev. 5 | IA-5, IA-9, AC-6, AU-2 | Removing static authenticators; service identification and authentication; least privilege; logging of exchanges |
| CIS Controls v8.1 | Control 5, Control 6 | Service account inventory and lifecycle; granting and revoking access for service accounts |
| MITRE ATT&CK | T1098.001 Additional Cloud Credentials; T1078.004 Valid Accounts: Cloud Accounts | An added federated credential or provider is a new credential path; a loose trust yields valid cloud sessions |
| OWASP Non-Human Identities Top 10 | NHI6:2025, NHI7:2025 | Insecure cloud deployment configurations (unrestricted subjects); long-lived secrets that federation replaces |
Common failure patterns
- Keys left behind: the workload federates but the old key still works. The Ultralytics PyPI compromise combined a GitHub Actions injection with a leftover long-lived publishing token.
- Secrets still in the pipeline: the tj-actions compromise dumped stored CI/CD secrets into build logs; with federation, what leaks is a token that expires.
- Organisation-wide subjects:
repo:my-org/*passes the AWS check but lets every repository in the organisation reach a production role. - Shared cluster pools: development and production GKE clusters in one project share identities, or a development cluster issuer is trusted by a production role.
- Uncontrolled credential writers: too many owners can add federated credentials. The Storm-2949 Azure intrusion shows why write access to service principal credentials is a pivot point.
- Silent logging gaps: Google Data Access logs for STS never enabled, so no one can say which external subject used which pool.
Practitioner checklist
- Inventory every IAM OIDC provider, Entra federated identity credential and Google pool provider, each with an owner and purpose.
- Pin issuer, audience and subject on every trust; reject wildcard subjects and pool-wide bindings in policy as code.
- Add immutable claims (
repository_id,repository_owner_id,job_workflow_ref) to CI/CD conditions. - Bind production roles to protected environments and give pull request jobs separate read-only identities.
- Separate Kubernetes clusters of different trust levels into separate pools or projects, and prefer EKS Pod Identity on EKS.
- Restrict who can add federated credentials or create providers, and deny creation outside approved scopes with Azure Policy and IAM controls.
- Enable Google Data Access logs for IAM and STS, and alert on new or changed providers and federated credentials in all clouds.
- Deactivate, then delete, every static key a federated workload replaces, and block new key creation.
- Test negative cases (other branch, repository, namespace, cluster) whenever a trust is created or changed.
Standards and references
- IETF: RFC 8693 OAuth 2.0 Token Exchange
- IETF: RFC 7523 JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants
- AWS: Create a role for OpenID Connect federation
- Microsoft Learn: Important considerations and restrictions for federated identity credentials
- Google Cloud: Configure Workload Identity Federation with other identity providers
- GitHub Docs: OpenID Connect reference
- Kubernetes: Configure Service Accounts for Pods
- Google Cloud: About Workload Identity Federation for GKE
Related NHI Mgmt Group resources: Cloud Workload Identity Guide · CI/CD Pipeline Identity Security Guide · Kubernetes NHI Security Guide · NHI Authentication Guide