Search code examples
terraformamazon-iamopenid-connectterraform-provider-awsterraform-cloud

Terraform Cloud: dynamic provider credentials and aliases


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!


Solution

  • 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.