Replacing Static AWS Keys with OIDC: A CI/CD Publisher Walkthrough
How to harden GitHub Actions CI/CD by migrating from static AWS credentials to OIDC, scoped to specific S3 prefixes and branches.
Static AWS credentials stored in GitHub Secrets represent a significant security liability. If compromised, they provide persistent access until manually revoked. A more secure approach is to migrate to OIDC (OpenID Connect), which provides temporary, scoped-down credentials for CI/CD workflows.
This walkthrough demonstrates how to implement a generic OIDC pattern scoped to a specific S3 prefix and a single branch.
The Problem: Persistent Credentials
Traditionally, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are used for automation. These keys are often overly permissive and valid indefinitely, making them high-value targets for attackers.
The Solution: GitHub Actions OIDC
With OIDC, GitHub acts as an Identity Provider (IdP). AWS is configured to trust GitHub, allowing specific repositories, branches, or environments to assume a dedicated IAM role.
Step 1: The IAM Trust Policy
The trust policy is the primary guardrail. It should be restricted to a specific repository and branch.
json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:my-organization/my-repository:ref:refs/heads/main" } } } ] } text
Step 2: Scoping S3 Permissions
To adhere to the principle of least privilege, the IAM role should only have access to the necessary S3 prefix.
json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject"], "Resource": "arn:aws:s3:::my-artifact-bucket/artifacts/*" } ] } text
Step 3: Workflow Configuration
In the GitHub Actions workflow, the id-token permission must be requested to enable the use of the OIDC token.
```yaml permissions: id-token: write # Required for requesting the JWT contents: read # Required for actions/checkout
jobs: publish: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4
1
2
3
4
5
6
7
8
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/ArtifactPublisherRole
aws-region: us-east-1
- name: Publish Artifacts
run: ./publish.sh --bucket my-artifact-bucket --prefix artifacts ```text
Benefits
- Elimination of Secret Rotation: There is no need to manually rotate static keys.
- Branch-Level Security: Access can be restricted so that only the
mainbranch (or other protected branches) can publish artifacts. - Temporal Access: Credentials are valid only for the duration of the job, significantly reducing the blast radius of a potential compromise.
Conclusion
Migrating to OIDC replaces static, high-risk credentials with a dynamic and verifiable identity flow. This shift significantly improves the security posture of any CI/CD pipeline.