Overview
The OIDC provider template creates the infrastructure needed for GitHub Actions to authenticate with AWS using OpenID Connect (OIDC). This eliminates the need for long-lived AWS access keys, providing a more secure authentication method for CI/CD pipelines.
The template creates:
- OIDC Provider — Establishes trust between AWS IAM and GitHub Actions
- IAM Role — Service role that GitHub Actions assumes during workflow execution
- Trust Policy — Controls which repositories and branches can assume the role
Template location
The template is located at templates/oidc-provider.yml in the starter kit repository.
Parameters
GithubActionsThumbprint
Type: CommaDelimitedList
Default: 6938fd4d98bab03faadb97b34396831e3780aea1
Thumbprint for GitHub Actions OIDC tokens. This validates the TLS certificate of GitHub's OIDC provider.
Default value: 6938fd4d98bab03faadb97b34396831e3780aea1 (current GitHub Actions thumbprint)
When to change: Only if GitHub updates their OIDC provider certificate (rare).
AudienceList
Type: CommaDelimitedList
Default: sts.amazonaws.com
Allowed audiences for OIDC tokens. The audience claim in the token must match this value.
Default value: sts.amazonaws.com (standard for AWS STS)
When to change: Only if you have specific token validation requirements.
SubjectClaimFilters
Type: CommaDelimitedList
Required: Yes
Most important parameter. Controls which repositories and branches can assume the IAM role.
Format patterns:
# Allow entire repository (any branch, any environment)
SubjectClaimFilters: repo:owner/repository:*
# Allow only main branch
SubjectClaimFilters: repo:owner/repository:ref:refs/heads/main
# Allow specific branch
SubjectClaimFilters: repo:owner/repository:ref:refs/heads/develop
# Allow any release branch
SubjectClaimFilters: repo:owner/repository:ref:refs/heads/release/*
# Allow pull requests
SubjectClaimFilters: repo:owner/repository:pull_request
# Allow GitHub Environment-specific deployments
SubjectClaimFilters: repo:owner/repository:environment:production
# Multiple filters (comma-separated)
SubjectClaimFilters:
- repo:owner/repository:ref:refs/heads/main
- repo:owner/repository:ref:refs/heads/develop
Security best practice: Use the most restrictive filter that meets your needs. For production environments, limit to specific branches.
Example for test environment:
# parameters/test/oidc-provider.yml
SubjectClaimFilters: repo:towardsthecloud/my-repo:ref:refs/heads/main
Path
Type: String
Default: /
IAM path for the service role. Useful for organizing roles in large organizations.
Examples:
/(default, root path)/github-actions//ci-cd/cloudformation/
ManagedPolicyARNs
Type: CommaDelimitedList
Default: arn:aws:iam::aws:policy/AdministratorAccess
AWS managed policies to attach to the service role. Controls what the GitHub Actions workflow can do in your AWS account.
Default: AdministratorAccess (full access - suitable for infrastructure deployment)
Alternative options:
# PowerUserAccess (everything except IAM)
ManagedPolicyARNs: arn:aws:iam::aws:policy/PowerUserAccess
# CloudFormation-only access
ManagedPolicyARNs: arn:aws:iam::aws:policy/AWSCloudFormationFullAccess
# Multiple policies
ManagedPolicyARNs:
- arn:aws:iam::aws:policy/AWSCloudFormationFullAccess
- arn:aws:iam::aws:policy/AmazonS3FullAccess
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
# Custom policy (create separately and reference)
ManagedPolicyARNs: arn:aws:iam::123456789012:policy/GitHubActionsCustomPolicy
Security consideration: For production environments, consider using least-privilege custom policies instead of AdministratorAccess.
Resources
GitHubIdentityProvider
Creates an IAM OIDC identity provider that establishes trust with GitHub Actions.
Type: AWS::IAM::OIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ThumbprintList: !Ref GithubActionsThumbprint
ClientIdList: !Ref AudienceList
Key properties:
- Url — GitHub Actions OIDC endpoint
- ThumbprintList — Validates GitHub's TLS certificate
- ClientIdList — Allowed audiences for tokens
GitHubActionsServiceRole
Creates the IAM role that GitHub Actions workflows assume.
Type: AWS::IAM::Role
Properties:
RoleName: GitHubActionsServiceRole
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Federated: !GetAtt GitHubIdentityProvider.Arn
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
"token.actions.githubusercontent.com:aud": !Ref AudienceList
StringLike:
"token.actions.githubusercontent.com:sub": !Ref SubjectClaimFilters
Trust policy conditions:
- StringEquals on aud — Token audience must match
AudienceList - StringLike on sub — Token subject must match
SubjectClaimFilters
These conditions ensure only authorized repositories/branches can assume the role.
Outputs
ServiceRoleARN
Value: !GetAtt GitHubActionsServiceRole.Arn
Returns the ARN of the created service role. Use this value in your GitHub Actions workflow:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsServiceRole
aws-region: us-east-1
Parameter file examples
Single repository, main branch only
# parameters/production/oidc-provider.yml
SubjectClaimFilters: repo:towardsthecloud/infrastructure:ref:refs/heads/main
ManagedPolicyARNs: arn:aws:iam::aws:policy/AdministratorAccess
Multiple branches
# parameters/test/oidc-provider.yml
SubjectClaimFilters:
- repo:towardsthecloud/infrastructure:ref:refs/heads/main
- repo:towardsthecloud/infrastructure:ref:refs/heads/develop
ManagedPolicyARNs: arn:aws:iam::aws:policy/AdministratorAccess
Multiple repositories (shared infrastructure account)
# parameters/shared/oidc-provider.yml
SubjectClaimFilters:
- repo:towardsthecloud/app1:ref:refs/heads/main
- repo:towardsthecloud/app2:ref:refs/heads/main
- repo:towardsthecloud/infrastructure:ref:refs/heads/main
ManagedPolicyARNs: arn:aws:iam::aws:policy/PowerUserAccess
Custom policy with least privilege
# parameters/production/oidc-provider.yml
SubjectClaimFilters: repo:towardsthecloud/infrastructure:ref:refs/heads/main
ManagedPolicyARNs: arn:aws:iam::123456789012:policy/GitHubActionsCloudFormationPolicy
Path: /github-actions/
Deployment
Initial deployment
Deploy the OIDC provider template first, before any other infrastructure:
# Deploy to test environment
rain deploy templates/oidc-provider.yml --config parameters/test/oidc-provider.yml
# Deploy to production environment
rain deploy templates/oidc-provider.yml --config parameters/production/oidc-provider.yml
Verification
After deployment, verify the stack was created:
# Check stack status
aws cloudformation describe-stacks --stack-name oidc-provider
# Get the service role ARN
aws cloudformation describe-stacks \
--stack-name oidc-provider \
--query 'Stacks[0].Outputs[?OutputKey==`ServiceRoleARN`].OutputValue' \
--output text
Testing the role
Test that GitHub Actions can assume the role:
# .github/workflows/test-oidc.yml
name: Test OIDC Authentication
on: workflow_dispatch
permissions:
id-token: write
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ vars.TEST_AWS_ACCOUNT_ID }}:role/GitHubActionsServiceRole
aws-region: ${{ vars.AWS_REGION }}
- name: Test AWS access
run: |
aws sts get-caller-identity
aws cloudformation list-stacks
Security best practices
1. Use restrictive SubjectClaimFilters
# Good: Specific branch
SubjectClaimFilters: repo:owner/repo:ref:refs/heads/main
# Bad: Too permissive
SubjectClaimFilters: repo:owner/repo:*
2. Separate roles per environment
Create different OIDC stacks for each environment:
parameters/
├── test/
│ └── oidc-provider.yml # GitHubActionsServiceRole-Test
├── staging/
│ └── oidc-provider.yml # GitHubActionsServiceRole-Staging
└── production/
└── oidc-provider.yml # GitHubActionsServiceRole-Production
Modify the template to include environment in the role name:
RoleName: !Sub GitHubActionsServiceRole-${Environment}
3. Use least-privilege policies
Instead of AdministratorAccess, create custom policies:
# Custom policy with only required permissions
ManagedPolicyARNs: arn:aws:iam::123456789012:policy/GitHubActionsMinimalPolicy
Example minimal policy for CloudFormation deployment:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:*",
"s3:*",
"iam:GetRole",
"iam:PassRole"
],
"Resource": "*"
}
]
}
4. Enable CloudTrail logging
Monitor all actions taken by the GitHub Actions role:
# View recent API calls made by the role
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=Username,AttributeValue=GitHubActionsServiceRole \
--max-results 50
5. Rotate credentials regularly
Although OIDC doesn't use long-lived credentials, periodically review:
- SubjectClaimFilters (ensure only authorized repos/branches)
- Attached policies (remove unnecessary permissions)
- Role usage (check CloudTrail for suspicious activity)
Troubleshooting
Error: "Not authorized to perform sts:AssumeRoleWithWebIdentity"
Cause: SubjectClaimFilters doesn't match the GitHub Actions context.
Solution: Check your filter matches the repository and branch:
# In GitHub Actions, print the token subject claim
- name: Debug OIDC token
run: |
echo "Repository: ${{ github.repository }}"
echo "Ref: ${{ github.ref }}"
Update your SubjectClaimFilters to match.
Error: "OpenIDConnect provider not found"
Cause: OIDC provider stack not deployed or deployed to wrong account.
Solution: Verify the stack exists:
aws cloudformation describe-stacks --stack-name oidc-provider
If not found, deploy the template.
Error: "Role does not have sufficient permissions"
Cause: Attached policies don't include required permissions.
Solution: Update ManagedPolicyARNs or add custom inline policies:
ManagedPolicyARNs:
- arn:aws:iam::aws:policy/AdministratorAccess
OIDC thumbprint is outdated
Symptom: Authentication suddenly stops working.
Cause: GitHub updated their OIDC provider certificate.
Solution: Update the thumbprint and redeploy:
# Get current GitHub OIDC thumbprint
openssl s_client -servername token.actions.githubusercontent.com \
-connect token.actions.githubusercontent.com:443 < /dev/null 2>/dev/null | \
openssl x509 -fingerprint -noout | \
cut -d'=' -f2 | \
tr -d ':' | \
tr '[:upper:]' '[:lower:]'
Related documentation
- Environments — Configure multiple deployment environments
- CI/CD Workflow — How GitHub Actions uses OIDC authentication
- Parameters reference — Parameter file structure and usage