Authenticating GitHub Actions with AWS

Generated by DALL·E 2.
Generated by DALL·E 2.

Before October 2021, the only way to authenticate GitHub Actions with AWS was by using long-lived access keys. In the best-case scenario, you would create a user with least-privileged access. In the worst-case, you would use an existing user that may have broader permissions to your AWS account, such as the root user. In addition, AWS access keys for GitHub Actions builds typically are stored in GitHub Secrets that may be accessible by multiple people, which is problematic for IAM user identities.

Long-lived credentials carry risk in case credentials get accidentally exposed. Therefore, AWS recommends using temporary credentials generated from IAM roles instead of long-term access keys. IAM role trust policies can also help restrict who can assume the credentials.

GitHub Actions has recently added OpenID Connect (OIDC) support with AWS and other cloud providers. Now you can create an IAM role in AWS that GitHub Actions can assume using temporary credentials.

Creating the role

Add GitHub as an IAM identity provider to set up OIDC authentication with GitHub Actions. Go to IAM > Identity providers > Add provider. The audience in the below configuration assumes you are using the official action.

Next, go to IAM > Roles > Create role. Create an IAM role with the below configuration.

Add least-privileged permissions required for your GitHub Actions workflow.

Modify the trust policy to look like the following but modify according to your circumstance. This example allows the repository my_github_org/my_repo to assume the role.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::[YOUR_ACCOUNT_ID]:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:sub": "repo:my_github_org/my_repo:*"
                }
            }
        }
    ]
}

Subject (abbreviated "sub" in the above trust policy) can fine-tune which entity (such as repo or branch) can assume the role.

For example, to allow any repo under your GitHub user or org to assume the role, you can set the subject to be like below, which grants access to all repositories under my_github_user.

"token.actions.githubusercontent.com:sub": "repo:my_github_user/*"

You can see other examples of subject claims in the documentation.

Please ensure you use "StringLike" and not "StringEqual" if you use "*" in your policy condition. Please also be aware that values in the condition are case-sensitive.

Now you can create the role. Finally, copy the role's ARN to use later.

Assuming the role

Your GitHub Actions workflow requires extra permissions to generate the token. Configure permissions at the workflow level or the job level.

permissions:
	 id-token: write  # This is required for generating OIDC tokens
	 contents: read  # This is required for actions/checkout@v2

You can use the official AWS action for configuring credentials. You only need to pass a couple of parameters. For extra security, especially for public repositories, I recommend storing the ARN of the role to assume in GitHub Secrets to hide your AWS account number.

 - name: Configure AWS Credentials
	 uses: aws-actions/configure-aws-credentials@v1
	 with:
		 role-to-assume: ${{ secrets.ROLE_TO_ASSUME }}
		 role-session-name: MySessionName  # Put whatever you like here
		 aws-region: us-east-1  # Put your AWS region here

The configure-aws-credentials action will set temporary AWS credentials for the role created earlier. Please consult the documentation for more information about configuring GitHub Actions OIDC for AWS.