Generally, when using HashiCorp Terraform to deploy and manage Amazon AWS resources, the Terraform project will be working with AWS resources in only a single AWS Account. However, it’s common to structure cloud deployments across multiple Amazon AWS Accounts in certain use cases. This could be to separate DEV and PROD environments, or to separate cloud resource managements across multiple AWS Accounts for several other reasons. Regardless of the actual reason to use multiple AWS Accounts, it really is possible to use a single Terraform project to manage all the cloud resources across multiple AWS Accounts without the need to split things out into multiple Terraform projects.
Let’s take a look at configuring the AWS Terraform Provider to enable the deployment and management of AWS resources across multiple AWS Accounts from a single Terraform project!
Table of Contents
Define Multiple AWS Providers
At these times, you will need to support multiple instances of the aws Terraform Provider, each targeting a different AWS Account, within a single Terraform project. This can be done by using the alias attribute on the provider declaration in Terraform. This enables the ability to have multiple aws providers configured for different AWS Account credentials.
This may become necessary when you have separate AWS Accounts, or even just separate AWS IAM credentials, that need to be used to deploy and manage specific Amazon AWS resources. Maybe the resources are managed across the different accounts, or maybe different security credentials are used for specific resource deployment needs. Either way, this technique will help you get the Terraform written the way you need it within a single Terraform project.
The following is an example of 2 different provider blocks for the aws Terraform provider with the alias attribute set to differentiate between them since they are configured for different AWS Accounts:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
provider "aws" {
alias = "dev"
access_key = var.dev_aws_key
secret_key = var.dev_aws_secret
region = "us-east-1"
}
provider "aws" {
alias = "prod"
access_key = var.prod_aws_key
secret_key = var.prod_aws_secret
region = "us-west-2"
}
}
Keep in mind the previous example uses Input Variables passed to the Terraform project to define the values that are used to configure the AWS Accounts for each aws Terraform provider instance.
Deploy to Multiple AWS Accounts within Terraform Project
Once you have multiple aws Terraform providers configured in the Terraform project with the alias attribute set on each, you can use the provider attribute on resource blocks to explicitly specific which provider to use for deploying each resource.
The following is an example of code from a single Terraform project that will deploy resources to multiple AWS Accounts using the aws providers from the previous example:
resource aws_s3_bucket "dev_bucket_1" {
provider = "dev"
bucket = "my-tf-dev-bucket-1"
}
resource aws_s3_bucket "prod_bucket_1" {
provider = "prod"
bucket = "my-tf-prod-bucket-1"
}
With the resource.provider attribute set, you’re telling the Terraform code which specific Terraform provider to use for deploying and managing that AWS resource. By defining multiple aws providers with the alias attribute, you are able to set up multiple instances of the aws provider to be used within a single Terraform provider. This is supported for the aws provider, as well as any other Terraform provider.
Passing Terraform Provider Alias to Modules
When writing Terraform Modules, for code reuse and organization within the Terraform project, the code within the module may be coded to just use the “default” aws provider; without any provider.alias expected. In these cases, you can explicitly set, or override, which aws Terraform provider from the Terraform project will be used as the “default” within the Terraform Module.
This is done by using the providers attribute on a module block to explicitly configure the Terraform Module for which Terraform providers to pass it.
The following is an example of using a Terraform Module within a project and passing different aws provider instances to it as the “default” provider. This will enable the same module, without code changes, to be used with multiple AWS Accounts within a single Terraform project.
module "sample-dev" {
source = "./sample-module"
providers = {
aws = aws.dev
}
}
module "sample-prod" {
source = "./sample-module"
providers = {
aws = aws.prod
}
}
When using the module.providers attribute to tell the Terraform Module which Terraform provider instance to use, you are defining it using an object syntax that allows for multiple providers. This enables you to explicitly specify all the different Terraform providers that module needs to use, in case it’s coded for multiple providers as well.
Deploy to Multiple AWS Accounts with a “Default” aws Provider
The previous examples all used named aws providers using the alias attribute on each provider. It is possible, and probably best practice, to use one aws Terraform provider instance as the “default”, and then use the alias attribute to configure multiple other providers to be used within the Terraform project as well.
The following it an alternative example that defines the dev AWS provider instance as the “default” for the Terraform project, while also defining the prod AWS provider instance as a named instance using the alias attribute.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
# This is the "default" provider
provider "aws" {
access_key = var.dev_aws_key
secret_key = var.dev_aws_secret
region = "us-east-1"
}
# This provider uses the "prod" alias
provider "aws" {
alias = "prod"
access_key = var.prod_aws_key
secret_key = var.prod_aws_secret
region = "us-west-2"
}
}
# Use the "default" aws provider
resource aws_s3_bucket "dev_bucket_1" {
bucket = "my-tf-dev-bucket-1"
}
module "sample-dev" {
source = "./sample-module"
}
# Use the "prod" aliased aws provider
resource aws_s3_bucket "prod_bucket_1" {
provider = "prod"
bucket = "my-tf-prod-bucket-1"
}
module "sample-dev" {
source = "./sample-module"
providers = {
aws = aws.prod
}
}
Happy Terraform-ing!
Original Article Source: Terraform: Deploy to Multiple AWS Accounts in Single Project written by Chris Pietschmann (If you're reading this somewhere other than Build5Nines.com, it was republished without permission.)

Microsoft Azure Regions: Interactive Map of Global Datacenters
Create Azure Architecture Diagrams with Microsoft Visio
Azure Functions: Extend Execution Timeout Past 5 Minutes
Azure VM Shutdown Tips to Save Money
Azure CLI: List and Set Azure Subscription





