Introduction
Traditional CI/CD pipelines often rely on long-lived AWS access keys stored as GitHub secrets, which introduces risks such as secret exposure and poor traceability. With GitHub Actions' support for OpenID Connect (OIDC), you can authenticate securely to AWS without static credentials.
Source Code link: https://github.com/ravindrasinghh/github-actions-s3-workshop/blob/master/.github/workflows/deploy-to-s3.yml
we will walk through setting up an automated deployment pipeline that takes your static website from GitHub repository to live S3 hosting with just a git push.
The Problem with Traditional Approaches
Security Challenges with Access Keys:
- Long-lived credentials stored in GitHub secrets
- Risk of credential exposure if secrets are compromised
- Manual rotation required for security compliance
- Broad permissions often granted for simplicity
- No audit trail of which specific workflow used credentials
The OIDC Solution:
- No stored credentials in GitHub
- Temporary tokens with automatic expiration
- Fine-grained permissions per repository/branch
- Complete audit trail of all AWS actions
- Principle of least privilege enforcement
How OIDC Works with GitHub Actions and AWS
Authentication Flow:
- GitHub Actions requests an OIDC token from GitHub's OIDC provider
- Token contains claims about the repository, branch, and workflow
- AWS STS validates the token against the configured trust policy
- Temporary credentials are issued for the specified IAM role
- GitHub Actions uses these credentials to access AWS services
Step-by-Step Implementation
Step 1: Create an OIDC Identity Provider in AWS
1.Open the IAM console in your AWS account.
- In the left-hand navigation, click Identity providers.
- Choose Add provider.
- For Provider type, select OpenID Connect.
- For Provider URL, enter: https://token.actions.githubusercontent.com
- For Audience, enter: sts.amazonaws.com
Step 2: Assign a Role
Once the OIDC provider is created, click "Assign role" or "Create new role" to configure access.
Click Next to proceed.
Step 3: Configure Web Identity Trust
- On the Trusted entity type page, choose Web identity.
- For Identity provider, select the one you just created.
Fill in:
- GitHub Organization/Username (e.g., ravindrasinghh)
- Repository name (e.g., github-actions-s3-workshop)
- Branch name (e.g., master)
Click Next.
Step 4: Attach Permissions to the Role
- Choose either a Managed policy or create a Custom policy.
- For demonstration purposes, can use AmazonS3FullAccess.
⚠️ In production, use least privilege policies instead of full access.
Click Next.
Step 5: Name and Create the Role
- Provide a Role name (e.g., GitHubOIDCRole)
- Add an optional description for future reference.
- Review the trust policy and click Create Role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::434605749312:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:ravindrasinghh/github-actions-s3-workshop:ref:refs/heads/master"
}
}
}
]
}
This policy ensures:
- Only workflows from the ravindrasinghh/argocd repository on the master branch can assume the role.
- Only tokens with audience sts.amazonaws.com are accepted.
Key Security Features:
-
aud
condition ensures tokens are intended for AWS STS -
sub
condition restricts access to specific repository and branch -
StringLike
allows for flexible branch matching if needed
Step 4: Update GitHub Actions Workflow for OIDC
Update .github/workflows/deploy-to-s3.yml with:
name: Deploy Static Website to S3
on:
push:
branches: [ main ]
workflow_dispatch: # Allows manual triggering
# OIDC permissions for keyless authentication
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
# No build step needed for this simple static website
# Just update the deployment timestamp in the JavaScript file
- name: Update deployment timestamp
run: |
echo "// Updating timestamp for deployment on $(date)" >> js/script.js
echo "// Deployment ID: ${{ github.run_id }}" >> js/script.js
# # Configure AWS credentials
# - name: Configure AWS credentials
# uses: aws-actions/configure-aws-credentials@v1
# with:
# aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
# aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# aws-region: "ap-south-1"
# OIDC/IRSA Authentication - No more access keys!
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: "arn:aws:iam::434605749312:role/GitHubOIDCRole"
role-session-name: GitHubActions-Backend-${{ github.run_id }}
aws-region: "ap-south-1"
# Deploy to S3 bucket - directly sync the repository contents
- name: Deploy to S3
run: |
aws s3 sync ./ s3://${{ secrets.S3_BUCKET_NAME }}/ \
--delete \
--exclude ".git/*" \
--exclude ".github/*" \
--exclude "README.md"
Troubleshooting Common Issues
1. "Incorrect token audience" Error
Cause: Trust policy audience mismatch
Solution: Ensure audience is exactly sts.amazonaws.com
(no trailing dots)
2. "No permission to assume role" Error
Cause: Trust policy subject condition too restrictive
Solution: Verify repository name and branch in trust policy
3. "OIDC provider not found" Error
Cause: OIDC provider not created or incorrect ARN
Solution: Verify OIDC provider exists and ARN is correct
4. Workflow permissions Error
Cause: Missing OIDC permissions in workflow
Solution: Add id-token: write
and contents: read
permissions
By using OIDC with IAM roles, you enhance the security posture of your GitHub Actions workflows. This is the modern, recommended way to connect GitHub to AWS — eliminating the risks of leaked secrets and manual credential management.
Top comments (0)