Using Open ID Connect to authenticate to AWS from GitHub
Note — if you’re here to find a repository with preconfigured code it can be found here.
Many people use non native CICD to deploy to AWS. Personally in addition to the native tools I’ve used GitHub and GitLab for both code repository and CICD.
Typically this approach has involved deploying private ‘runners’ inside the AWS environment which poll the repos for changes and then execute the pipelines. This approach is great from a security perspective, you can use IAM Instance Profiles so there are no static credentials, however there’s a cost and complexity drawback in terms of needing a VPC with outbound internet connectivity, EC2 instance(s) running etc. I’ve used techniques to limit the costs, like autoscaling spot instances on t series instances to keep the runner costs down, but unless you’re willing to put the runner in a public subnet you need some kind of outbound solution incurring more cost such as NAT instances, NAT Gateway, Network Firewall or connectivity off to a Transit Gateway / on-premise / another VPC with a proxy solution.
I’ve not previously used GitHub hosted runners as I didn’t want to use static credentials such as access key / secret access key for security reasons to authenticate resources outside of AWS. Step forward Open ID Connect.

OpenID Connect is a layer on top of the OAuth2.0 protocol. I’m using it between GitHub and AWS to exchange information that ultimately results in a token being generated by AWS IAM that GitHub can then exchange for temporary credentials using the Security Token Service AssumeRoleWithWebIdentity api call.
The Open ID Connect provider in AWS is configured to access the GitHub URL, and includes a fingerprint for security. There’s a convoluted process for calculating the thumbprint associated with GitHub’s, however I just searched for it. Creating this provider allows GitHub OpenID Connect to communicate with your AWS account to get a token that can be presented to the STS service, however at this stage no rights have been granted to GitHub.

Once that’s created a role that can be assumed by GitHub is required, along with appropriate permissions for the role to undertake the task you want within your account. The key for GitHub to be able to use this role is that the trusted entity is the OpenID Connect provider created in the above step, as can be seen below, this allows GitHub to perform the STS AssumeRoleWithWebIdentity call, and then for security purposes I’ve scoped down which repository can use this role to the demo repo in my GitHub organisation, as of course you wouldn’t want the entirety of GitHub to be able to assume a role in your account!

Putting it all together….
To check it all works I’ve then used a GitHub Action to login to AWS using the configure-aws-credentials action and deploy an SNS topic. I’ve created this resource using the AWS cli for simplicity, however once logged in you’re free to deploy with whatever you want, you can run Terraform, Python whatever your deployment tool of choice is….

If you’re interesting in using Open ID Connect with AWS I’ve created a demo repository which uses Terraform to create the resources I’ve described above and has the GitHub action pipeline I’ve used to test. Instructions on how to use are in the readme. GitHub’s instructions on how to set this up can be found here.