From a Repository to the Cloud: Maximizing Efficiency with GitHub Actions and AWS
Nowadays, automation has become an essential aspect of the modern technological work environment; it plays a crucial role in improving efficiency, productivity, and quality. By eliminating manual interventions, automating activities not only saves time and effort but also minimizes errors and enables individuals and organizations to focus on more strategic and value-added tasks.
In a developer environment, many techniques and practices are recommended to improve the results, making the software development cycle faster and more reliable. One of them is CI/CD practices (continuous integration/continuous deployment) that act as a bridge, connecting development and operations teams and of course, their activities by emphasizing the importance of automation in building, testing, and deploying software solutions.
GitHub Actions is a powerful CI/CD platform provided by GitHub that allows developer teams to automate different tasks in their software development cycle, streamlining their processes and improving collaboration within their teams. It uses GitHub Runners to execute workflows that let us perform actions in different cloud platforms such as AWS, GCP, Azure Cloud, etc.
In this article, we will explore how to configure and integrate one of two types of GitHub runners of GitHub Actions with AWS using a custom OpenID Connect (OIDC) authentication protocol provider.
Overview
Firstly, there are some concepts that we need to understand before starting:
- Workflows: They are sequences of actions defined in source code files, serving as pipelines that specify a set of automated steps to be executed.
- GitHub Runners: These virtual machines serve as the infrastructure required to execute workflows, enabling development teams to automate tasks and processes.
- OIDC: This is an interoperable authentication protocol based on the OAuth 2.0 framework, which simplifies the way to verify the identity of users.
There are two types of GitHub Runners: self-hosted and GitHub-hosted runners:
- Self-hosted runners are machines that you configure on your own, but you have to manage them too. The advantage of using this kind of “runners” is that it provides us with a full level of customization on hardware and software. By utilizing self-hosted runners, you can run workflows in your preferred environment: on-premises, in a private cloud, or any other infrastructure, and you have complete control over the security settings.
- GitHub-hosted runners are virtual machines offered by GitHub, providing us with preconfigured environments to execute our workflows. Every GitHub subscription has storage and GitHub-hosted runners running minutes included. By using this kind of “runners”, we delegate the responsibility of setting up and maintaining the hardware and software, ensuring compatibility and letting us focus on what the workflow has to do.
In summary, both types of runners offer us flexibility and scalability to meet our needs regarding workflows and integration with AWS services for CI/CD pipelines, but it is important to check some conditions before selecting one of them:
There aren’t good or bad options; it depends on what we need. For example, if our team is small, we have a free GitHub subscription, execute simple workflows to deploy some infrastructure in AWS, GCP, or Azure, and don’t need some special configuration regarding security, probably using GitHub-hosted runners is the best option. But if we are working in a big team, we use GitHub Actions to perform complex tasks that need external libraries or a specific operating system, we need some specific configuration regarding security, and we have an operational capacity to maintain our runners, most likely our best option is to use self-hosted runners. This decision depends on our conditions and capacities (operational, financial, etc.).
As we mentioned before, we will explain how to configure GitHub-hosted runners in this article.
Prerequisites
Before we dive into the details of integrating GitHub Actions with AWS, there are a few prerequisites that need to be in place:
- An AWS account with the necessary permissions to create and manage IAM roles and policies.
- Administrator access in a GitHub enterprise instance.
- A GitHub repository where you will configure your workflows.
- Basic knowledge of GitHub Actions and AWS Identity and Access Management (IAM).
Considerations
- We will use official actions to configure AWS credentials in our GitHub workflows.
- To ensure only one enterprise has access to use this integration, we will set up a custom OIDC issuer.
- (Optional) If you have GitHub CLI installed on your machine, it would be great in this process because it could make it easier.
Hands-on
The following diagram shows the architecture of our solution, where we can see the artifacts needed in each platform and how they interact:
The configuration has to be done on both platforms: GitHub and AWS, following these steps:
- Configure a custom OIDC issuer in GitHub.
- Configure an IAM OIDC identity provider in AWS.
- Create an IAM role and attach it to an Identity Provider.
- Update the GitHub Actions workflow to connect with AWS.
Configure custom OIDC issuer in GitHub
When you integrate GitHub Actions with a cloud provider, it grants access to all repositories in GitHub, and this could be insecure and dangerous. For this reason, it’s necessary to configure a custom OIDC issuer in GitHub Actions, limiting access only to repositories whose JWT token has been issued by a specific provider.
To configure the custom GitHub Actions OpenID Connect (OIDC) issuer, you have to follow these steps:
- Authenticate in GitHub Enterprise as an administrator.
- Set the custom issuer:
Authenticate in GitHub Enterprise as an administrator
Depending on how your Enterprise security was configured and what platform you want to use (browser, desktop, command line, etc.), you have to authenticate in GitHub and ensure that you have Administrator access granted. Here you can find a guide about how to do it, depending on your preferences.
Set the custom issuer
You can set the custom issued in two ways:
If you have GitHub CLI installed, execute the following command, replacing first where it says ENTERPRISE with the name of your enterprise:
# GitHub CLI API
# https://cli.github.com/manual/gh_api
gh api \
- method PUT \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022–11–28" \
/enterprises/ENTERPRISE/actions/oidc/customization/issuer \
-F include_enterprise_slug=true# GitHub CLI API
If you don’t have GitHub CLI installed, you can use the curl
command:
Execute the following command, adding a BEARER authorization token (<YOUR-TOKEN>), and replacing where it says ENTERPRISE with the name of your enterprise:
curl -L \
-X PUT \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer <YOUR-TOKEN>"\
-H "X-GitHub-Api-Version: 2022–11–28" \
https://api.github.com/enterprises/ENTERPRISE/actions/oidc/customization/issuer \
-d '{"include_enterprise_slug":true}'
That’s it! If everything went ok, you should have received a code 204 as a response.
Configuring AWS for OIDC Integration
To start integrating GitHub Actions with AWS, we need to set up an identity provider in AWS using OIDC:
Create an IAM OIDC identity provider in AWS.
- In the AWS console, go to IAM.
- In the left panel, go to the “Identity Provider” sub-menu.
- Click on “Add provider” located in the top-right corner.
4. In “Provider type”, select OpenID Connect
.
5. Specify the secure OpenID Connect URL for authentication requests in. the “Provider URL”. It should be something like: token.actions.githubusercontent.com/<ENTERPRISE>
6. For the “Audience”: Use sts.amazonaws.com
.
7. Optional: Add some tags if needed.
8. Click on “Add provider”
Create an IAM role in AWS and define the necessary permissions for the workflows.
- In the AWS console, go to IAM.
- On the left panel, go to the “Roles” sub-menu.
- Click on “Create role” located in the top-right corner.
4. Select “web identity” as Trusted entity type
.
5. In “Identity provider”, you should see the identity provider created in the previous step; select it.
6. For the “Audience” select sts.amazonaws.com
.
7. Press “Next”
8. Create a policy or select all permissions this role needs. It depends on the types of tasks you will automate with GitHub Actions.
9. Press Next
10. Assign a name for the role.
11. Add some description if needed.
12. The “Select trusted entities” box should be filled with a basic trusted policy automatically based on the information provided by you. This policy allows using this role to all sts: AssumeRoleWithWebIdentity
API calls with a JWT token emitted by a unique URL provided by GitHub (configured in step: Configure custom OIDC issuer in GitHub).
13. Finally, press “Create role”.
This is all the configuration required to let GitHub-hosted runners assume an IAM role to execute tasks in AWS.
Updating GitHub Actions workflow to connect with AWS
Now you will need to make two changes to your workflow YAML file:
Add permissions settings for the token: In order for a job or workflow to be able to request the OIDC JWT token, some permissions must be assigned as shown in the following piece of code:
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
Use the official actions to configure AWS credentials: As mentioned earlier in this article, we’ll use the official actions to configure AWS credentials. For this, you need to add a step like the following, where you have to replace <account-id
> and <role-name>
with the values that you have obtained in previous steps in this document:
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::<account-id>:role/<role-name>
role-session-name: samplerolesession
aws-region: ${{ env.AWS_REGION }}
Example:
The following is a simple example of how to properly configure the workflow YAML file, adding permissions and using the official action to configure AWS credentials. This code should be saved as a YAML file (<workflow_name>.yml
) in the path “.github/workflows” on our repository:
# Sample workflow to access AWS resources when the workflow is tied to the branch
# The workflow Creates a static website using aws s3
name: AWS example workflow
on:
push
env:
BUCKET_NAME : "<example-bucket-name>"
AWS_REGION : "<example-aws-region>"
# permission can be added at the job level or workflow level
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
jobs:
S3PackageUpload:
runs-on: ubuntu-latest
steps:
- name: Git clone the repository
uses: actions/checkout@v3
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::1234567890:role/example-role
role-session-name: samplerolesession
aws-region: ${{ env.AWS_REGION }}
# Upload a file to AWS s3
- name: Copy index.html to s3
run: |
aws s3 cp ./index.html s3://${{ env.BUCKET_NAME }}/
Conclusions
This is a simple example of how to connect AWS and GitHub and take advantage of them daily, enhancing our teams by automating developer lifecycle tasks, trying to eliminate human errors, applying best practices in our processes as CI/CD pipelines, and above all, using them together securely.
It’s important to analyze all features of each of those two options that GitHub offers us regarding runners before deciding what to use in each case. Remember, there aren’t good or bad options; there are only features that need to be checked to enhance our process and avoid waste of money and resources.
Finally, as with almost everything, GitHub Actions and AWS are high-powered platforms designed for big things; with them, we can create a basic “hello world” application or support an entire enterprise infrastructure around the world; everything depends on us, on what we are eager to learn every day.
References
- GitHub Actions quickstart
- Authentication on GitHub
- OpenID foundation
- OAuth 2.0: https://oauth.net/2/
- Self-hosted runners
- GitHub hosted runners
- About billing for GitHub Actions
- Official action to configure AWS credentials in GitHub workflows
- Set a custom GitHub OIDC issuer
- How to create a personal access token