Cross Account Resource creation using Terraform

Manoj Bhagwat
2 min readApr 5, 2020
Cross Account Setup

In this blog, we are going to create resources in multiple AWS accounts using Terraform.
OK !!! before we start you might have question why do we need to provision resources across multiple accounts.
If you look at the large organization they always have a huge infrastructure(multi-tier architecture), so its always best practice to keep your resources loosely coupled as its help in managing things in a much better manner, rather than setting up everything single account and facing challenger later.
So in this example, we have a SUB and MAIN account, we are spinning up application EC2 instance in sub-account and creating corresponding DNS entry for application in the main account using terraform.

To start with we need to a setup role in the main account that gives access to route53 service for creating records.

  1. Create trust relationship policy in main account as below :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<SUB ACCOUNT ID>:root"
]
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}

2. Attach custom policy to above role:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"route53:GetHostedZone",
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets",
"route53:DeleteHostedZone",
"route53:UpdateHostedZoneComment"
],
"Resource": "arn:aws:route53:::hostedzone/*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"route53:CreateHostedZone",
"route53:GetHealthCheckStatus",
"route53:GetHealthCheckLastFailureReason",
"route53:ListHostedZones",
"route53:GetHealthCheck",
"route53:UpdateHealthCheck",
"route53:DeleteHealthCheck",
"route53:ListHostedZonesByName",
"route53:GetCheckerIpRanges",
"route53:ListHealthChecks",
"route53:CreateHealthCheck",
"route53:GetHostedZoneCount",
"route53:GetHealthCheckCount",
"route53:GetChange",
"route53:ListTagsForResource"
],
"Resource": "*"
}
]
}

3. Now in provider.tf file add below configuration

# we provision resources only in aws
# region is defined by the variables
provider "aws" {
region = "eu-central-1"
assume_role {
role_arn = "<ARN OF THE ROLE CREATED IN MAIN ACCOUNT>"
}
alias = "route53"
}
provider "aws" {
region = "eu-central-1"
}
terraform {
backend "s3" {
bucket = "<BACKEND S3 bucket>"
key = "demo/demo.tfstate"
region = "eu-central-1"
}
}

4. Use the new above alias in route53 resource.

resource "aws_route53_record" "bar1"{ 
zone_id = data.aws_route53_zone.zone.zone_id
name = "bar1.bar.example.org"
type = "CNAME"
ttl = "300"
records = ["${aws_instance.bar1.public_dns}"]
provider = "aws.route53"
}

In this scenario we are assuming you already a hosted done setup in main account so using data element in variables.tf we are just calling it in terraform.

Now you just need to do terraform init and apply and see a automatic entry updated in main account.

Hope this helps you guys !!!! Please let me know if something is unclear and needs to be improved.

BOOM you did it :)

--

--

Manoj Bhagwat

Trying new things. Breaking stuff. Likes open source | DevOps | Find me on LinkedIn 🔎. https://www.linkedin.com/in/manoj-bhagwat-73045082/