GitHub Actions and no AWS credentials
At GRRR we know AWS STS assume role, because AWS Lambda functions use it. Now it's possible to use it in GitHub workflows to access the AWS API. I use the workflow that publishes this blog as an example.
Some background
To access the AWS API you can use an access key id. That gives an IAM user access to the API. Works fine, but the downside is that you have to provide credentials. In the case of a GitHub workflow two secrets containing the access key id and secret access key.
But there is another method. You can assume an IAM role. By using the credentials of your personal account you are allowed to become a role and gain access to other AWS resources. This makes it possible to give your private AWS account access to resources in another AWS account. A short-lived access token is created in the background and used to authenticate.
This method isn’t limited to giving access to other AWS accounts. AWS Lambda uses this method to give the Lambda function access to AWS resources within an account. Upon invoking the Lambda function an access token is created. That token gives access to the resources defined by the role policies.
It took me some time to wrap my head around, so here are some resources that helped me:
📖 A clear StackOverflow answer
📖 AssumeRole is a feature of AWS STS
OpenID
Since November 23 OpenID for GitHub Actions is generally available. With OpenID, GitHub can request short-lived access tokens directly from cloud providers. In this article I use AWS, but Azure, Google Cloud Platform, and HashiCorp are also available.
📖 Read the official announcement
Let’s get our hands dirty.
Identity provider
First, add GitHub as OpenID provider to IAM Identity providers. This connects AWS and GitHub, so they can exchange tokens.
Provider URL: https://token.actions.githubusercontent.com
Audience: sts.amazonaws.com
IAM role
Instead of a user, you have to create a role with a trust relationship. It’s a relationship between the role and the added GitHub identity provider.
Press Next to add permissions. It’s the same as adding permissions to a user. You can copy the policies of the user you currently use.
The last step is changing the trust relationship condition to restrict usage of the role. You can do a lot more with token.actions.githubusercontent.com:sub
. This is just a simple one that restricts access from a specific repository, but you can use environments, event types, users, and a lot more. You can read about it in the GitHub Documentation.
📖 Read about security hardening
Click on “Edit trust relationship” to start editing.
..
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:organization/repository:*"
}
}
..
If you want to use the role in multiple repositories you can let it match “repository-a” OR “repository-b”:
..
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": [
"repo:organization/repository-a:*",
"repo:organization/repository-b:*"
]
}
}
..
Update the workflow file
Finally, we can do something with the workflow file. It’s not a lot, but removing secrets is my favorite part. This is a simplified version of the workflow grrr.tech uses to deploy new versions.
name: Deploy
on:
push:
jobs:
deploy:
name: Deploy
runs-on: ubuntu-18.04
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::111111111111:role/deploy-grrr.tech
aws-region: eu-central-1
- name: Build
...
- name: Publish front-end
run: aws s3 sync . s3://grrr.tech
What changed?
The secrets containing AWS credentials have been removed:
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Before the workflow is allowed to create an OpenID token you have to modify the default permissions granted to the GitHub API token (GITHUB_TOKEN
). You must add the id-token
permission to the workflow file.
permissions:
...
id-token: write
...
The step “Configure AWS Credentials” does the magic and authenticates the workflow.
📖 aws-actions/configure-aws-credentials documentation
All done!
And that’s it. Now you can remove the user! Or disable the access key id first, just to be sure.
Cheers!