GitHub Actions x AWS: A Quick Integration Guide

Alisson Cruz
7 min readJan 29, 2024

--

Introduction

In the fast-moving field of software development, having smooth and automated deployment processes is crucial. In this post, we’ll break down the integration of GitHub Actions with AWS, making it easy for developers to build, test, and deploy their applications effortlessly.

As DevOps engineers, we know how important it is to have a well-organized CI/CD pipeline. GitHub Actions offers a powerful solution, allowing you to automate workflows directly within your GitHub repository. Combining GitHub Actions with AWS services opens up exciting possibilities, allowing you to use Amazon Web Services for scalable and reliable infrastructure in your CI/CD process.

This tutorial is here to help you connect GitHub Actions to AWS in a secure and authenticated way, providing practical knowledge and hands-on experience. By the end, you’ll be able to seamlessly integrate these technologies, making your software development lifecycle more efficient.

So, let’s get started!

OpenID Connector (OIDC)

OpenID Connect (OIDC) is a vital player in the security realm of web applications. Its primary role is to ensure that users can securely access applications and services without compromising sensitive information. Think of it as the digital bouncer, making sure only the right people get through the virtual entrance.

In the OIDC arena, we have Users (the individuals using the applications), Clients (the applications themselves), and Identity Providers (the platforms confirming users’ identities). The process of giving the right access to the Users has two steps: Authentication and Authorization.

When a User attempts to log in to the Client, the Identity Provider performs checks to verify the user’s identity — such as requesting the user’s password. This constitutes the authentication step. Once authenticated, the Identity Provider issues an ID Token, functioning like a badge that validates the User’s identity to the Client. Using this ID Token, the Client then requests an Access Token from the Identity Provider, specifying what resources the User is permitted to access — this represents the authorization process.

GitHub Actions and AWS

OIDC protocol is the recommended method (by GitHub itself) to authenticate GitHub Actions workflows on AWS, ensuring benefits like standardization, interoperability, security (fine-grained control, reduced credential exposure), single sign-on (log in once and access to multiple services), and so on.

https://github.com/aws-actions/configure-aws-credentials#using-this-action

The following flowchart shows how the components interact with each other using the OIDC protocol, and each one playing a role as described earlier:

  • GitHub Actions workflow: User
  • GitHub OIDC Provider: Identity Provider
  • AWS: Client
GitHub Actions x AWS: simplified OIDC authentication flowchart

Step-by-Step Guide

As an overview, the list below summarize what it is necessary to be configured in order to authenticate and authorize GitHub Actions to access services or resources in AWS.

  1. AWS: Create an Identity Provider for GitHub OIDC Provider
  2. AWS: Create an IAM Role with necessary permission policies
  3. GitHub Actions: Add permissions on workflow or step
  4. GitHub Actions: Add a step on workflow to call STS Assume Role

AWS: IAM Identity Provider & OIDC Role

To start things “a la DevOps”, the AWS CloudFormation template below helps us to configure the IAM resources needed to authenticate our GitHub Actions workflow on AWS.

This template is responsable for configure both the IAM IdP for GitHub Provider and the OIDC Role that will be assumed by the workflow (which represents the listed steps 1 & 2 above).

1. Save the CloudFormation template code below in a file with extension “.yml”.

Parameters:
GitHubOrgUser:
Description: Name of GitHub organization/user (case sensitive)
Type: String
RepositoryName:
Description: Name of GitHub repository (case sensitive)
Type: String
OIDCAudience:
Description: Audience supplied to configure-aws-credentials.
Default: "sts.amazonaws.com"
Type: String

Resources:
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated:
- !Ref GithubOidc
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: !Ref OIDCAudience
StringLike:
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrgUser}/${RepositoryName}:*

GithubOidc:
Type: AWS::IAM::OIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- ffffffffffffffffffffffffffffffffffffffff

Outputs:
Role:
Value: !GetAtt Role.Arn

Important: The Role template above does not have any policy attached to it (policies will be attached by hand to the Role as needed later). In a definitive deployment, it is recommended to incorporate the necessary policies to the CloudFormation template as well.

2. On AWS Console, access the CoudFormation page and make sure you are in the “Stacks” sub-categorie (left panel).

3. Click “Create stack” button, than click “ With new resources (standard)”.

