Posted on 1 April 2020, updated on 21 December 2023.

When using Terraform with other people it’s often useful to store your state in a bucket. For example, an S3 bucket if you deploy on AWS. And then you may want to use the same bucket for different AWS accounts for consistency purposes. Or you may also want your S3 bucket to be stored in a different AWS account for right management reasons. 

But how to use a Terraform state stored in one AWS account and deploy in another one? That’s what you’ll discover now.

AWS account architecture

The following figure shows what we want to establish.

AWS-accounts

The idea is to have an AWS root account, that gives the user access to 4 accounts:

  • Infra account: it contains the Terraform state bucket
  • Dev account: dev environment
  • Preprod account: preprod environment
  • Prod account: prod environment

We want to be able to perform a `terraform apply` from the AWS root account, that will access the Terraform state in the S3 bucket of the Infra account, in order to deploy resources on either one of dev, preprod or prod environments.

We assume in this article the user has set up the proper credentials and has currently access to the root account. We also assume that a role named “deploy” exists in each of the 4 non root accounts and that the user has the proper rights to assume this role in each account because Terraform will need this. If you didn’t already do it, then you’ll find here how to apply the same Terraform on multiple AWS accounts. Also find out here how AWS IAM roles work.

Setup Terraform provider and backend configurations

The main thing to understand here is that Terraform doesn’t use the AWS provider configuration in order to access the state bucket. It only uses the backend one.

So for this to work you need to configure the proper assume roles in the Terraform backend and provider configurations separately.

Backend configuration in `backend.tf`, add your Infra AWS account ID (the account that contains your state bucket) :

Provider configuration in `provider.tf`:

At this point, we can notice that it’s possible to use variables in the provider, whereas it’s unfortunately not possible to do so in the backend configuration. That’s not a problem for this example since the backend will be the same for all environments.

Setup workspaces configurations

Now you can setup a Terraform “.tfvars” file for each environment.

Dev configuration in `dev.tfvars`:

Preprod configuration in `preprod.tfvars`:

Prod configuration in `preprod.tfvars`:

And then create the associated Terraform workspaces:

Apply Terraform on one account

To be sure to deploy with Terraform your preprod environment on the preprod AWS account, for example, you can do this like this:

This is one way to make sure you use the configuration of the workspace you’re on while keeping the possibility to put configurations in different files: one for each workspace.

We saw in this article everything you will need to configure your Terraform deployment in order to use a Terraform state bucket that is stored in another AWS account. Terraform will this way be able to get its state from a bucket in one account, and then deploy in another account.