Skip to main content

The Rhythmic Blog

Control Tower & AFT Turn AWS Account Chaos into Infrastructure as Code

April 11, 2025       Steven Black               Comments  0

AWS Account Factory for Terraform (AFT) is a game-changer for businesses managing multiple AWS accounts. It optimizes the creation, management, and removal of AWS accounts through Terraform, meeting the growing need for standardized processes in multi-account environments. AFT automates account lifecycle management, enabling users to request fully configured accounts with minimal code.

The implementation involves three key steps: setting up a Control Tower landing zone, configuring AFT repositories, and deploying the AFT root module to provision resources efficiently. By maintaining configuration consistency and preventing resource sprawl, AFT offers organizations of all sizes the benefits of efficient AWS account management.

Let’s walk through what AWS Control Tower is, how it works with AFT, and why you’d want to use this powerful combination.

What is AWS Control Tower?

Our introduction covers what Control Tower’s function is but what is it made out of? And how does AFT fit into all this?

AWS Control Tower vs. AFT

AWS Control Tower is an AWS service that provides best-practices for a multi-account cloud environment. Part of that solution is an Account Factory. Control Tower comes with an Account Factory but they also provide AFT to users who are interested in using Terraform to manage their accounts.

Core Components of AWS Control Tower & AFT

Control Tower is, at present, set up through the AWS console. The AFT portion is written in terraform which deploys several AWS services including DynamoDB, AWS SQS, Lambdas, CodeBuild, CodePipeline, and State Machines. These perform the automations which create and customize the AWS accounts requested through AFT.

Control Tower

Exploring AWS Control Tower’s Architecture & GitHub Resources

The whole solution is open sourced on GitHub so you can pry through all the individual resources if you’re so curious. For a visual overview check out their provisioning workflow diagram.

How to Implement AWS Control Tower and AFT

The details of how to best implement AWS Control Tower and AFT are going to depend on the use-case. We’ll explain this at a high-level so that anyone familiar with AWS can grok it. AWS provides more in-depth documentation. Basically it consists of four steps, including provisioning your first accounts:

  1. Create a Control Tower landing zone
  2. Create / modify the AFT repos (AFT uses four repos to request and customize accounts)
  3. Launch AFT
  4. Profit

1. Create a Control Tower landing zone

Creating a landing zone is super simple when done through the console. This is a one-time task when setting up AFT and the console walks you through it. The only gotcha I ran into was that AWS Config needed to be disabled because Control Tower takes control (haha) of that service going forward.

So far all the instances of Control Tower we’ve deployed are into existing AWS Organizations with existing separation of concerns. For the most use-cases the AWS recommendations are good so don’t be afraid to click through and accept all the defaults.

AWS recently released APIs to create Landing Zones and they have documentation for doing this with the CLI. For most organizations creating the Control Tower Landing Zone is a one-time operation so there is low ROI from automating this process.

2. Create / modify the AFT repos

Creating the AFT repos is a little more involved, a lot more technical, and not strictly necessary because AFT will create these repos in CodeCommit if you don’t create them yourself. We created them along with most of our other code, on GitHub. AFT uses four repos stored in the same repo as the main module. These are for:

  1. aft-account-request Requesting new accounts.
  2. aft-account-provisioning-customizations
  3. aft-global-customizations
  4. aft-account-customizations creating account-specific resources.

  1. The requests account can be created and then ignored until you want to start using your “account vending machine”. Commits here trigger the AFT process to provision new accounts.
  2. The second one runs against the AFT management account and by default just creates some roles for the AWS State Machine that makes sure the accounts are maintaining configuration.
  3. The last two get applied in CodeBuild back-to-back. The first gets applied to every repo, hence it is “global”
  4. The last repository applies a particular directory, allowing you to create terraform to define different account types. Which directory depends on the value of account_customizations_name. In our case we set it to workload which corresponds to a directory that contains terraform code to spin up the desired VPC configuration for a workload account.

You may be asking, as I did, “How does AWS get access to our private repos in GitHub?” Setting up the GitHub to AWS connection involves creating an “AWS CodeConnections” which is on the developer tools (the same console as CodeCommit) console under settings. It gets created in the next step when we launch AFT.

Launch AFT

The AFT root module will deploy all the resources necessary to set up the AFT app. Just apply it to the Account Factory account which was created during the Control Tower setup. The best high-level explanation of the machinations underlying this application is the diagram on the AFT Architecture page. We created a bespoke repository to maintain the AFT configuration but given that the aft-account-provisioning-customizations repo runs against the same account I wonder if you could get away with applying out of that repo and then migrating state to the correct place after the initial apply to prevent the resources from getting duplicated. That’s a little meta and more a curiosity than something useful.

