terraform-aws-control_tower_account_factory icon indicating copy to clipboard operation
terraform-aws-control_tower_account_factory copied to clipboard

Allow to pass AWS_PROFILE to the module

Open LozanoMatheus opened this issue 1 year ago • 3 comments

Describe the outcome you'd like

Currently, we need to export the environment variable to terraform, so it can do the work. It would be really great if we could just not need to do so.

For example, right now we need to do this

export AWS_PROFILE="<MY_AWS_PROFILE>"
terraform ...

# or

AWS_PROFILE="<MY_AWS_PROFILE>" terraform ...

Is your feature request related to a problem you are currently experiencing? If so, please describe.

I've some TF files automatically generated (e.g. the providers, global env vars, etc), so I don't have to care about it when switching between accounts in the same or different organization. Since this is done in Terraform itself, adding something outside of Terraform makes it a bit annoying/complex for me to do.

Also, if

Additional context

We could change the providers.tf to have something like for all providers

provider "aws" {
  profile = var.aws_profile != "" ? var.aws_profile : "default"
...

For the tf_backend_secondary_region, we also need to change the region.

  region  = var.tf_backend_secondary_region != "" ? var.tf_backend_secondary_region : var.ct_home_region

We also need to add it in the variables.tf

variable "aws_profile" {
  type        = string
  description = "Define your AWS_PROFILE"
  default     = ""
  validation {
    condition     = can(regex("^[A-Za-z].*[-_A-Za-z0-9]+$", var.aws_profile)) || contains([""], var.aws_profile)
    error_message = "Define the AWS_PROFILE, only alphanumeric and - or _"
  }
}

If we don't change the region, we'll get this error:

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: configuring Terraform AWS Provider: validating provider credentials: retrieving caller identity from STS: operation error STS: GetCallerIdentity, failed to resolve service endpoint, an AWS region is required, but was not found
│
│   with module.aft.provider["registry.terraform.io/hashicorp/aws"].tf_backend_secondary_region,
│   on .terraform/modules/aft/providers.tf line 30, in provider "aws":
│   30: provider "aws" {
│
╵
ERRO[0125] Terraform invocation failed in /<path>/<to>/<my/<tf>/<code>/aft
ERRO[0125] 1 error occurred:
        * exit status 1

Then we can call it something like this

module "aft" {
  source = "github.com/aws-ia/terraform-aws-control_tower_account_factory"
  # Required Vars
  ct_management_account_id    = "111122223333"
  log_archive_account_id      = "444455556666"
  audit_account_id            = "123456789012"
  aft_management_account_id   = "777788889999"
  ct_home_region              = "us-east-1"
  aws_profile                 = var.aws_profile
}

LozanoMatheus avatar May 19 '23 15:05 LozanoMatheus

Hey @LozanoMatheus! Thanks for bringing this issue up! I've gone ahead and made a backlog with the team to allow passing the AWS_Profile environment variable to the terraform module

hanafya avatar May 19 '23 18:05 hanafya

@LozanoMatheus the AFT module is intended to be called by the root module, hence we rely on inheritance of default provider configuration from the root module.

For your use-case, what is preventing you to do something like this:

provider "aws" {
  profile = var.aws_profile != "" ? var.aws_profile : "default"
}

module "aft" {
  source = "github.com/aws-ia/terraform-aws-control_tower_account_factory"
  # Required Vars
  ...
}

Thanks!

wellsiau-aws avatar Jun 29 '23 02:06 wellsiau-aws

I'm seeing the same behavior. In my root module I have for provider:

provider "aws" {
  region  = var.region
  profile = "muh-profile"
  default_tags {
    tags = var.common_tags
  }
}

My profile looks like this in ~/.aws/config

[default]
region=us-east-1

[sso-session company-sso]
sso_region=us-east-1
sso_start_url=https://example-company.awsapps.com/start#/
sso_registration_scopes=sso:account:access

[profile muh-profile]
region=us-east-1
sso_session=company-sso
sso_account_id=111111111111
sso_role_name=AWSAdministratorAccess

Where I pass my sso profile. When I try a terraform plan I receive:

│ Error: No valid credential sources found
│ 
│   with module.control_tower_account_factory.provider["registry.terraform.io/hashicorp/aws"].ct_management,
│   on .terraform/modules/control_tower_account_factory/providers.tf line 4, in provider "aws":
│    4: provider "aws" {
│ 
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│ 
│ Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, request canceled, context deadline exceeded

However if I update ~/.aws/config and update my default profile to use my sso credentials:

[default]
region=us-east-1
sso_session=company-sso
sso_account_id=111111111111
sso_role_name=AWSAdministratorAccess

[sso-session company-sso]
sso_region=us-east-1
sso_start_url=https://example-company.awsapps.com/start#/
sso_registration_scopes=sso:account:access

Then terraform plan gives me no errors.

Could perhaps update this line to optionally take a profile if provided (just like @wellsiau-aws showed), or a users AWS_PROFILE environment variable (if set)?

provider "aws" {
  alias  = "ct_management"
  region = var.ct_home_region
  profile = length(trimspace(environment("AWS_PROFILE"))) > 0 ? environment("AWS_PROFILE") : (var.aws_profile != "" ? var.aws_profile : "default")
  default_tags {
    tags = {
      managed_by = "AFT"
    }
  }
}

However, if I simply run export AWS_PROFILE=muh-profile, then terraform plan works fine 😄

maafk avatar Jan 14 '24 11:01 maafk