Terraform providers and modules

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 = [
    effect = "Allow"
    actions = [

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 = [
    resources = ["*"]

also look at this article to learn about setting up of terraform workspaces


Leave a Reply

Your email address will not be published. Required fields are marked *