aws-ia / terraform-aws-control_tower_account_factory

AWS Control Tower Account Factory
Apache License 2.0
629 stars 418 forks source link

Add example for deploying private Terraform modules with AFT #215

Open stumins opened 2 years ago

stumins commented 2 years ago

Describe the outcome you'd like

AFT 1.5.0 flattened the customization pipeline stages into a single container for per-account customizations, and a single container for global customizations. This allows customers to add authentication steps to pre-api-helpers.sh and have any set variables / configurations persist through the terraform apply and post-api-helpers.sh executions.

Using this technique enables deploying private Terraform modules using AFT by authenticating to the private registry during the the pre-api-helpers stage. However, this process is undocumented and requires some understanding how AFT's internals function.

Adding an example of how to deploy private Terraform modules to the AFT repository will make this process more clear & easier to achieve without deep understanding of AFT.

MichaelYak commented 2 years ago

@stumins Are you taking about using static secrets for authentication, e.g. personal access token for github? Do you plan to support use of aws codestar connection for this use case? For example: if the existing codestar connection, in addition to giving access to aft-account-customizations, also gives access to customization dependences (terraform modules used by customization)? Maybe use of "full clone" in codepipeline (source stage)?

stumins commented 2 years ago

@MichaelYak

The pre-api-helpers.sh and post-api-helpers.sh are scripts defined by users that are executed before and after terraform apply in the customization pipelines, and are not inherently opinionated about the methods of authentication.

One could leverage static secrets by storing them in AWS Secrets Manager or AWS Systems Manager Parameter Store (with appropriate encryption and access controls), granting access to the IAM role that AFT uses, and then querying them at runtime using the helper scripts before making calls to external services.

Alternatively, dependency resources could be made directly available in the AFT management account (via CodeStar, S3, or other AWS services) and accessed via AWS API calls authenticated using the AFT IAM role.

We do not currently have a backlog to directly integrate CodeStar beyond connecting to AFT repositories hosted externally, but please feel free to cut us a Feature Request for the use case you have in mind.

ivansamartino commented 1 year ago

@stumins , one concern that I have about the pre-api-helpers.sh handling the authentication setup is in the account customizations repository. You would need to duplicate the pre-api-helpers code in all the accounts if you are using mainly private github repositories for your Terraform modules.

I have tried using symlinks in the account customizations repo, but the core of the AFT framework (the buildspec of the Code Pipeline project) does not handle it. Maybe it could be worth to actually support it in the core of the AFT framework, don't you think?

snebhu3 commented 1 year ago

Reference: Also requested via issue 327

johnjelinek commented 1 year ago

It seems like maybe this ought to work out of the box now with the GitHub version 2 app CodeStar connection.

yves-vogl commented 12 months ago

Just for the sake of documentation:

I try adding an access token to access a gitlab.com hosted private Terraform Module registry.

In my code I'm calling a module like this:

module "cloudwatch_oam" {

  source  = "gitlab.com/xxx/terraform-cloudwatch-oam/aws"
  version = "~> 0.1"

  sink_identifier = nonsensitive(data.aws_ssm_parameter.monitoring_account_id.value)
}

Terraform allows to authenticate to private registries by either specifying credentials in a CLI configuration file or by exposing environment variables (see https://developer.hashicorp.com/terraform/cli/config/config-file)

Therefore I tried to use in pre-api-helpers.sh the following code:

export TF_TOKEN_gitlab_com=$(aws secretsmanager get-secret-value --secret-id arn:aws:secretsmanager:eu-central-1:*****:secret:**** | jq -r ".SecretString" | jq -r ".TF_TOKEN_gitlab_com")

But that does not work. I'm now trying to figure out why.