Terraform AWS Control Tower Account Factory for Terraform AFT Deep Dive

AWS Control Tower Account Factory for Terraform provides a Terraform module that makes it easy to create and customize new accounts that comply with an organization’s security guidelines. AFT defines a pipeline for automated and consistent creation of AWS Control Tower accounts, giving you the benefits of Terraform’s workflow and Control Tower’s governance features. AWS maintains this module.

This article covers deployment, configuration, customization options, workflow components, state management, and teardown as described in the official tutorial and reference material.

Introduction

AWS Control Tower Account Factory for Terraform, commonly referenced as AFT, is a Terraform module designed to automate multi-account vending in an AWS Control Tower landing zone. Initially the multi-account vending system for AWS was called Landing Zones. Eventually Landing Zones got rebranded and restructured as AWS Control Tower. It is an opinionated way for provisioning AWS accounts with management tools like dashboards.

There are no public API endpoints for AWS Control Tower, so the only ways to automate provisioning are:
Manual provisioning - ClickOps
Customizations for AWS Control Tower - which uses CloudFormation
Target underlying AWS services that do have a Terraform provider or use a provider like idealo/controltower that does that for you
AWS Control Tower Account Factory for Terraform - AFT

Using AFT brings a GitOps driven workflow, HCLv2 usage, and is fully into both AWS and Terraform ecosystems with support. Security is built-in and aligned with Well-Architected Framework practices.

Prerequisites and Initial Setup

This tutorial assumes that you are familiar with the standard Terraform workflow. If you are new to Terraform, complete the Get Started tutorials first.

For this tutorial, you will need:
- Terraform v0.15+ installed locally configured with credentials for the non-root user with AdministratorAccess
- an AWS account, with credentials for a non-root user with the AdministratorAccess policy attached. Some steps can take up to 30 minutes, so make sure your credentials have a long enough duration

The tutorial guides you through the one-time steps required to deploy AFT to create the pipeline for account creation. Then, you will to use AFT to create and customize your Control Tower accounts. In this tutorial, you will deploy the AFT module, review the support account customization options, and learn about the components of AFT and its workflow.

Module Structure and File Layout

The reference configuration layout includes helper scripts and Terraform files for initial bootstrapping.

├── pre-api-helpers.sh │ └── python │ └── requirements.txt └── terraform ├── aft-providers.jinja └── backend.jinja

This configuration does not define any global customizations for your account.

AFT applies Account customizations to a specific account or set of accounts. It uses the customizations defined in the repository you pass to the accountcustomizationsrepo_name input variable.

Core AFT Module Declaration

A typical module block for AFT is declared in learn-terraform-aws-control-tower-aft/main.tf:

