Your CI runs Terraform against AWS with no long-lived access keys stored anywhere. How does the AWS provider obtain credentials in that setup, and what has to exist for it to work?
answer
- short-lived token in, session out
- no stored secret to rotate
- issuer registered once per account
- the trust policy conditions carry the security
- the environment route needs no HCL
basics
~20 sThe CI platform issues the job a short-lived signed OIDC token, and the AWS provider exchanges it for a temporary role session through STS web-identity federation. It needs the CI issuer registered as an OIDC identity provider in the account and a role whose trust policy accepts tokens from that issuer.
solid answer
~50 sInstead of a stored key, the pipeline gets an identity at runtime. The CI platform mints a short-lived signed JSON Web Token describing the job and writes it where the job can read it; the AWS provider then calls STS to trade that token for temporary credentials — the `assume_role_with_web_identity` block, with `role_arn` and `web_identity_token_file`, or equivalently the ambient `AWS_ROLE_ARN` and `AWS_WEB_IDENTITY_TOKEN_FILE` variables that the provider's chain already understands. On the AWS side two things must exist: the CI provider's issuer registered as an IAM OIDC identity provider in the account, and a role whose trust policy accepts that issuer and, critically, conditions on the token's claims so only the intended repository, branch or environment can assume it. The payoff is that there is no durable secret to leak, revoke or rotate — every run has its own short-lived, attributable session.
code
hcl · 9 linesprovider "aws" {
region = "eu-west-1"
assume_role_with_web_identity {
role_arn = "arn:aws:iam::111122223333:role/terraform-ci"
session_name = "terraform-ci"
web_identity_token_file = "/var/run/secrets/ci/token"
}
}go deeper
Know that credentials can arrive at runtime rather than being stored: the pipeline receives a short-lived token proving which job it is, and that token is exchanged for temporary cloud credentials.
Describe the exchange and both ways to configure it — the assume_role_with_web_identity block, or the AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE environment variables that the provider's chain already reads.
Put the emphasis where the risk is: a trust policy that accepts the issuer without conditioning on audience and subject claims is broadly assumable. Also cover session lifetime versus apply duration, backend credentials, and tracing a run through CloudTrail.
Own the federation design across the estate: where the identity provider is registered, how roles are scoped per repository and environment, how access is revoked when a repository is retired, and what evidence proves no long-lived cloud key exists in any pipeline.
## The exchange, step by step 1. The CI job starts. The platform signs a JWT asserting facts about the job — which repository, which branch or environment, which workflow — and makes it available to the job, usually as a file path plus an environment variable. This side is the CI platform's own configuration. 2. Terraform configures the AWS provider. The provider takes the token and calls STS's web-identity assume-role operation with a role ARN. 3. STS validates the token's signature against the registered OIDC identity provider's published keys, checks the audience, and evaluates the target role's trust policy against the token's claims. 4. If it passes, STS returns temporary credentials. The provider uses them for the rest of the run. Nothing durable existed at any point. The token is valid for minutes; the resulting session for an hour or so. ## Configuring the provider side Two equivalent routes, and knowing both is worth a mark: ```hcl provider "aws" { region = "eu-west-1" assume_role_with_web_identity { role_arn = "arn:aws:iam::111122223333:role/terraform-ci" session_name = "terraform-ci" web_identity_token_file = "/path/to/token" } } ``` Or an empty provider block, letting the standard chain pick up `AWS_ROLE_ARN` and `AWS_WEB_IDENTITY_TOKEN_FILE` from the environment. The second is usually better: the configuration stays portable, and a developer running the same code locally with a profile is unaffected. The same mechanism, incidentally, is how a Kubernetes pod with a projected service-account token gets AWS credentials — it is not a CI-specific trick. ## What must exist in the account - **An IAM OIDC identity provider** for the CI platform's issuer URL, registered once per account (or in a central account that the workload roles trust). - **A role with a web-identity trust policy** that references that provider. - **Conditions on the token's claims.** This is the part that carries all the security. A trust policy that accepts *any* token from the issuer lets anyone with an account on that CI platform assume your role. It must condition on the audience claim and on the subject claim, scoping to your organisation and repository, and usually further to a specific branch or deployment environment. "We use OIDC" with an unscoped subject condition is a worse posture than a well-guarded static key, and an interviewer may well probe exactly there. ## Operational consequences - **Revocation changes shape.** There is no key to delete. You remove access by editing the trust policy or deleting the role, and it takes effect for new sessions immediately. Existing sessions run until they expire. - **Session lifetime versus apply duration.** Same trap as any assumed role: a long apply can outlive its session and fail partway through. Size the session for the longest realistic apply, or split the root module. - **The state backend needs its own path.** Remote state authenticates independently of the providers; it needs credentials that work too, which in this setup usually means the same federated session having access to the state store, or its own role configuration. - **Fork and untrusted-contributor exposure.** Whether a pull request from outside the organisation can obtain a token at all is the CI platform's configuration, but the AWS-side defence is the same one that matters anyway: a trust policy whose subject condition excludes those contexts. Defence on both sides. - **Auditing.** The session name and the role show in CloudTrail. Choose a session name that identifies the pipeline so a destructive action can be traced back to a run. ## Why teams do this A static CI key is the highest-value credential most organisations have: it usually has broad permissions, it lives in a secret store many people can administer, it is copied into logs by accident, and rotating it means a coordinated change across pipelines. Federation removes the object entirely. What replaces it is a *policy* problem — getting the trust conditions right — which is reviewable, version-controllable and far less prone to silent leakage than a shared string. ## The interview point Say the exchange out loud: short-lived signed token in, temporary session out, no stored secret. Then name the two artifacts that must exist in the account, and — the senior differentiator — put the weight on the trust policy's claim conditions rather than treating "we enabled OIDC" as the answer.
- A role's web-identity trust policy names the CI issuer but sets no condition on the subject claim. What is the exposure?Any job on that CI platform — including one in a stranger's account — can present a validly signed token from the same issuer and assume your role. The signature check only proves the issuer minted the token, not who for. Conditions on the audience and subject claims are what bind the role to your organisation, repository and branch or environment.
- How do you revoke a federated pipeline's access, given there is no key to delete?You change the authorization, not the credential: tighten or remove the role's trust policy conditions, or delete the role. New sessions are refused immediately. Sessions already issued remain valid until they expire, which is the argument for keeping session durations modest. Compare that with a leaked static key, where revocation requires finding and rotating every copy.
- Does the remote state backend get credentials from the same federated session?Not automatically — the backend resolves credentials through its own configuration and the ambient environment, independently of provider blocks. In practice the federated session is usually also granted access to the state store, or the backend is given its own role settings. Either way it is a separate authorization path that must be provisioned deliberately.
saying these in an interview costs you the question
- Enabling OIDC is secure regardless of the trust policy
- The token itself is the AWS credential
- You still need a fallback access key for the backend
- A federated session cannot expire mid-apply
- Only CI can use web-identity federation