{"id":6,"date":"2022-03-23T10:31:00","date_gmt":"2022-03-23T15:31:00","guid":{"rendered":"https:\/\/34.82.124.6\/?p=6"},"modified":"2022-04-29T10:33:18","modified_gmt":"2022-04-29T15:33:18","slug":"terraform-aws-cross-account-access","status":"publish","type":"post","link":"https:\/\/cloudlearning365.com\/?p=6","title":{"rendered":"Terraform AWS Cross-Account access"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Pre-requisite<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Two AWS accounts: AccountA and AccountB<\/li><li>IAM programmatic access user already setup and working for Terraform in AccountA, let\u2019s call this user&nbsp;<strong>Terraform-User<\/strong>, and it already have role assigned in AccountA<\/li><li>Now that we are going to use the same&nbsp;<strong>Terraform-User<\/strong>&nbsp;access key and secret to work on resources in AccountB<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Create a new role in AccountB<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Trusted entity -&gt; AWS account -&gt; since AccountB need to trust AccountA, enter AccountA\u2019s account ID<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cloudlearning365.com\/wp-content\/uploads\/2022\/03\/image-25-1024x424.png\" alt=\"\" class=\"wp-image-63\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>Assign required permission polices to this role, eg: AdministratorAccess<\/li><li>Assign a role name, eg: CrossAccountSignin<\/li><li>Example of the role JSON created<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": &#091;\n        {\n            \"Effect\": \"Allow\",\n            \"Principal\": {\n                \"AWS\": \"arn:aws:iam::<em><strong>AccountA_Account_ID<\/strong><\/em>:root\"\n            },\n            \"Action\": \"sts:AssumeRole\",\n            \"Condition\": {}\n        }\n    ]\n}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Note down the ARN of this role, eg:<br>arn:aws:iam::<em><strong>AccountB_Account_ID<\/strong><\/em>:role\/<strong>CrossAccountSignin<\/strong><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Create and assign policy in AccountA<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Use following JSON definition<\/li><li>\u201cResource\u201d point to the ARN of the CrossAccountSignin role created in AccountB<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": &#091;\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": &#091;\n                \"sts:AssumeRole\"\n            ],\n            \"Resource\": \"arn:aws:iam::<em><strong>AccountB_Account_ID<\/strong><\/em>:role\/CrossAccountSignin\"\n        }\n    ]\n}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Assign this policy to AccountA IAM user:&nbsp;<strong>Terraform-User<\/strong><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Assume role in Terraform<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>providers.tf<br>Notice an alias gets created for account_b<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>provider \"aws\" {\n  region = \"us-east-1\"\n}\n\nprovider \"aws\" {\n  region = \"us-east-1\"\n  <strong>alias  = \"account_b\"<\/strong>\n  assume_role {\n    role_arn = \"<a href=\"https:\/\/cloudlearning365.com\/2022\/03\/23\/terraform-aws-cross-account-access\/role\/CrossAccountSignin\">arn:aws:iam::<em><strong>AccountB_Account_ID<\/strong><\/em>:role\/CrossAccountSignin<\/a>\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>main.tf<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"aws_vpc\" \"account_a_vpc\" {\n  cidr_block = \"10.0.1.0\/24\"\n  tags = {\n    \"Name\" = \"account_a_vpc\"\n  }\n}\n\n\nresource \"aws_vpc\" \"account_b_vpc\" {\n  <strong>provider   = aws.account_b<\/strong>\n  cidr_block = \"10.0.2.0\/24\"\n  tags = {\n    \"Name\" = \"account_b_vpc\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>resource.aws_vpc.account_<strong>a<\/strong>_vpc will create VPC in AccountA implicitly<\/li><li>resource.aws_vpc.account_<strong>b<\/strong>_vpc will create VPC in AccountB by explicitly specifying&nbsp;<strong>provider = aws.account_b<\/strong><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Cross account access to data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Similarly to resource block, you can perform the same for data block, example:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Same providers.tf<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>provider \"aws\" {\n  region = \"us-east-1\"\n}\n\nprovider \"aws\" {\n  region = \"us-east-1\"\n  <strong>alias  = \"account_b\"<\/strong>\n  assume_role {\n    role_arn = \"<a href=\"https:\/\/cloudlearning365.com\/2022\/03\/23\/terraform-aws-cross-account-access\/role\/CrossAccountSignin\">arn:aws:iam::<em><strong>AccountB_Account_ID<\/strong><\/em>:role\/CrossAccountSignin<\/a>\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>data.tf<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>data \"aws_availability_zones\" \"az_zones\" {\n}\n\ndata \"aws_availability_zones\" \"app_az_zones\" {\n  provider = aws.<strong>account_b<\/strong>\n}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>data.aws_availability_zones.az_zones will retrieve availability zones as&nbsp;<strong>Terraform-User<\/strong>&nbsp;from AccountA<\/li><li>data.aws_availability_zones.app_az_zones\u201d will retrieve availability zones assume role in AccountB<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Cross account for module<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Assume we have following folder structure:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>|_ main.tf\n|  providers.tf\n|_ modules\n    |_ app\n         |_ main.tf\n         |_ providers.tf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Root \/providers.tf have following statement as before:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>provider \"aws\" {\n  region = \"us-east-1\"\n}\n\nprovider \"aws\" {\n  region = \"us-east-1\"\n  <strong>alias  = \"account_b\"<\/strong>\n  assume_role {\n    role_arn = \"<a href=\"https:\/\/cloudlearning365.com\/2022\/03\/23\/terraform-aws-cross-account-access\/role\/CrossAccountSignin\">arn:aws:iam::<em><strong>AccountB_Account_ID<\/strong><\/em>:role\/CrossAccountSignin<\/a>\"\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Root \/main.tf have following statement<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>module \"app1\" {\n  source   = \".\/modules\/app\"\n\n   .\n   .\n   .\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you run it, you may find resources gets created in the default account : AccountA, where&nbsp;<strong>Terraform-User<\/strong>&nbsp;is resided. How do we make the resource create in AccountB instead?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Think of module a mini block of terraform code that also require it\u2019s own provider block. If you don\u2019t specify anything in \/modules\/app\/providers.tf, it will implicitly have this block, basically it\u2019s looking for a provider called&nbsp;<strong>aws<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>provider \"aws\" {\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So we will modify \/main.tf like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>module \"app1\" {\n  source   = \".\/modules\/app\"\n   providers = {\n    aws = aws.<strong>account_b<\/strong>\n  }\n   .\n   .\n   .\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is telling within the module, provider.aws is equal to root provider.aws.account_b.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you rerun terraform apply. you will notice:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Resources created in AccountA remains<\/li><li>New resources get created in AccountB now<\/li><li>Warning message:<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>Warning: Provider aws is undefined\n\u2502\n\u2502   on main.tf line 8, in module \"app1\":\n\u2502    8:     aws = aws.<strong>account_b<\/strong>\n\u2502\n\u2502 Module module.app1 does not declare a provider named aws.\n\u2502 If you wish to specify a provider configuration for the module, add an entry for aws in the required_providers block within the module.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To make Terraform happy, add following lines in \/modules\/app\/providers.tf<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>terraform {\n  required_providers {\n\n    aws = {\n      source = \"hashicorp\/aws\"\n    }\n  }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Pre-requisite Two AWS accounts: AccountA and AccountB IAM programmatic access user already setup and working for Terraform in AccountA, let\u2019s call this user&nbsp;Terraform-User, and it already have role assigned in AccountA Now that we are going to use the same&nbsp;Terraform-User&nbsp;access &hellip; <a href=\"https:\/\/cloudlearning365.com\/?p=6\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[8],"tags":[],"class_list":["post-6","post","type-post","status-publish","format-standard","hentry","category-terraform"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=\/wp\/v2\/posts\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6"}],"version-history":[{"count":1,"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=\/wp\/v2\/posts\/6\/revisions"}],"predecessor-version":[{"id":8,"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=\/wp\/v2\/posts\/6\/revisions\/8"}],"wp:attachment":[{"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudlearning365.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}