Introduction

This design shows how a development or infrastructure team managing multiple AWS accounts can use Terraform and DevOps practices to strengthen change management processes.

Managing cloud resources with Terraform Infrastructure as Code (IaC) with a Continuous Integration (CI) system allows teams to programmatically deploy their infrastructure. Many teams leverage multiple accounts for change management between development, staging, and production. A multi-account strategy offers additional benefits for applying least privilege, separation of duties, and blast isolation. Combining Terraform with well thought out IAM policies in this multi-account strategy allows teams to deploy safely and securely.

Multi-account Terraform

Teams that do not already use Terraform may start off with a proof of concept applied from the DevOps team’s workstations, but this quickly presents both operational and security challenges due to lack of auditability and environment reproducibility. Using the following outline, a DevOps team can add a Terraform pipeline that follows best practices for environment isolation and least privilege usage of IAM.

This diagram shows the account relationships and the use of IAM roles to grant Terraform the correct permissions in each managed account.

AWS account diagram

Account Setup

The multi-account strategy requires an existing CI system with access to the version control system. It does not matter where the system resides, either on-premises or in an Infrastructure AWS account, as long as it has access to your source code, the necessary secrets, and the AWS API. The development team may already have one or more product accounts. Setup a Terraform workspace for each product account. To add Terraform in the CI system, provision an additional AWS account exclusively for Terraform use. A dedicated account allows for separation of duties and minimizes exposure of the resources Terraform uses. Protecting this account and its associated credentials minimizes risk of bypassing the change management process; anyone with access to the IAM user used by Terraform could abuse the permissions Terraform uses. This account should also follow best practices for logging and auditing usage of these privileges.

To setup the users and permissions Terraform will use, add an IAM user and role for the CI system in the Terraform AWS account. Store the IAM user credentials in the CI system’s secret storage system. The Terraform pipeline will assume this CI Terraform role to access resources for the Terraform backend in the Terraform AWS account. The assume role policy should allow only the CI IAM user to assume the CI Terraform role.

Next, in each product account, add an IAM role for Terraform. The policy attached to this role should be consistent across all product accounts to avoid differences in results of Terraform pipeline runs in each environment. This role will control what Terraform is allowed to do; it can be scoped to only allow access to services that you want Terraform to manage. Since this role manages all infrastructure in the product account, it grants access to highly privileged permissions and its use should be controlled carefully. The assume role policy should allow only the CI Terraform role to assume the product account Terraform role.

To complete the setup, specify the product account Terraform role for each workspace in the Terraform backend. When each workspace is selected, Terraform will assume the correct role in the product account using temporary credentials.

Change Management

The CI system serves as the enforcement point for the change management process. DevOps and Security personnel should review and approve changes to the IaC repository before merging them to master. The CI system itself must be treated as a production system as discussed in my posts on CI Security Part 1 and Part 2.

Conclusion

By leveraging tooling and best practices, we can securely deploy infrastructure into a multi-account architecture. This design strengthens change management and builds a foundation for applying least privilege throughout the AWS environments.