hcl module "aft" { source = "github.com/aws-ia/terraform-aws-control_tower_account_factory" ##... vcs_provider = "github" account_request_repo_name = "${var.github_username}/learn-terraform-aft-account-request" account_provisioning_customizations_repo_name = "${var.github_username}/learn-terraform-aft-account-provisioning-customizations" global_customizations_repo_name = "${var.github_username}/learn-terraform-aft-global-customizations" account_customizations_repo_name = "${var.github_username}/learn-terraform-aft-account-customizations" }

The value of that input variable must match a subdirectory of your account customizations repository.

Key Input Variables and Feature Flags

AFT exposes a set of input variables to control VPC creation, feature toggles, framework sourcing, and metrics.

VPC and Networking Variables

Name Description Default
aftvpccidr CIDR Block to allocate to the AFT VPC 192.168.0.0/22
aftvpcendpoints Flag turning VPC endpoints on/off for AFT VPC true
aftvpcprivatesubnet01_cidr CIDR Block to allocate to the Private Subnet 01 192.168.0.0/24
aftvpcprivatesubnet02_cidr CIDR Block to allocate to the Private Subnet 02 192.168.1.0/24
aftvpcpublicsubnet01_cidr CIDR Block to allocate to the Public Subnet 01 192.168.2.0/25
aftvpcpublicsubnet02_cidr CIDR Block to allocate to the Public Subnet 02 192.168.3.0/25

Feature Flags

Name Description Default
aftenablevpc Flag turning use of VPC on/off for AFT true
aftfeaturecloudtraildataevents Feature flag toggling CloudTrail data events on/off false
aftfeaturedeletedefaultvpcs_enabled Feature flag toggling deletion of default VPCs on/off false
aftfeatureenterprise_support Feature flag toggling Enterprise Support enrollment on/off false
aftmetricsreporting Flag toggling reporting of operational metrics true

Framework Sourcing Variables

Name Description Default
aftframeworkrepogitref Git branch from which the AFT framework should be sourced from null
aftframeworkrepo_url Git repo URL where the AFT framework should be sourced from https://github.com/aws-ia/terraform-aws-controltoweraccount_factory.git
aftmanagementaccount_id AFT Management Account ID n/a, required

Dependency and Version Requirements

AFT has defined provider and module dependencies.

Provider Requirements

Name Version
terraform >= 1.6.1, < 2.0.0
aws >= 6.0.0, < 7.0.0

Module Dependencies

Name Source Version
aftaccountprovisioning_framework ./modules/aft-account-provisioning-framework n/a
aftaccountrequest_framework ./modules/aft-account-request-framework n/a
aft_backend ./modules/aft-backend n/a
aftcoderepositories ./modules/aft-code-repositories n/a
aft_customizations ./modules/aft-customizations n/a
aftfeatureoptions ./modules/aft-feature-options n/a
aftiamroles ./modules/aft-iam-roles n/a
aftlambdalayer ./modules/aft-lambda-layer n/a
aftssmparameters ./modules/aft-ssm-parameters n/a
packaging ./modules/aft-archives n/a

Data Sources

Name Description Type
aws_partition.current data source
awsservice.homeregion_validation data source
localfile.pythonversion data source
local_file.version data source

Account Customization Inputs

Account customizations are maintained outside AFT and re-applied after AFT updates.

Name Description Type Default Required
accountcustomizationsrepo_branch Branch to source account customizations repo from string main no
accountcustomizationsrepo_name Repository name for the account customizations files string

Note that this customization must be maintained outside of AFT and re-applied after AFT updates.

State Management and Security Considerations

This artifact describes the state of the resources that Terraform created. If you plan to update the AFT version, make sure to preseve the Terraform state file, or set up a Terraform backend using Amazon S3 and DynamoDB. The AFT module doesn't manage a backend Terraform state.

Note
You're responsible for protecting the Terraform state file. Some input variables might contain sensitive values, such as a private ssh key or Terraform token. Depending on your deployment method, these values can be viewable as plain text in the Terraform state file. For more information, see Sensitive data in State

Workflow and Customization Options

AFT applies Account customizations to a specific account or set of accounts. It uses the customizations defined in the repository you pass to the accountcustomizationsrepo_name input variable.

The tutorial covers deploying the AFT module, reviewing the support account customization options, and learning about the components of AFT and its workflow.

Support account customization options can be toggled via feature flags such as aftfeaturecloudtraildataevents, aftfeaturedeletedefaultvpcsenabled, and aftfeatureenterprisesupport.

Teardown and Cleanup

Cleanup involves removing pipelines, emptying buckets, decommissioning accounts, and destroying Terraform resources.

Select the pipeline, then click Delete pipeline and confirm the deletion.

Next, navigate to your learn-terraform-aws-control-tower-aft repository, which contains a remove_buckets.sh script to empty and delete buckets created in your log archive and AFT management accounts.

Run the script.

$ ./remove_buckets.sh

Next, decommission your sandbox-aft account from your Control Tower landing zone. This disassociates your account, but does not close it.

Log in to the AWS Console as your Control Tower management user, then navigate to your Provisioned Products in ServiceCatalog.

Select the Account Access Filter, then select your sandbox-aft account.

Under Actions, click Terminate. Then click Terminate provisioned product to confirm the termination. This will remove the account from Control Tower, and move it under the Root organization for your account.

Then, run terraform destroy to delete the AFT resources from your account.

Respond yes to the prompt to confirm the operation.

$ terraform destroy

Plan: 0 to add, 0 to change, 297 to destroy.

Changes to Outputs:
- aftmanagementaccountid = "365371481900" -> null
- audit
accountid = "187724155000" -> null
- ct
managementaccountid = "447475458655" -> null
- logarchiveaccount_id = "866255933133" -> null
- region = "us-east-1" -> null

Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo

Conclusion

AWS Control Tower Account Factory for Terraform delivers a fully automated, GitOps driven account vending pipeline that integrates with AWS Control Tower governance. The module is maintained by AWS and provides a standard Terraform workflow for creating and customizing accounts while preserving compliance.

Deployment requires a non-root AWS user with AdministratorAccess and Terraform v0.15+ locally. Configuration is driven through input variables for VPC sizing, feature flags, framework sourcing, and account customization repositories. The module internally composes multiple sub-modules for account provisioning, account request, backend, code repositories, customizations, feature options, IAM roles, Lambda layer, SSM parameters, and packaging.

Operational best practices include preserving Terraform state, optionally moving state to S3 and DynamoDB backend, and protecting sensitive values stored in state. Cleanup follows a deliberate sequence of pipeline deletion, bucket removal via remove_buckets.sh, account decommissioning in Control Tower Service Catalog, and final terraform destroy.

When used as designed, AFT reduces manual ClickOps, enforces consistent security baselines, and aligns multi-account provisioning with the Well-Architected Framework.

Sources

  1. HashiCorp Terraform Tutorials AWS Control Tower AFT
  2. GitHub aws-ia terraform-aws-controltoweraccount_factory
  3. AWS Control Tower AFT Getting Started User Guide
  4. HashiCorp Using Terraform with AWS Control Tower via AFT

Related Posts