
Table of Contents
Jump to a section
Introduction
GitHub Actions is one of the best CI/CD platforms out there.
It's easy to get started, powerful, and comes with a generous free tier for build minutes. It's fast too. You don't need to bootstrap containers that add overhead like AWS CodeBuild and CodePipeline do.
Configuring pipelines and jobs is simpler as well.
The catch is that GitHub Actions doesn't natively integrate with AWS like CodeBuild does (unless you run your own build agents, which most people don't).
Luckily, OIDC makes it possible to connect GitHub Actions with one or multiple AWS accounts in just a few steps.
No access keys to store. No credentials to rotate. Just secure, temporary access whenever your workflow runs.

IAM on One Page (No Fluff)
Secure your AWS resources. Our IAM cheat sheet covers roles, policies, and permissions - everything you need for proper access control.
HD quality, print-friendly. Stick it next to your desk.
What is OIDC Authentication?
OIDC stands for OpenID Connect.
It's a protocol that lets one service verify your identity without sharing credentials. Think of it like a secure handshake between GitHub and AWS.
When your GitHub Actions workflow runs, GitHub acts as the identity provider. It generates a short-lived token that proves the workflow is legitimate. AWS checks this token, verifies it came from GitHub, and grants temporary access based on the permissions you've configured.
The verification process also checks which repository the request came from. You configure exactly which repos are allowed to access your AWS account. Any workflow from an unauthorized repository gets blocked automatically.

No static credentials. No secrets stored in your repository. The token expires automatically after the job finishes.
This makes OIDC perfect for CI/CD pipelines where you need AWS access but don't want to manage long-lived credentials.
We wrote a detailed guide to OIDC if you want to understand the protocol more deeply.
Prerequisites
You need two things to follow along:
- A GitHub repository where you want to run workflows
- An AWS account where you want to deploy or access resources
No previous IAM or OIDC knowledge required.
Step 1: Create an OIDC Identity Provider in AWS
We'll use Pulumi for this guide.
Pulumi is an Infrastructure as Code framework that lets you define cloud resources using your favorite programming language instead of YAML or custom DSLs. We're using TypeScript here, but you could also use Python, Go, or C#.
The first step is creating an OIDC identity provider in AWS that trusts GitHub.
This tells AWS that tokens from GitHub's identity service are legitimate.
const githubOidcProvider = new aws.iam.OpenIdConnectProvider('GitHubOidcProvider', {
url: 'https://token.actions.githubusercontent.com',
clientIdLists: ['sts.amazonaws.com'],
thumbprintLists: ['6938fd4d98bab03faadb97b34396831e3780aea1'],
});
The URL points to GitHub's OIDC token service.
The client ID sts.amazonaws.com is what AWS expects when workflows request temporary credentials.
The thumbprint validates GitHub's SSL certificate.
Step 2: Create an IAM Role for GitHub Actions
Next, create an IAM role that GitHub Actions will assume.
This role connects to the OIDC provider we just created.
const githubActionsRole = new aws.iam.Role('GitHubActionsProductPipelineRole', {
name: 'my-app-prod-github-role',
assumeRolePolicy: githubOidcProvider.arn.apply((oidcArn) =>
JSON.stringify({
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Federated: oidcArn,
},
Action: 'sts:AssumeRoleWithWebIdentity',
// Trust policy conditions will be added in the next step
},
],
}),
),
description: 'Role for GitHub Actions from awsf-infra repository',
});
The role name can be whatever you want.
The important part is the assumeRolePolicy which defines the trust relationship.
Step 3: Configure the Trust Policy
The trust policy is where the security magic happens.
You need to add a Condition block to the assume role policy that specifies which repositories can use this role.
Condition: {
StringEquals: {
'token.actions.githubusercontent.com:aud': 'sts.amazonaws.com',
},
StringLike: {
'token.actions.githubusercontent.com:sub': [
'repo:awsfundamentals-hq/awsf-infra:*',
],
},
}
The StringEquals condition ensures the token is meant for AWS STS.
The StringLike condition is what locks down access to specific repositories.
Replace awsfundamentals-hq/awsf-infra with your own organization and repository name.

The :* wildcard allows any branch or tag from that repository.
You can make this more restrictive by specifying exact branches like repo:your-org/your-repo:ref:refs/heads/main to only allow the main branch.
Step 4: Attach Permissions to the Role
The role needs permissions to actually do something in AWS.
You can grant access to any AWS service or resource your workflow needs. In our case, we want GitHub Actions to list and upload files to an S3 bucket.
const s3UploadPolicy = new aws.iam.Policy('GitHubActionsS3UploadPolicy', {
description: 'Allows GitHub Actions to upload files to S3',
policy: JSON.stringify({
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['s3:PutObject', 's3:GetObject', 's3:ListBucket'],
Resource: ['arn:aws:s3:::my-bucket-name', 'arn:aws:s3:::my-bucket-name/*'],
},
],
}),
});
Then attach the policy to the role.
new aws.iam.RolePolicyAttachment('GitHubActionsS3UploadPolicyAttachment', {
role: githubActionsRole.name,
policyArn: s3UploadPolicy.arn,
});
Replace the actions and resources with whatever your workflow needs. Follow the principle of least privilege. Only grant the minimum permissions required.
Step 5: Update Your GitHub Actions Workflow
Now that the AWS infrastructure is set up, you need to configure your GitHub Actions workflow to use it.
The aws-actions/configure-aws-credentials action handles the OIDC authentication for you.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/my-app-prod-github-role
role-session-name: github-actions-${{ github.run_id }}
aws-region: us-east-1
Replace the role ARN with the ARN of the role you created.
The role-session-name is just a unique identifier for the session.
Using github.run_id makes it easy to trace which workflow run assumed the role.
The uses directive tells GitHub Actions to run the official AWS credentials action.
This action exchanges the GitHub OIDC token for temporary AWS credentials automatically.
After this step runs, any AWS CLI commands or SDK calls in subsequent steps will use those credentials.
Here's an example that lists the contents of your S3 bucket.
- name: List S3 bucket contents
run: |
aws s3 ls s3://my-bucket-name/
That's it. No secrets to configure. No credentials to rotate. The authentication happens automatically through OIDC.
Security Best Practices
Keep your setup secure by following these practices:
- Restrict repository access: Use specific repository names in your trust policy instead of wildcards. Lock it down to exact branches like
ref:refs/heads/mainif workflows only run from main. - Grant minimal permissions: Only attach IAM policies with the exact actions and resources your workflow needs. Avoid using
*for actions or resources. - Rotate the OIDC thumbprint: GitHub's SSL certificate can change. Keep the thumbprint updated to prevent authentication failures.
- Monitor CloudTrail logs (advanced): Track when and how the role is assumed. This gives you visibility into all authentication attempts and role usage.
- Set up alerting: Configure CloudWatch alarms or EventBridge rules to alert you on unexpected usage patterns or failed authentication attempts.
Conclusion
Connecting GitHub Actions to AWS with OIDC is simple and has become an industry standard.
You created an OIDC provider, set up an IAM role with a trust policy, attached the necessary permissions, and configured your workflow. Five steps total.
GitHub Actions comes with a generous free tier for build minutes. Combined with secure AWS access through OIDC, you have everything you need to start a proper continuous delivery process.
Now go build something.

IAM on One Page (No Fluff)
Secure your AWS resources. Our IAM cheat sheet covers roles, policies, and permissions - everything you need for proper access control.
HD quality, print-friendly. Stick it next to your desk.
