Terraform Cloud: dynamic provider credentials and aliases

579 Views Asked by At

Following this example from Hashicorp, I'm struggling to understand the right way to populate Aliases for AWS Providers.

Let's assume I've got 2 AWS Roles in 2 different accounts, OIDC is configured properly for Terraform Cloud to access them:

  • arn:aws:iam::123456789012:role/test-terraform-cloud-access
  • arn:aws:iam::123456789013:role/staging-terraform-cloud-access

Now, following the documentation, I use:

  • TFC_AWS_PROVIDER_AUTH = true
  • TFC_AWS_RUN_ROLE_ARN = arn:aws:iam::123456789012:role/test-terraform-cloud-access

Now, based on their documentation, they advice using this config:

variable "tfc_aws_dynamic_credentials" {
  description = "Object containing AWS dynamic credentials configuration"
  type = object({
    default = object({
      shared_config_file = string
    })
    aliases = map(object({
      shared_config_file = string
    }))
  })
}

Then you can target the alias this way:

provider "aws" {
  shared_config_files = [var.tfc_aws_dynamic_credentials.default.shared_config_file]
}

provider "aws" {
  alias = "ALIAS1"
  shared_config_files = [var.tfc_aws_dynamic_credentials.aliases["ALIAS1"].shared_config_file]
}

My questions are:

  • Where does this shared_config_file is configured in Terraform Cloud?
  • How do I indicate my secondary role to use for this alias such as ["STAGING"]?
  • I was looking at the vault example, can I use something like TFC_AWS_RUN_ROLE_ARN_STAGING for this to work?

I did try the last one, but it doesn't seem to be picked up by the system.

Thanks a lot again!

2

There are 2 best solutions below

2
Martin Atkins On BEST ANSWER

If you have multiple configurations for the hashicorp/aws provider that each need a separate dynamic credentials configuration then you must also consider the companion tutorial Specifying Multiple Configurations. The tutorial you linked in your question is focused on the simpler and more common case of using only a single set of dynamic credentials for each provider.

The tutorial describes setting additional environment variables where each has a suffix which will appear as the key in the aliases map.

In your case then, if you want to use the "staging" ARN for ALIAS1 then you would set the environment variables as follows:

  • TFC_AWS_RUN_ROLE_ARN to arn:aws:iam::123456789012:role/test-terraform-cloud-access
  • TFC_AWS_RUN_ROLE_ARN_ALIAS1 to arn:aws:iam::123456789013:role/staging-terraform-cloud-access

With those two environment variables set, your var.tfc_aws_dynamic_credentials object should contain both the default object as before, referring to an AWS configuration file for the "test" role, and also have an ALIAS1 key in aliases whose object refers to a separate AWS configuration file for the "staging" role.

A configuration like you wrote should then work:

variable "tfc_aws_dynamic_credentials" {
  description = "Object containing AWS dynamic credentials configuration"
  type = object({
    default = object({
      shared_config_file = string
    })
    aliases = map(object({
      shared_config_file = string
    }))
  })
}

provider "aws" {
  shared_config_files = [
    var.tfc_aws_dynamic_credentials.default.shared_config_file,
  ]
}

provider "aws" {
  # Notice that this "alias" doesn't need to match the one
  # in the environment variable. These are two separate
  # namespaces, so you can use the same names here if you
  # like but that's not actually required.
  alias = "staging"
  shared_config_files = [
    var.tfc_aws_dynamic_credentials.aliases["ALIAS1"].shared_config_file,
  ]
}

These shared_config_file arguments refer to AWS configuration files as described in the AWS docs Shared config and credentials files. When you're using dynamic credentials, Terraform Cloud's execution environment creates those files dynamically just before running Terraform CLI, and then passes the paths to those files in as as part of the input variable tfc_aws_dynamic_credentials.

Those configuration files contain information about which role to assume and which JSON Web Token to use to authenticate to the AWS APIs. Therefore the file associated with ALIAS1 will specify the staging role ARN, while the file associated with the "default" object will specify the testing role ARN.

0
Oli at cdcloudlogix.com On

Thanks @martin for your previous and complete answer. One last important detail in order to have Aliases working properly in Terraform Cloud, you need to enable Alias in your environment too, i.e:

TFC_AWS_PROVIDER_AUTH_ALIAS1 = true

Alongside with TFC_AWS_RUN_ROLE_ARN_ALIAS1 to arn:aws:iam::123456789013:role/staging-terraform-cloud-access

If you don't do that, var.tfc_aws_dynamic_credentials.aliases object will be left empty.