Yeda AI Tips · #167

Español

Replace Long-Lived AWS Keys With OIDC

Your CI has AWS keys that never expire. Attackers know that too.

Most pipelines still authenticate to AWS with a long-lived access key ID and secret stored as a CI secret. That pair is a standing target: it works from anywhere, it works forever, and nothing about using it looks abnormal. Leak it once, in a log line, a forked workflow, or a compromised action, and it keeps working until a human notices and rotates it. OpenID Connect (OIDC) removes the stored credential entirely.

Why standing keys are the problem

A stored access key is a bearer credential with no expiry and no context. Whoever holds the string is you. The common leak paths are boring and constant:

Because the key never expires, detection is the only defense, and detection is slow. You are betting your cloud account on nobody making a mistake, indefinitely.

The mechanism: OIDC role assumption

With OIDC, your CI provider (GitHub Actions, GitLab, etc.) issues a signed, short-lived identity token for each workflow run. You configure an IAM role in AWS that trusts that provider and restricts which repository, branch, or environment may assume it. At run time the workflow exchanges the token for temporary credentials via AWS STS.

# GitHub Actions
permissions:
  id-token: write        # allow the workflow to request the OIDC token
  contents: read

steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/ci-deploy
      aws-region: us-east-1

No aws-access-key-id or aws-secret-access-key anywhere. The trust policy on the IAM role scopes it down so only your repo on your branch can assume it:

{
  "Condition": {
    "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" },
    "StringLike": { "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main" }
  }
}

The payoff

Static keysOIDC role assumption
Stored secretaccess key + secret in CInothing stored
Lifetimeuntil manually rotatedminutes (STS session)
Scopefull user, from anywhereone role, one repo/branch
Leak blast radiusworks foreveralready expired

Nothing is stored, so there is nothing to leak. The credentials expire on their own, so a stolen token is worthless minutes later. Once OIDC is live, delete the static keys.

Power moves

Resources

Shipping AI or cloud systems? Yeda AI audits and hardens production LLM and container pipelines. Talk to us · Read the blog