Deploying to AWS using GitHub Actions via OpenID Connect [OIDC]
Learn how to use GitHub Actions and OIDC for safe AWS deployment.
In today's fast-paced development landscape, implementing secure, automated CI/CD pipelines is crucial for efficient software delivery. Traditionally, deploying to AWS using GitHub Actions required creating an IAM user (service account) with key credentials (Access Key and Secret Key).
These credentials would then be stored in GitHub as secrets to enable the Actions workflow. However, this approach posed significant security risks. The stored secrets could remain valid indefinitely, often exceeding the recommended 90-day rotation period for credentials.
If compromised, especially if the credentials have elevated permissions, then malicious actors could exploit them to deploy unauthorized resources like crypto miners or access sensitive data, leading to severe security breaches.
With the integration of GitHub Actions and OpenID Connect (OIDC), deploying resources to AWS will become more secure. This publication walks you through deploying an S3 bucket to AWS using GitHub Actions and OIDC.
What Is OpenID Connect (OIDC)?
OIDC allows GitHub Actions to securely authenticate with AWS without relying on long-lived access keys. Instead, it leverages temporary credentials granted via an identity provider (IdP) trust relationship between AWS and GitHub.
This approach:
Reduces the risk of credential exposure.
Simplifies authentication management.
Facilitates least-privilege access with short-lived tokens.
Prerequisites:
An AWS account with IAM permission to create S3 Bucket.
Basic understanding of creating an AWS IAM role and its functionality.
Basic understanding of GitHub Actions.
Basic Understanding of OIDC OpenID Connector
GitHub repository for your project. Here is my Repository for this project
NOTE:
I’ve outlined two methods for configuring the OIDC Identity provider and connecting it to an IAM role in AWS. The first involves using the Management console, while the second involves utilizing a cloud-formation template provided in the subsequent steps below.
Step 1: Configure AWS OIDC Identity Provider
Create an Identity Provider in AWS:
Log into AWS Management Console:
Go to the IAM Service:
Select Identity Providers:
Click on Add Provider
Choose OpenID Connect, then add Provider Url and Audience. By default, this information is the same for everyone, as GitHub/AWS provides it.
For the provider URL: Use https://token.actions.githubusercontent.com
For the Audience Use sts.amazonaws.com
- FAQs - To add the GitHub OIDC provider to IAM, see the AWS documentation & official GitHub page action
Create an IAM Role for GitHub Actions:
Now that we've set up the Identity provider, we’ll create an IAM role with the specific permissions we want our GitHub action to have. We’ll also specify the name of the GitHub repository to which the role will grant permission. Finally, we’ll link the Identity provider to the IAM role we created.
Click to open the created identity provider
Click on the Assign Role button at the right corner of the screen
Chose Create a new role
Select “Web identity” as the trusted entity type. Then, fill out the form fields:
- GitHub organization
- GitHub repository
Click on NEXT.
Attached the required permission. In our use case, we will attach S3 full access permission.
Click on NEXT.
Provide the role name and description, and then click on Create role.
Using CloudFormation for Configuring OIDC Identity Provider in AWS
Open the CloudFormation Template File in this Repository
Access the CloudFormation YAML file
Update Role Name
Look for the section defining the IAM role in the template
Modify the
RoleName
property to match the desired role name.
Parameters:
RoleName:
Type: String
Default: "YourUpdatedRoleName"
Description: Name of the IAM role to be created
Update Repository Name
Locate the parameter, resource, or property specifying the repository name.
Replace it with the appropriate repository name.
# GitHub repository name in format owner/repo
RepoName:
Type: String
Default: "YourUpdatedRepoName"
Description: GitHub repository name in format owner/repo
Save the Changes
- Save the modified CloudFormation file locally.
Deploy the CloudFormation Template
- Use the AWS Management Console, AWS CLI, or AWS SDKs to deploy the template.
You have successfully deployed your CloudFormation stack! Everything is now set up, and your resources should be ready to use. 🎯
Step 2: Write Your GitHub Actions Workflow
In the below repository, you’ll find the GitHub action workflow and a readme file that explains how the GitHub action works and how to create your own.
Workflow Code
Create a new file .github/workflows/s3-deploy.yml
in your repository with the following content:
name: Deploy AWS S3 Bucket with OIDC authentication
on:
push
env:
AWS_REGION : "us-east-1"
AWS_ROLE_TO_ASSUME: "arn:aws:iam::{YOUR-AWS-ACCOUNT-ID}:role/github-actions-s3-oidc-role-dev"
REPOSITORY_NAME: "${{ github.actor }}"
BUCKET_NAME: "${{ github.actor }}-oidc-test-bucket"
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }}
role-session-name: s3-deploy-action-session
aws-region: ${{ env.AWS_REGION }}
- name: Check if bucket exists
id: check_bucket
run: |
if aws s3api head-bucket --bucket ${{ env.BUCKET_NAME }} 2>/dev/null; then
echo "Bucket ${{ env.BUCKET_NAME }} already exists"
echo "bucket_exists=true" >> $GITHUB_OUTPUT
else
echo "Bucket ${{ env.BUCKET_NAME }} does not exist"
echo "bucket_exists=false" >> $GITHUB_OUTPUT
fi
- name: Create S3 bucket
if: steps.check_bucket.outputs.bucket_exists == 'false'
run: |
aws s3api create-bucket \
--bucket ${{ env.BUCKET_NAME }} \
--region ${{ env.AWS_REGION }} \
$(if [ "${{ env.AWS_REGION }}" != "us-east-1" ]; then echo "--create-bucket-configuration LocationConstraint=${{ env.AWS_REGION }}"; fi)
echo "Configuring bucket settings..."
aws s3api put-bucket-versioning \
--bucket ${{ env.BUCKET_NAME }} \
--versioning-configuration Status=Enabled
aws s3api put-bucket-encryption \
--bucket ${{ env.BUCKET_NAME }} \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}'
- name: Configure bucket public access
if: steps.check_bucket.outputs.bucket_exists == 'false'
run: |
aws s3api put-public-access-block \
--bucket ${{ env.BUCKET_NAME }} \
--public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
Workflow Overview
The workflow triggers on every push and performs the following operations:
Authenticates with AWS using OIDC
Check if the specified S3 bucket exists
Creates a new bucket if it doesn't exist
Configures bucket security settings and encryption
Configuration Requirements
AWS IAM Role Setup
You need to replace the AWS_ROLE_TO_ASSUME
environment variable with your IAM role ARN. Your role ARN should look similar to:
arn:aws:iam::{YOUR-AWS-ACCOUNT-ID}:role/github-actions-s3-oidc-role-dev
Step 3: Test the Workflow
Commit and push the changes to your main branch.
Go to the Actions tab in your GitHub repository to monitor the workflow execution.
Verify the S3 bucket creation in the AWS Management Console.
Key Benefits of Using OIDC with GitHub Actions
Enhanced Security: Eliminates the need for long-term AWS credentials in GitHub Secrets.
Scalability: Easily manage permissions for multiple repositories.
Cost-Effective: Automates deployment without additional infrastructure.
Conclusion
By leveraging GitHub Actions with OIDC, you can build secure, streamlined CI/CD pipelines to deploy resources like S3 buckets to AWS. This setup not only reduces complexity but also ensures your workflows adhere to modern security best practices.
Next Steps
Try extending this workflow to deploy additional AWS resources, such as Lambda functions or DynamoDB tables, and explore the power of GitHub Actions in simplifying cloud deployments.
Congratulations! 🎉 and feel free to share your thoughts or ask questions about this guide! 🚀