When we are working with terraform to create cloud infrastructure, one of the common use case is dealing with multiple terraform providers ( accounts, or entirely different providers).
For example it may be a simple case of creating a S3 bucket in account A with cross account permissions and create the IAM role in account B. or it can a complicated use case like setting up transit gateway with multi account.
Working with terraform Providers
There are two way we can do this , first approach is using provider argument as part of resource definition as described in terraform documentation here
#declare additional provider in prodiver.tf file
# create this cross account IAM role in account A
provider "aws" {
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::xxxxxx:role/CROSS-ACCOUNT-IAM-ROLE"
}
alias = "aws_cross_account_1"
}
# run this terraform code in account B.
#refer to the provider alias in tf file
resource "aws_ram_principal_association" "ram_principal" {
principal = "Account Number"
resource_share_arn = "ARN of shared Resource "
provider = aws.aws_cross_account_1
}
Second approach is using providers argument in terraform modules – this approach is only applicable when you are using terraform modules.
in this approach the source module is generic with no provider definition and the caller module will pass the providers information as argument.
module "module-a" {
source = "path of your source module"
var1 = "value 1"
var2 = "value 2"
providers = {
aws = aws.aws_cross_account_1
}
}
Creating cross account role
Create a cross account IAM role in account A before implementing the above code in account B.
resource "aws_iam_role" s3-assume-role" {
name = "CROSS-ACCOUNT-IAM-ROLE"
assume_role_policy = data.aws_iam_policy_document.s3_assume_policy.json
tags = {
Name = "CROSS-ACCOUNT-IAM-ROLE"
}
}
# Add account B to this policy.
data "aws_iam_policy_document" "s3_assume_policy" {
statement {
principals {
type = "AWS"
identifiers = [
"arn:aws:iam::account-num-B:root"
]
}
effect = "Allow"
actions = [
"sts:AssumeRole"
]
}
}
resource "aws_iam_policy" "s3-policy-attach" {
name = "${local.tag_prefix}-CROSS-ACCOUNT-MSS-IAM-POLICY"
path = "/"
policy = data.aws_iam_policy_document.cross_account_s3_policy.json
}
resource "aws_iam_role_policy_attachment" "s3_policy" {
role = aws_iam_role.s3-assume-role.name
policy_arn = aws_iam_policy.s3-policy-attach.arn
}
data "aws_iam_policy_document" "cross_account_s3_policy" {
#Grant S3 list and get permissions for Account B
statement {
sid = "s3readpermissions"
effect = "Allow"
actions = [
"s3:List*",
"s3:Get*",
]
resources = ["*"]
}
}
also look at this article to learn about setting up of terraform workspaces