module "control_tower_account_factory" {
  source  = "aws-ia/control_tower_account_factory/aws"
  version = "1.11.1"
  # Configuration Vars
  aft_feature_delete_default_vpcs_enabled = true
  aft_metrics_reporting                   = false
  aft_vpc_endpoints                       = false
  cloudwatch_log_group_retention          = 365
  ct_home_region                          = "us-east-1"
  # VCS Config
  account_customizations_repo_branch              = "master"
  account_customizations_repo_name                = "rhythmictech/rhythmictech-aft-account-customizations"
  account_provisioning_customizations_repo_branch = "master"
  account_provisioning_customizations_repo_name   = "rhythmictech/rhythmictech-aft-account-provisioning-customizations"
  account_request_repo_branch                     = "master"
  account_request_repo_name                       = "rhythmictech/rhythmictech-aft-account-request"
  global_customizations_repo_branch               = "master"
  global_customizations_repo_name                 = "rhythmictech/rhythmictech-aft-global-customizations"
  vcs_provider                                    = "github"
  # Account IDs
  aft_management_account_id = "0123456789"
  audit_account_id          = "9012345678"
  ct_management_account_id  = "8901234567"
  log_archive_account_id    = "7890123456"
}

Why Use AWS Control Tower and AFT for Multi-Account Setup

AWS is recommending customers use a multi-account setup. This isn’t just for the large companies anymore, but for small and medium sized companies that want to use accounts to separate concerns and reduce the risk of security breaches to an infrastructure account. The drawback is this distributed setup can lead to configuration divergence and resource sprawl. AFT standardizes this process so that you can request a fully-formed account with a few lines of code (example below). Then it automates account creation along with maintaining configuration. Having all the resources defined with Infrastructure As Code (IAC) allows systems administrators control. Not only is the IAC itself auditable but Control Tower provides guardrails to prevent undesirable divergence and unwanted resources from being created.

Here’s an example for creating a “data warehouse” account with the aft requests repo:

module "datawarehouse_uat" {
  source = "./modules/aft-account-request"
  account_customizations_name = "workload"
  account_tags = {
    "env"        = "infra"
    "vended"     = "true"
    "managed_by" = "ct-terraform"
  }
  change_management_parameters = {
    change_requested_by = "Nevets Kcalb"
    change_reason       = "creating data warehouse account"
  }
  control_tower_parameters = {
    AccountEmail              = "aws-dwhuat@example.com"
    AccountName               = "aws-example-dwhuat"
    ManagedOrganizationalUnit = "Data Warehouse (ou-gon2-getit)"
    SSOUserEmail              = "tatertotlover@hotmail.com"
    SSOUserFirstName          = "Nevets"
    SSOUserLastName           = "Kcalb"
  }
  custom_fields = {
    environment            = "uat"
    namespace              = "workload"
    tfassume_account_id    = 0123456789
    tfassume_external_id   = "rofljk+lolol"
    vpc_availability_zones = "[\"us-east-1a\", \"us-east-1b\", \"us-east-1c\"]"
    vpc_cidr               = "10.186.160.0/20"
    vpc_public_subnets     = "[\"10.186.160.0/24\", \"10.186.161.0/24\", \"10.186.162.0/24\"]"
    vpc_private_subnets    = "[\"10.186.164.0/23\", \"10.186.166.0/23\", \"10.186.168.0/23\"]"
  }
}

This example was really used to provision an entire AWS account complete with a CloudTrail, SSO, and a VPC attached to a central transit gateway. It’s been slightly modified to protect anonymity.

Alternative to AFT: The Service Catalog Approach

While we’ve focused here on AFT as our recommended implementation method, it’s worth acknowledging that AWS Control Tower offers another approach through its native Service Catalog. The Service Catalog method is often integrated with IT Service Management (ITSM) systems or helpdesks, allowing non-technical staff to create accounts through established request workflows. This can be advantageous in environments with formalized IT processes or where account creation needs to be handled by operations teams rather than developers. However, we generally prefer AFT for its DevOps-oriented approach, infrastructure-as-code capabilities, and better alignment with how modern cloud-native organizations operate. For small and medium businesses (SMBs) without complex ITSM requirements, AFT typically offers a more flexible and automation-friendly solution that scales better with your growing cloud environment.

Real-World Impact

AFT transforms AWS account management from a manual, error-prone process into a streamlined, code-based workflow. Organizations gain operational consistency across accounts while reducing administration overhead. The solution scales efficiently from small business deployments to enterprise environments. As multi-account architectures become standard practice, AFT provides the automation foundation that makes compliance, security, and resource management practical for teams of any size.

Leave a Reply