{"id":4646,"date":"2025-10-06T08:39:54","date_gmt":"2025-10-06T08:39:54","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=4646"},"modified":"2025-10-06T08:39:54","modified_gmt":"2025-10-06T08:39:54","slug":"working-with-aws-using-terraform-cross-accounts-aliases","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=4646","title":{"rendered":"Working with AWS using Terraform Cross-Accounts (Aliases)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A potential scenario is to have a single Terraform template repository where you need to manage AWS resources across a number of different AWS Accounts. However, because each AWS Account is the edge of its authentication and authorisation profile, there is a need to be able cross this boundary within your Terraform to be able to manage resources cross-account. A method of doing this is by the use of &#8220;aliases&#8221; within your Terraform, however you need to have your workstation&#8217;s AWS Configuration configured appropriately and specify the aliases on each resource to ensure Terraform is managing the expected resource where it is located.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is possible to have a &#8220;provider of last resort&#8221;, i.e. a provider which you have no aliases defined for, by doing this if you don&#8217;t include an alias\/provider in the resource definition, it is assumed by Terraform to use this &#8220;last resort&#8221;, if you chose to do this is mostly down to your own preferences, however if you do manage accounts across AWS Account boundaries, being explicit in each resource can reduce the likelihood of unexpected results!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"WorkingwithAWSusingTerraformCrossAccounts(Aliases)-DefineAWSConfiguration(Profiles)onyourAWS\/TerraformWorkstation\">Define AWS Configuration (Profiles) on your AWS\/Terraform Workstation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Although your locations and requirements will vary here is a simple example where I have an SSO (Single Sign On) based configuration along with two AWS Accounts (which I&#8217;ll use to create resources). My AWS configuration file was located in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~\\.aws\\config<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So we define the SSO session followed by the two profiles for our two AWS Accounts (~\\.aws\\config).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;sso-session mysso]\nsso_start_url = https:\/\/3dfbv5d671.awsapps.com\/start#\nsso_region = eu-west-2\nsso_role_name = AWSAdministratorAccess\nsso_registration_scopes = sso:account:access\n\n&#91;profile hub-account]\nsso_session = mysso\nsso_account_id = 12345678910\nsso_role_name = AWSAdministratorAccess\nregion = eu-west-2\n\n&#91;profile spoke-account]\nsso_session = mysso\nsso_account_id = 10987654321\nsso_role_name = AWSAdministratorAccess\nregion = eu-west-2<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once those are added, you would authenticate as you normally would be using specifying a profile if you so require, although this is not mandatory because we&#8217;ll be specifying the actual profile (i.e. AWS Accounts) we want to use explicitly.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export AWS_PROFILE=hub-account\naws sso login --profile=$AWS_PROFILE<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"WorkingwithAWSusingTerraformCrossAccounts(Aliases)-DefineProviders(withAliases)inyourTerraform\">Define Providers (with Aliases) in your Terraform<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We next need to define the &#8220;providers&#8221; within our Terraform. Within these definitions we include the &#8220;alias&#8221; for which we want to refer to the AWS Account when creating AWS resources within our Terraform. (providers.tf)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>...\n\n# Hub\nprovider \"aws\" {\n  alias   = \"hub\"\n  region  = \"eu-west-2\"\n  profile = \"hub-account\"\n}\n\n# Spoke\nprovider \"aws\" {\n  alias   = \"spoke\"\n  region  = \"eu-west-2\"\n  profile = \"spoke-account\"\n}\n\n...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see, we are using a simple example as Hub and Spoke, our first definition is for a &#8220;Hub&#8221; Account where some network resources (e.g. TGW) will be deployed, then we&#8217;ll have a &#8220;Spoke&#8221; account where we&#8217;ll run some workloads, that will need to be &#8220;connected&#8221; to network resources (i.e. the TGW) within the &#8220;Hub&#8221; Account, although the mechanics of doing this are outside the scope of this document; this focusses on how you can refer to resources when using the Aliases.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notice that the names specified in the &#8220;profile&#8221; line refer to the same name as is used within your AWS config file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"WorkingwithAWSusingTerraformCrossAccounts(Aliases)-DefineAWSResourceswithAliasestotheRequiredAccount\">Define AWS Resources with Aliases to the Required Account<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OK, so now we are ready to define the AWS Resources within the &#8220;Hub&#8221; and &#8220;Spoke&#8221; accounts. Let&#8217;s just use something really simple, a VPC (Virtual Private Cloud) definition. We&#8217;ll create one in each AWS Account and use the &#8220;Alias&#8221; (Provider) to tell Terraform which of the two profiles (i.e. providers) to use to create the VPC.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"aws_vpc\" \"hub_vpc\" {\n  provider             = aws.hub\n  cidr_block           = \"10.0.0.0\/16\"\n  instance_tenancy     = \"default\"\n  enable_dns_support   = true\n  enable_dns_hostnames = true\n\n  tags = {\n    Name = \"hub_vpc\"\n  }\n}\n\nresource \"aws_vpc\" \"spoke_vpc\" {\n  provider             = aws.spoke\n  cidr_block           = \"10.1.0.0\/16\"\n  instance_tenancy     = \"default\"\n  enable_dns_support   = true\n  enable_dns_hostnames = true\n\n  tags = {\n    Name = \"spoke_vpc\"\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And that&#8217;s it, now when you run the Terraform Apply, it will use the two different Aliases (providers) to create the resources in the appropriate AWS account. Of course, you need to have logged in via SSO first!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A potential scenario is to have a single Terraform template repository where you need to manage AWS resources across a number of different AWS Accounts. However, because each AWS Account is the edge of its authentication and authorisation profile, there is a need to be able cross this boundary within your Terraform to be able &#8230; <a title=\"Working with AWS using Terraform Cross-Accounts (Aliases)\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=4646\" aria-label=\"Read more about Working with AWS using Terraform Cross-Accounts (Aliases)\">Read more<\/a><\/p>\n","protected":false},"author":4,"featured_media":4373,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,45],"tags":[],"class_list":["post-4646","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aws","category-terraform"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4646"}],"version-history":[{"count":1,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4646\/revisions"}],"predecessor-version":[{"id":4647,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4646\/revisions\/4647"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/media\/4373"}],"wp:attachment":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}