Manage an AWS Landing Zone using AWS Control Tower Account Factory for Terraform

AWS Control Tower Account Factory for Terraform

An AWS Landing Zone provides the perfect platform for customers to set up a secure, multi-account AWS environment based on AWS best practices. This is done by implementing the initial security baseline, core AWS accounts, and resources.

The AWS Control Tower has become the de facto standard for quick and easy deployment of the Landing Zone on AWS. A Control Tower deployment offers a baseline architecture, which can further be customized and built using Customizations for AWS Control Tower. This customization uses AWS CloudFormation under the hood and is hence suitable for customers who are well versed with AWS CloudFormation to manage the infrastructure-as-Code.

AWS Control Tower Account Factory for Terraform

The AWS Control Tower team has recently released a Terraform Module called the AWS Control Tower Account Factory for Terraform (AFT) for those who want to leverage HashiCorp’s Terraform to work alongside the AWS Control Tower.

The AFT Module supplements an existing Control Tower deployment and helps to provide and manage a landing zone environment using configuration repositories and deployment pipelines. The module is maintained by the AWS Control Tower team.

AFT Components and Work Flow

AFT uses deployment pipelines to provision, customize, and manage a landing zone. These pipelines are triggered by changes made to a number of source code repositories. AFT supports GitHub, GitHub Enterprise, AWS CodeCommit, and Bitbucket as the choice for storing your source code.

These deployment pipelines and other relevant resources are provisioned by deploying the AFT module within an existing AWS Control Tower environment. Most of the resources for AFT are provisioned within a dedicated AWS account (referred to as the AFT Management Account) as shown in the above diagram. The AFT module works with Terraform Open Source (OSS), Terraform Cloud, and Terraform Enterprise.

AFT pipelines use configuration defined across 4 different source code repositories –

Repository Name (Default) Repository Purpose
aft-account-request New account provisioning request using AFT
aft-global-customizations Specify customizations to apply to all accounts created by AFT
aft-account-customizations Specify account-related customizations
aft-account-provisioning-customizations Specify provisioning-time customizations to apply to accounts

Note – The repository names given above can be customized as needed.

Workflow – Developers push changes to the respective repositories as needed, which triggers the following AFT workflow to provision and customize the account(s) –

  1. An AWS CodePipeline pipeline downloads the source code (Terraform files), and runs them within CodeBuild, which inserts an item in a DynamoDB table. The insertion of the item triggers a Lambda function which puts the request into an SQS-FIFO queue. The use of an SQS-FIFO queue within the workflow enables placing multiple requests simultaneously.
  2. Another Lambda function then reads the message placed on the queue and invokes the AWS Control Tower account vending machine within the Control Tower Management account. Once an account is provisioned by Control Tower, the workflow moves back to the AFT Management account for further processing.
  3. Lambda functions within the AFT management account trigger an account-specific customization pipeline for further customizations to the vendor account(s).

AFT Deployment


  • Existing Control Tower deployment
  • Dedicated OU for AFT (recommended, not mandatory)
  • Dedicated AWS account for AFT module resources
  • Terraform environment configured with
    • terraform version >= 0.15
    • Administrator credentials of Control Tower Management Account.

Deployment Steps

Once the above pre-requisites are met and you have access to a suitable terraform environment, create a file that uses the AFT Module. Below is a sample file with some of the module parameters –

module "aft" {
    source = ""
    # Required Vars
    ct_management_account_id    = "121212121212"
    log_archive_account_id      = "343434343434"
    audit_account_id            = "565656565656"
    aft_management_account_id   = "787878787878"
    ct_home_region              = "ap-south-1"
    tf_backend_secondary_region = "ap-southeast-1"

    # Optional vars
    terraform_distribution = "oss"  # Default - supports oss, tfc, or tfe
    vcs_provider           = "codecommit"   # Default - supports codecommit, bitbucket, github, or githubenterprise

    # Optional Repo Names
    account_request_repo_name = "blazeclan-aft-account-request"
    global_customizations_repo_name = "blazeclan-aft-global-customizations"
    account_customizations_repo_name = "blazeclan-aft-account-customizations"
    account_provisioning_customizations_repo_name = "blazeclan-aft-account-provisioning-customizations"

    # Optional Feature Flags
    aft_feature_delete_default_vpcs_enabled = false # Default
    aft_feature_cloudtrail_data_events      = false # Default
    aft_feature_enterprise_support          = false # Default

    # AFT Vpc
    aft_vpc_endpoints = false


Below is a description of the parameters used above:

Parameter Name Type Description
ct_management_account_id Required Control Tower Management Account Id
log_archive_account_id Required Log Archive Account Id
audit_account_id Required Audit Account Id
aft_management_account_id Required Account Id of dedicated AWS account for AFT
ct_home_region Required Must be set as the AWS Region where Control Tower is deployed. AFT uses this region for resource deployment as well as the primary region for Terraform State storage.
tf_backend_secondary_region Required Secondary Region for Terraform State storage
terraform_distribution Optional Select between Terraform open source (default), Enterprise, or Cloud
vcs_provider Optional Selection of VCS provider for AFT repositories AWS CodeCommit (default), GitHub, GitHub Enterprise, or BitBucket
account_request_repo_name Optional Repository name for the account request files. For non-CodeCommit repos, name should be in the format of Org/Repo
global_customizations_repo_name Optional Repository name for the global customization files. For non-CodeCommit repos, name should be in the format of Org/Repo
account_customizations_repo_name Optional Repository name for the account customizations files. For non-CodeCommit repos, name should be in the format of Org/Repo
account_provisioning_customizations_repo_name Optional Repository name for the account provisioning customizations files. For non-CodeCommit repos, name should be in the format of Org/Repo
aft_feature_delete_default_vpcs_enabled Optional Feature flag toggling deletion of default VPCs on/off for vended accounts
aft_feature_cloudtrail_data_events Optional Feature flag toggling CloudTrail data events on/off for vended accounts
aft_feature_enterprise_support Optional Feature flag toggling Enterprise Support enrollment on/off for vended accounts
aft_vpc_endpoints Optional Flag turning VPC endpoints on/off for AFT VPC

Please refer to the instructions in the AWS documentation for detailed deployment steps and the AFT Module README for available parameters and options. Once the file is ready with the required parameter values, the AFT module can be deployed by using the below standard terraform commands:

$ terraform init
$ terraform apply

This operation will deploy approximately 300+ resources across all Control Tower accounts and will take about 30 mins to complete. Good time to grab a coffee!

To deploy AFT module resources, Terraform initially authenticates with the Control Tower Management account and then assumes the AWS Control Tower Execution role to deploy resources to other Control Tower accounts. Once the operation is complete, we then login to the AFT-Management account to have a look around. We navigate to CodeCommit and see 4 empty repositories created.

These repositories can now be used to trigger the AFT workflow pipelines for account provisioning, customizations and management. We are now all set to start on our journey with the AFT Module.

Learn More

To see the AFT account provisioning and customization pipelines in action, register for our upcoming webinar on 19th May 2022.