Creating a new stack on AWS CloudFormation — part 1

4. On the “Create stack” page, select the following options as the image below and click “Next”. Pay attention to choose the “.yml” file in “Choose file” that represents the CoudFormation template from step 1 (in this case, it’s “cf.yml”).

Creating a new stack on AWS CloudFormation — part 2

5. On the “Specify stack details” screen, fill the forms with infos about your stack name and GitHub repo, then click “Next”.

  • Stack name: CloudFormation stack name to be created
  • GitHubOrgUser: Name of GitHub organization or username
  • OIDCAudience: sts.amazonaws.com (default, don’t change)
  • RepositoryName: Name of GitHub repository where the Actions workflow is configured
Creating a new stack on AWS CloudFormation — part 3

6. On “Configure stack options” page, just click “Next”.

7. On “Review <stack-name>” page, check the “Capabilities” checkbox and click “Submit”.

Creating a new stack on AWS CloudFormation — part 4

8. Wait for CloudFormation deployment to be completed and validate that both OIDC Provider and Role were created sucessfully (on "Resource" tab).

Creating a new stack on AWS CloudFormation — part 5

9. Now let's add the necessary permissions to the new Role. Click the blue link that redirects to the Role page ("github-oidc-auth-Role-mVCfrIMPaYfi" in this case).

10. On the Role page, Click the "Add permissions" button, then "Attach policies".

Attaching policies to the new Role for OIDC — part 1

11. On the "Add permissions" page, search and select the policies needed for whatever actions the GitHub Actions workflow would perform on AWS. For this guide, we will add the "AmazonS3FullAccess" policy. Click "Add permission" to attach the policy to the OIDC Role.

Attaching policies to the new Role for OIDC — part 2

GitHub Actions: GitHub permission & Assume Role

GitHub Actions is a continuous integration and continuous deployment (CI/CD) platform that runs actions (e.g. test, build, deploy) based on yaml templates that describe the steps that should be executed. These templates are declared in the same repository, on the .github/workflows path.

  1. Create a yaml template file ("aws-bucket.yml" in this case) on the path .github/workflows. The full file's path should be .github/workflows/aws-bucket.yml.
GitHub Actions template file

In order to authenticate on AWS, the workflow needs two configurations: permissions (so the workflow can get the ID token) and a job step to assume the OIDC Role created earlier (so the workflow can authenticate and get temporary credentials from AWS).

permissions:
id-token: write
contents: read
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
role-to-assume: arn:aws:iam::<AWS_ACCOUNT_ID>:role/<OIDC_ROLE_FROM_CLOUDFORMATION>

2. Edit the workflow file with the necessary steps for your use case. A complete example template is presented below with significant comments:

name: AWS S3 Bucket

# Trigger the workflow every push to branch "main"
on:
push:
branches: [ "main" ]

# Necessary permissions for workflow
permissions:
id-token: write
contents: read

jobs:
S3BucketIntegration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

# Install awscli
- uses: unfor19/install-aws-cli-action@v1

# Assume the OIDC Role to get temporary credentials
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
role-to-assume: arn:aws:iam::<AWS_ACCOUNT_ID>:role/<OIDC_ROLE_FROM_CLOUDFORMATION>

# List all buckets
- name: List S3 Bucket
run: |
echo "==> Listing all S3 buckets"
aws s3 ls

3. That's it!

Now, everytime something is pushed to branch "main" (our trigger condition), the workflow will run and execute these steps to authenticate and list our S3 buckets on AWS.

Workflow completed successfully
Workflow successfully authenticated on AWS and had permission to list all S3 buckets

Conclusion

In conclusion, integrating GitHub Actions with AWS using OIDC creates a smooth and secure automation pipeline that improves development workflows and operational efficiency. DevOp'ers can securely access AWS resources without the need for long-lived access keys or complex IAM configurations.

As DevOps evolves, adopting technologies like GitHub Actions and OIDC authentication with AWS highlights a dedication to efficiency, security, and innovation in software development and deployment. This integration enables teams to enhance their workflows, speed up time to market, and provide outstanding experiences to users.

--

--

Alisson Cruz

I am a DevOps Engineer and tech enthusiast with nearly 10 years of experience helping companies to deploy applications in a faster and more reliable way.