Securely Access Your AWS Resources From Github Actions

Security is a very important topic for all cloud engineers. Making sure that your infrastructure and data are kept out of reach of malicious people is one of the most serious things to get right. In AWS, we are used to dealing with IAM roles and permissions that make our resources accessible to users or to other resources. However, sometimes you need to grant access from outside your organization.

One example is when you want to deploy your infrastructure from a CI/CD pipeline, like Github Actions. How do you allow your workflow to gain access to your AWS account?

One approach is to create a dedicated IAM user, store its credentials in the Github secrets store, and allow the workflow to use them. Easy, enough! Secrets are encrypted by Github, so it is secure, right?

Not really… The problem is that those credentials are meant to be long-lived. It means that if anyone is able to get hold of them for whatever reason (eg: a leak in workflow logs, someone gaining access to a GitHub action runner, etc), they will be able to access all your resources (at least those that the credentials are allowed to control). Sure, you could rotate them from time to time, but you’d have to do that manually. This is probably not something you want to spend time doing and let’s face it, you probably won’t!

Luckily, there is a better solution. If you are using Github Actions, you can allow Github to grab temporary, short-lived, credentials that it can use during the execution of the workflow. After that, the credentials will expire and no one will ever be able to use them again.

In this post, I will guide you through the steps to set this up. Don’t worry, it’s actually easier than you think!

Here is a schema representing what we are going to accomplish

Setting up your AWS account

💡 TL;DR; I created a CloudFormation quick-create link that you can use to automate the following steps. See at the bottom of this article. If you want to know how it works, and what CloudFormation is going to do, keep reading this section.

Create an OpenID Connect Identity provider

The first step is to create an OpenID Connect (OIDC) identity provider in your AWS Account. This will allow Github to identify itself.

  • Got to the IAM console -> Identity providers
  • Click Add new provider
  • Select OpenID Connect
  • Provider Url: https://token.actions.githubusercontent.com (Don't forget to click Get Thumbprint)
  • Audience: sts.amazonaws.com
  • Add tags if you want to and click Add Provider

💡 You will need to do this step only once per AWS account.

Create a role

You now need to create a role that Github will be able to assume in order to access the resources it needs to control.

  • Go back to IAM and select Roles
  • Create a new Role
  • Chose Web Identity, select the Identity provider you created in the previous step, and its audience.
  • Click Next:Permissions

You now need to give the role the appropriate permissions (Policies). These are the ones that Github needs in order to do whatever it has to do. This will vary based on your use case, so I will leave that up to you. Keep in mind that you should stick to the principle of least privileges.

When that is done, give your role a name and click Create Role.

There is now an additional step to do. You need to edit the trust policy of the role to reduce its scope to your repository only. Make sure you don’t skip this part, it is very important. Without that, any repository on GitHub will be able to assume your role and access your resources. (Unfortunately, there does not seem to be a way to do that at creation time).

Go back to IAM Roles and select the created Role. Choose Trust Relationships and Edit Trust Relationship.

Under Condition, add the following segment:

"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:[your-org]/[your-repo]:*"
}

Replace the organization and repo names to match yours, and click Update Trust Policy.

✍️ Note: You can take this even further and reduce the scope, by using git references, to a branch or tag only, for example. eg: repo:[your-org]/[your-repo]:ref:refs/heads/master

The final result will look like this:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::1234567890: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:[your-org]/[your-repo]:*"
}
}
}
]
}

This concludes the required configurations on your AWS account. Take note of the role ARN, you’ll need it later.

💡 You can create different roles per account and use a different one for each use case. For example, one per application, per usage (configurations, deployment, integration tests), etc. You can play with that to reduce the scope of each session even more.

Configure Github action workflow

Your Github workflow requires additional permissions in order to be able to use OIDC. Add the following at the top of your workflow’s YML file. You can also add it at the job level to reduce the scope if needed.

permissions:
id-token: write # required to use OIDC authentication
contents: read # required to checkout the code from the repo

You can now use the configure-aws-credentials Github action in the job that needs to assume the role. Add this step to generate credentials before doing any call to AWS:

- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::1234567890:role/your-role-arn
role-duration-seconds: 900 # the ttl of the session, in seconds.
aws-region: us-east-1 # use your region here.
# You can now execute commands that use the credentials👇
- name: Serverless deploy
run: sls deploy --stage dev

The configure AWS credentials step will use the OIDC integration to assume the given role, generate short-lived credentials, and make them available to the current job.

💡 If you want to take security even further, you can also keep your role’s ARN used in role-to-assume in a Github secret.

Automate

The guys at configure-aws-credentials shared a CloudFormation template that you can use to automate the AWS configuration steps.

I took it one step further; I hosted that template and created a deployment link for you.

Click here to deploy it into your account.

Fill in the parameters:

  • GitHubOrg: your organization name, or your Github username
  • RepositoryName: the repository that needs access to your AWS account
  • OIDCProviderArn: your existing OIDC provider's ARN, if you have one already. If you don't, leave it empty and one will be created for you. (Remember that you only need one per account).

✍️ Note: The created role will not have any Policy attached to it. You will still need to attach the ones that your workflow needs to it after that.

Conclusion

As you can see, securing your account doesn’t have to be hard. The part that might require a little more effort is to define the right Policies if you want to follow the principle of least privileges (which you should!).

For more content like this, follow me on Twitter @Benoit_Boure, and don’t forget to subscribe to my newsletter.

Originally published at https://benoitboure.com.

--

--

--

Twitter @Benoit_Boure — Need help? Hire me for a one-on-one session http://hiretheauthor.com/bboure

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Supporting Mercari’s development and quality assurance by in-app dev tools

Introducing Larahawk — Simple log monitoring for Laravel applications

Installing Protobuf Compiler(protoc)

Reduce Cost and Increase Productivity with Value Added IT Services from buzinessware — {link} -

The first Mongolian IT engineering community meet up

Easy as 1,2,3 … GnuCOBOL environment variables in Windows 10

CS371P Fall 2021: Vishal Tak

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Benoît Bouré

Benoît Bouré

Twitter @Benoit_Boure — Need help? Hire me for a one-on-one session http://hiretheauthor.com/bboure

More from Medium

How to host a static website on AWS with S3, CloudFront, Route53 and Terraform — Interweave

How to monitor disk space on EC2

How to use AWS EFS with Multiple EC2 instances

Working with AWS Directory Service