Author: @suzuki-shunsuke, SRE in Quipper

Original article in Japanese: Terraform の CI を AWS CodeBuild から GitHub Actions + tfaction に移行しました

In this post, I’d like to talk about how we migrated our Terraform CI from AWS CodeBuild to GitHub Actions + tfaction.

Terraform Workflow so far (AWS CodeBuild)

Originally, we used to run CI on AWS CodeBuild. Before that, we used CircleCI, but we migrated to AWS CodeBuild.

There are two main reasons why we migrated to AWS CodeBuild.

  • Security
    • You can manage AWS resources without persistent Access Keys
    • Google Cloud Platform (GCP) can also be managed without Service Account Key by Workload Identity Federation
  • Dynamic workflow
    • In Monorepo, we would like to run CI only in the working directory where the code was changed by pull request
    • This can be achieved by generating a buildspec dynamically during build and executing Batch Build with AWS CLI
    • CircleCI now supports dynamic workflow, but at the time it did not

The first reason in particular was a major strength of AWS CodeBuild.

Another advantage of AWS CodeBuild is that it can be run in AWS VPC. We manage MongoDB Atlas by Terraform. The Atlas supports restriction of API usage by source IP addresses, if it is not restricted, it is very risky when the key leaked. So, we only allow access from the Elastic IP address of a specific AWS VPC NAT Gateway.

OIDC support for GitHub Actions

However, the situation has changed dramatically since GitHub Actions started supporting OIDC to access AWS and GCP without a persistent access key.

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect

You can also run GitHub Actions in VPC by GitHub Actions’ Self-hosted Runner. Since we originally run Self-hosted Runner, we thought it would be relatively easy to run Terraform with Self-hosted Runner.

As the strengths of AWS CodeBuild became available in GitHub Actions, the momentum to migrate to GitHub Actions grew.

Reasons for migrating to GitHub Actions

We decided to migrate from AWS CodeBuild to GitHub Actions for the following reasons.

  • No more need to sign in to AWS to see CI logs and retry CI
  • GitHub Actions’ build matrix allows for a more natural dynamic workflow
  • Leverage Action ecosystem

No more need to sign in to AWS to see CI logs and retry CI

It’s bothersome to sign in to AWS to see CI logs and retry CI. In case of GitHub Actions, you don’t have to sign in to AWS for them.

GitHub Actions’ build matrix allows for a more natural dynamic workflow

We achieved dynamic workflow in AWS CodeBuild by generating buildspec and uploading it to AWS S3 and running a Batch Build with AWS CLI. So the build is executed in two stages, and CI takes a bit of time. Batch Build itself takes some time to start and finish too.

GitHub Actions’ build matrix allows for a more natural dynamic workflow. There is no need to dynamically generate a buildspec and upload to S3. It also makes CI faster.

Leverage of Action ecosystem

you can leverage GitHub Actions’ Action ecosystem. By replacing existing shell scripts with Actions, you can reduce the number of maintenance targets and improve maintainability.

Adopt tfaction

We have adopted tfaction, which is GitHub Actions collection for Opinionated Terraform Workflow.

https://github.com/suzuki-shunsuke/tfaction

tfaction supports almost all the features that we have originally implemented with shell scripts by ourselves, so we expected that we could eliminate shell scripts entirely.

Benefit of migration to GitHub Actions and tfaction

Migrating to GitHub Actions with tfaction has improved things in the following ways.

Least Privilege

One of the main problems we had was that all builds of Terraform used IAM Role with very strong privileges. GitHub Actions’ OIDC allows you to change IAM Roles per branch, so you can use IAM Role with strong privileges only in the default branch that executes terraform apply, and you can use IAM Role with almost ReadOnly privileges for pull requests. Furthermore, you can use IAM Role with very limited permission in builds for tfmigrate and for non-AWS Terraform Providers.

tfaction provides a Terraform Module to create IAM Roles with minimal privileges.

https://github.com/suzuki-shunsuke/terraform-aws-tfaction

And tfaction allows to configure IAM Roles for each working directory and GitHub Actions job (terraform plan, terraform apply, tfmigrate plan, tfmigrate apply), so you can achieve the least privilege easily.

tfaction-specific features

tfaction provides various useful features. Please see the official document.

Conclusion

In this post, I introduced the migration of Terraform Monorepo Workflow from AWS CodeBuild to GitHub Actions and tfaction. This migration has improved Developer Experience and achieved the lest privilege.