Posted on 25 December 2019, updated on 21 December 2023.

You are using Terraform with AWS (Amazon Web Services) and you want to deploy your resources on several accounts? You want to use workspaces to isolate your environments but you can’t set the `provider` parameter as a variable? Learn how to do it in three minutes!

The issue: deploy the same Terraform code on multiple AWS accounts

I was terraforming my AWS infrastructure with this idea in mind: I deploy one environment for each namespace, I create (3 in my case) and the AWS account isn’t the same depending on the environment. To accomplish this, I thought of defining an AWS provider with an alias for each account and then add in my resources the `provider` parameter which would change in accordance with the workspace (using the terraform.workspace variable).

I was without considering that the `provider` argument MUST be hardcoded. It can’t be a variable, it can’t be a local, it can’t be in an `if` statement and so on. But there is still a way to do it.

Use IAM to change the default provider with Terraform

The tip is to use the AWS IAM Assume Role property. If you don’t know how AWS IAM works, this article can help you.

The tip is to change the default provider depending on your workspace:

  • Assume a role to apply to another account
  • Don’t assume a role to apply to your current account

To explain the bellow Terraform code, let’s say that you are connected to <AWS_ACCOUNT_1> using the AWS CLI. The <AWS_ACCOUNT_2> is the second account. We want to apply the workspace <ENV_1> to the first account and <ENV_2> to the second account.

Here is the code you need on your account:

This works only if <ROLE_NAME> is correctly set up. To manage accounts, I suggest you use another Terraform state: it allows you to manage resources that don’t depend on your environment with a single workspace.

Here is the Terraform part you need to apply to add the assume role policy to a group on your <AWS_ACCOUNT_1>:

It works only if the user you are using is part of the group you attach the policy to. Note that you can attach the policy to a specific user if you prefer.

Create the role to assume manually

One part is remaining but you can’t apply it with Terraform since it is on the <AWS_ACCOUNT_2> and assume role is still not working. Connect to the <AWS_ACCOUNT_2> using the AWS Console and create a role with the AdministratorAccess policy (you can give fewer rights, it’s up to you). In the `trusted account` tab, add this policy:

 

You can now apply the same Terraform on multiple AWS accounts without duplicating your code! If you want to go further on your IAM management with Terraform, the good practice is to have an account specifically to manage Users and to only allow assume role while doing actions on the others accounts!