Securely Authenticating to AWS from GitHub Actions Workflows
GitHub Actions Workflows have become the go-to solution for running CI/CD workflows for projects hosted on GitHub. Its seamless integration with GitHub repositories makes it a natural choice for automating tasks like building, testing, and deploying applications. For Developers deploying applications to AWS, a key challenge arises: How to securely access AWS services, such as Amazon Elastic Container Registry (ECR) for pushing Docker images or S3 buckets for uploading or downloading data?
The traditional approach for accessing AWS services involves creating an IAM user and generating access keys, which are then stored as secrets in GitHub. However, this method introduces risks, such as key leakage or the need to rotate credentials regularly.
A more secure and modern alternative is to leverage GitHub’s OpenID Connect (OIDC) provider. By configuring an OIDC trust relationship, GitHub Actions can assume temporary IAM roles in AWS, eliminating the need to manage long-lived access keys and enhancing security through short-lived credentials. This approach simplifies credential management while aligning with AWS best practices for secure access.
AWS Configuration
To enable secure authentication from GitHub Actions Workflows to AWS using OpenID Connect (OIDC), you need to configure specific resources in your AWS account. This section walks through setting up the OIDC provider, creating an IAM role, and assigning appropriate IAM policies to ensure secure and controlled access.
First, you need to set up the OIDC Provider. to establish a trust relationship with GitHub. In the AWS Management Console, navigate to the IAM service and select “Identity Providers”, then click “Add Provider”. Choose OpenID Connect as the provider type and use the following settings:
- Provider URL:
https://token.actions.githubusercontent.com
- Audience:
sts.amazonaws.com
These values allow AWS to trust GitHub’s OIDC provider for authentication. After adding the provider, AWS will verify the provider’s URL and store its metadata, enabling secure token exchange between GitHub Actions and AWS.
Next, you need to create an IAM role that the GitHub Actions Workflow will assume to access AWS resources. In the IAM console, go to “Roles” and click “Create Role”. Select “Web Identity” as the trusted entity type, then choose the OIDC provider you just created (token.actions.githubusercontent.com
). Specify the audience as sts.amazonaws.com
.
To ensure the role is only assumed by the intended GitHub repositories or branches, configure the trust relationship with a condition in the role’s trust policy. For example, to restrict access to a specific repository and branch, use the following trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>: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:<GITHUB_ORG>/<GITHUB_REPO>:*"
}
}
}
]
}
Replace <AWS_ACCOUNT_ID>
with your AWS account ID, <GITHUB_ORG>
with your GitHub organization or username and <GITHUB_REPO>
with the repository name. To be even more specific, you can further specify which branches and tags should be able to assume the role. This way you can ensure that only workflows from the specified repository and branches can assume the role.
Attach appropriate policies to the new role to grant it access to the AWS services that are needed for the role. Remember to adhere to the Least Priviledge Principle and only grant the permissions that are actually needed.
Terraform Template for setting up resources
Since using Infrastructure as Code (IaC) is a best practise for managing Cloud infrastructure, here’s the Terraform template as an example for setting up the necessary resources. In this example, the GitHub Actions Workflow gets permission to push Docker images to an ECR repository:
resource "aws_iam_openid_connect_provider" "github_oidc_provider" {
url = "https://token.actions.githubusercontent.com"
client_id_list = [
"sts.amazonaws.com"
]
}
resource "aws_iam_role" "github_actions_role" {
name = "GitHubActionsRole"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Federated = aws_iam_openid_connect_provider.github_oidc_provider.arn
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringLike = {
"token.actions.githubusercontent.com:sub" : "repo:<GITHUB_ORG>/<GITHUB_REPO>:*"
}
}
}
]
})
}
resource "aws_iam_role_policy" "github_action_ecr_authorization_policy" {
name = "ecr-authorizaton-policy"
role = aws_iam_role.github_action_role.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Sid = "AllowAuthorizationToECR",
Effect = "Allow",
Action = "ecr:GetAuthorizationToken",
Resource : "*"
}
]
})
}
resource "aws_iam_role_policy" "github_action_push_to_ecr_policy" {
name = "push-to-ecr-repository-policy"
role = aws_iam_role.github_action_role.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Sid = "AllowPushToECR",
Effect = "Allow",
Action = [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
Resource = <ECR_REPO_ARN>
}
]
})
}
Use this example as a starting point to set up the permissions that you need for GitHub Actions Workflow to access AWS services.
GitHub Actions Workflow Configuration
Once the AWS setup is complete, you need to configure your GitHub Actions Workflow to authenticate with AWS using the OIDC provider and interact with AWS services securely. This section covers setting up the necessary permissions, using the configure-aws-credentials
action for authentication.
Here’s a basic GitHub Actions Workflow that builds a Docker image and pushes it to a ECR repository on AWS. The Workflow is triggered whenever code is pushed to the main
branch.
name: Build and Push Docker Image
on:
push:
branches: [ "main" ]
permissions:
contents: read
id-token: write
jobs:
package:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>
aws-region: <AWS_REGION>
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to AWS ECR
uses: docker/login-action@v3
with:
registry: <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/<REPOSITORY_NAME>
tags: |
type=semver,pattern={{version}}
type=sha,suffix=-${{ github.run_number }}
- name: Build and push Docker Image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: $
labels: $
cache-from: type=gha
cache-to: type=gha,mode=max
The configure-aws-credentials
action will fetch short-lived access credentials and provide them in the context of the GitHub Actions Workflow. This way, any subsequent steps in the workflow can access AWS services as needed. In this example, the docker-login
action can use the credentials to sign in to ECR for pushing Docker images. In the same way, the AWS CLI - which is pre-installed in the GitHub Actions Runner - can be used to upload or download data from S3. Likewise, Terraform can be set up via the setup-terraform
action and the Workflow can apply Terraform templates to the AWS account.
Summary
By integrating GitHub Actions Workflows with AWS using OpenID Connect (OIDC), you can streamline your CI/CD pipelines while adhering to security best practices. This approach eliminates the risks associated with managing long-lived AWS access keys and simplifies credential management with temporary, role-based access. Whether you’re pushing Docker images to Amazon ECR, downloading data from S3, or interacting with other AWS services, the combination of GitHub’s OIDC provider and AWS IAM roles offers a secure and scalable solution.
To deepen your understanding, explore the official documentation on configuring OpenID Connect with GitHub Actions and the configure-aws-credentials action repository for advanced configuration options. For hands-on practice, try setting up a sample workflow in a test repository to push an image to ECR or perform other AWS operations. Start securing your CI/CD pipelines today by implementing OIDC-based authentication in your next GitHub Actions workflow!