Shape
Shape

Work with multiple AWS accounts

Aws Use cases Cli Aws iam

Work with multiple AWS accounts

Motivation

The most secure way to manage infrastructure in AWS is to use multiple AWS accounts. You define all your IAM users in one account (e.g., the “security” account) and deploy all of your infrastructure into a number of other accounts (e.g., the “dev”, “stage”, and “prod” accounts). To access those accounts, you login to the security account and assume an IAM role in the other accounts.

There are a few ways to assume IAM roles when using AWS CLI tools, such as Terraform:

  1. One option is to create a named profile, each with a different role_arn parameter. You then tell Terraform which profile to use via the AWS_PROFILE environment variable. The downside to using profiles is that you have to store your AWS credentials in plaintext on your hard drive.

  2. Another option is to use environment variables and the AWS CLI. You first set the credentials for the security account (the one where your IAM users are defined) as the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and run aws sts assume-role --role-arn <ROLE>. This gives you back a blob of JSON that contains new AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY values you can set as environment variables to allow Terraform to use that role. The advantage of this approach is that you can store your AWS credentials in a secret store and never write them to disk in plaintext. The disadvantage is that assuming an IAM role requires several tedious steps. Worse yet, the credentials you get back from the assume-role command are only good for up to 1 hour, so you have to repeat this process often.

  3. A final option is to modify your AWS provider with the assume_role configuration and your S3 backend with the role_arn parameter. You can then set the credentials for the security account (the one where your IAM users are defined) as the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and when you run terraform apply or terragrunt apply, Terraform/Terragrunt will assume the IAM role you specify automatically. The advantage of this approach is that you can store your AWS credentials in a secret store and never write them to disk in plaintext, and you get fresh credentials on every run of apply, without the complexity of calling assume-role. The disadvantage is that you have to modify all your Terraform / Terragrunt code to set the role_arn param and your Terraform backend configuration will change (and prompt you to manually confirm the update!) every time you change the IAM role you’re using.

To avoid these frustrating trade-offs, you can configure Terragrunt to assume an IAM role for you, as described next.

Configuring Terragrunt to assume an IAM role

To tell Terragrunt to assume an IAM role, just set the --terragrunt-iam-role command line argument:

terragrunt apply --terragrunt-iam-role "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"

Alternatively, you can set the TERRAGRUNT_IAM_ROLE environment variable:

export TERRAGRUNT_IAM_ROLE="arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
terragrunt apply

Additionally, you can specify an iam_role property in the terragrunt config:

iam_role = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"

Terragrunt will resolve the value of the option by first looking for the cli argument, then looking for the environment variable, then defaulting to the value specified in the config file.

Terragrunt will call the sts assume-role API on your behalf and expose the credentials it gets back as environment variables when running Terraform. The advantage of this approach is that you can store your AWS credentials in a secret store and never write them to disk in plaintext, you get fresh credentials on every run of Terragrunt, without the complexity of calling assume-role yourself, and you don’t have to modify your Terraform code or backend configuration at all.