Normal view

Received — 4 September 2026 posts from Frontend, drupal, Panama, reactjs, devops, selfhosted, webhosting, Wordpress, web_design, webdev, PHP, technology, ProgrammerHumor, CRM

A quick guide and gotchas for GitHub OIDC and avoid using AWS permanent credentials in GitHub Actions

I have been aggressively migrating from AWS permanent credentials to OIDC in GitHub Actions, mainly for deploying to ECS.

I know GitHub Actions were supporting OIDC for a while now. But the pressure on compliance is the reason for this migration.

If you are new to OpenID Connect (OIDC), it allows GitHub runners to mint short-lived (15–60 min) STS tokens on-the-fly with zero stored secrets.

Here’s a quick breakdown of how it works, the Terraform/OpenTofu setup, and the subtle gotchas that I faced.

1. How It Works Under the Hood

  1. When your workflow job starts with id-token: write, GitHub's OIDC service generates a cryptographically signed JSON Web Token (JWT).
  2. The aws-actions/configure-aws-credentials action sends this JWT to AWS STS via sts:AssumeRoleWithWebIdentity.
  3. AWS validates GitHub's signature, checks your IAM Role's Trust Policy (to ensure the token came from your exact repo and branch), and returns temporary STS credentials.

2. The Infrastructure Setup (Terraform / OpenTofu)

You only need two AWS resources: an OIDC Provider and an IAM Role with a Trust Policy.

hcl # 1. The GitHub OIDC Identity Provider resource "aws_iam_openid_connect_provider" "github" { url = "https://token.actions.githubusercontent.com" client_id_list = ["sts.amazonaws.com"] thumbprint_list = [ "6938fd4d98bab03faadb97b34396831e3780aea1", "1c58a3a8518e8759bf075b76b750d4f2df264fcd" ] } # 2. IAM Role with Scoped Trust Policy resource "aws_iam_role" "github_deploy_role" { name = "github-actions-deploy-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Federated = aws_iam_openid_connect_provider.github.arn } Action = "sts:AssumeRoleWithWebIdentity" Condition = { StringEquals = { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { # Restrict exclusively to your repository & branch/tags "token.actions.githubusercontent.com:sub" = "repo:your-username/your-repo:*" } } }] }) }

3. The GitHub Actions Workflow

In your .github/workflows/deploy.yml

name: Deploy to AWS on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write # CRITICAL: required to request the OIDC JWT contents: read steps: - name: Checkout code uses: actions/checkout@v4 - name: Configure AWS Credentials via OIDC uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy-role aws-region: us-east-1 - name: Verify Authentication run: aws sts get-caller-identity 

Three real-world gotchas that will save you hours

If you get Error: Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity, check these 3 things:

  1. Case Sensitivity in the sub claim: AWS IAM condition strings are case-sensitive. If your GitHub repo or username uses mixed casing (e.g. MyOrg/Repo), make sure your IAM sub condition matches the exact casing GitHub sends in the token. Using wildcard matching (repo:MyOrg/Repo:*) helps avoid exact ref string mismatch issues.
  2. Job-Level vs. Workflow-Level Permissions: Always set permissions: id-token: write on the specific job, not just globally at the top of the YAML file. Some runner configs don't inherit top-level permissions to nested jobs.
  3. CA Thumbprints: Don't dynamically query GitHub's leaf certificate for thumbprints in Terraform—they change frequently with CDN updates. Use GitHub's official intermediate root CA thumbprints:
    • 6938fd4d98bab03faadb97b34396831e3780aea1
    • 1c58a3a8518e8759bf075b76b750d4f2df264fcd

Summary

  • No stored secrets in GitHub settings.
  • No key rotation schedules to manage.
  • Granular security. You can restrict deployment roles to specific branches or environments.

Are you already using OIDC for your pipelines, or are you still relying on IAM users? Curious how folks here handle multi-account / cross-account OIDC setups.

submitted by /u/SeaworthinessHour233 to r/devops
[link] [comments]
❌