how to set up short-lived credentials for CI
How to give CI jobs short-lived credentials instead of long-lived secrets: OIDC federation from GitHub Actions to your cloud, dynamic secrets from a vault, and scoped permissions per workflow. Use when a static deploy key has lived too long. Triggers: 'short-lived CI credentials', 'OIDC GitHub Actions AWS'. Not for: local dev credentials, long-lived service accounts.
how to set up short-lived credentials for CI
TL;DR
Stop putting long-lived cloud keys in CI secrets. Use OIDC federation so each workflow run mints a short-lived credential that dies when the job ends, or use your vault's dynamic secrets. The setup is a trust policy on the cloud side plus a permissions tweak on the CI side, and then there is nothing to rotate or leak.
how to set up short-lived credentials for CIUse this when
- A static deploy key or cloud access key has lived in CI secrets for way too long
- You are setting up a new pipeline and want to do it right from the start
- An audit flagged long-lived CI credentials
- A CI secret leaked and you want the replacement to be better
Not for this skill when
- You need credentials on a developer laptop (different problem)
- Your CI runs fully on-prem with no cloud access (static secrets may be fine there)
- You are looking for general CI security hardening (broader topic)
Steps
1. Create the OIDC trust on the cloud side
Tell your cloud provider to trust tokens from your CI. In AWS this is an IAM role with a trust policy pointing at your CI's OIDC issuer; other clouds have equivalents.
aws iam create-role --role-name ci-deploy --assume-role-policy-document file://trust-policy.jsonExpected: the role exists. The trust policy should pin the exact repo (something like repo:your-org/your-repo with a ref qualifier), not your whole org, or any repo can mint creds.
2. Grant the workflow permission to request the OIDC token
In GitHub Actions, the workflow needs the OIDC permission under permissions. Without it, the token request fails.
permissions:
contents: readExpected: the workflow runs. The OIDC permission is the one GitHub names id-token, set to write; add it alongside contents read. If the job fails with a token error, this permission is the first thing to check.
3. Assume the role in the workflow instead of using stored keys
Use the official cloud action to exchange the OIDC token for short-lived credentials. No static keys in CI secrets at all.
- name: configure cloud credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::[account id]:role/ci-deploy
aws-region: [region]Expected: subsequent steps can call cloud APIs, and the credentials expire when the job ends. Check the CI secrets list afterward: no cloud keys should remain.
4. Scope the role's permissions tightly
The role should allow exactly what the pipeline does and nothing else. Start from what the deploy actually needs.
aws iam get-role --role-name ci-deploy --query "Role.AssumeRolePolicyDocument"Expected: the trust document shows only your repo. Attach a permissions policy limited to the deploy targets; use Access Analyzer or CloudTrail to trim what the job never calls.
Variant: dynamic secrets from a vault
If you use HashiCorp Vault or similar, skip OIDC and have CI request dynamic cloud credentials from the vault with a short TTL. Same outcome: nothing static to leak, and the vault audit log shows every issuance.
5. Delete the old static credentials
The migration is not done until the long-lived keys are gone. Remove them from CI secrets and revoke them at the provider.
echo "CI settings: secrets section, delete the old cloud key; provider console: revoke the old key; then run a dry-run deploy"Expected: a dry-run deploy succeeds using only the OIDC path, and the old key returns unauthorized if tested. If anything still references the old secret name, the dry run will tell you.
Why this happens
Static CI credentials are copied into every run, logged in debug output, and forgotten in repo settings. They also never expire, so a leak from two years ago still works. Short-lived credentials bound to a single workflow run shrink the blast radius to minutes and remove rotation from your todo list entirely.
Edge cases and pitfalls
- The trust policy must pin the repo and ideally the branch or environment; a loose subject claim lets any repo in the org assume the role.
- Some older CI actions do not support OIDC; upgrade them before migrating.
- Debugging OIDC failures is mostly checking three things: the permissions block, the trust policy subject, and the role ARN.
- If your pipeline needs credentials that outlive one job (like a multi-hour deploy), set the session duration explicitly; the default is one hour.
- Do not forget scheduled workflows and Dependabot runs; they need the same treatment or they break when you delete the static keys.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_4IfbvDfpLlaWsZ-PbB638w
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.