AWS Control Tower Account Factory for Terraform enables organizations to provision and customize AWS accounts with governance and repeatability. The module automates account creation and post-provisioning customization inside an AWS Control Tower landing zone using Terraform workflows.
AWS Control Tower Account Factory for Terraform is a Terraform module that makes it easy to create and customize new accounts that comply with your 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.
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.
This tutorial assumes that you are familiar with the standard Terraform workflow. If you are new to Terraform, complete the Get Started tutorials first.
Prerequisites and Environment Requirements
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
Prerequisites before you start for a typical AFT account provisioning run are:
- You should have an AWS Control Tower environment deployed and available. Follow the getting started guide if you need to launch AWS Control Tower.
- You should have an AFT deployed on a dedicated AFT Management account. Follow the guide on this post to set up AFT.
- A new root email address for a new vended AWS account that you’ll submit through AFT.
- A new or existing Organizational Units (OU) governed by AWS Control Tower, which is needed as part of new account request parameter in AFT.
- Integrated development environment (IDE) with Git, Terraform, and AWS Command Line Interface (AWS CLI) installed
AFT follows a GitOps model and sets up a Terraform pipeline to provision and customize AWS accounts in AWS Control Tower. You create an account request in Terraform and commit to the repository that triggers the AFT workflow for Account Factory. After Account Factory execution is complete, AFT runs additional customization steps automatically.
| Prerequisite | Description |
|---|---|
| Terraform version | v0.15+ installed locally |
| AWS credentials | Non-root user with AdministratorAccess |
| Control Tower landing zone | Deployed and available |
| AFT Management account | Dedicated account with AFT deployed |
| Account root email | New root email address for vended account |
| Organizational Unit | New or existing OU governed by Control Tower |
| Tooling | IDE with Git, Terraform, AWS CLI |
AFT Architecture and Repositories
AFT uses four separate repositories to manage this entire workflow.
The repositories and their functions are:
- aft-account-request
- handles placing or updating account requests
- aft-account-customizations
- holds account level Terraform customizations
- aft-global-customizations
- applies customizations to all accounts managed by AFT
- aft-account-provisioning-customizations
- state machine for provisioning customizations
AWS Control Tower Account Factory for Terraform follows a GitOps model to automate the processes of account provisioning and account updating in AWS Control Tower. You'll create an account request Terraform file, which provides the necessary input that triggers the AFT workflow for account provisioning.
For more information on AFT, see Overview of AWS Control Tower Account Factory for Terraform
This guide is intended for administrators of AWS Control Tower environments who wish to set up Account Factory for Terraform in their environment. It describes how to set up an Account Factory for Terraform environment with a new, dedicated AFT management account. This guide follows the deployment steps outlined in Deploy AWS Control Tower Account Factory for Terraform.
| Repository | Purpose |
|---|---|
| aft-account-request | Place or update account requests via Terraform |
| aft-account-customizations | Per-account category customizations, e.g., SANDBOX, PRODUCTION |
| aft-global-customizations | Cross-account customizations applied to all managed accounts |
| aft-account-provisioning-customizations | Provisioning customization state machine |
Customers use AWS Control Tower Account Factory to create a new AWS account or enroll existing AWS accounts in their AWS Organizations. Customers launch Account Factory from the AWS Control Tower console or via AWS Service Catalog API. We hear from customers that they want to manage their AWS accounts in the same way that they manage their AWS infrastructure using Terraform. We launched AWS Control Tower Account Factory for Terraform at re:Invent 2021, a new Terraform module to provision and customize AWS accounts using Terraform. In this post, we’ll walk you through the steps to deploy a new AWS account using AFT, and then we’ll show you how to customize the account created via AFT.
Deployment Steps for AFT Environment
Five steps are required to configure and launch your AFT environment.
Step 1: Launch your AWS Control Tower landing zone
Before launching AFT, you must have a working AWS Control Tower landing zone in your AWS account. You will configure and launch AFT from the AWS Control Tower management account.
Step 2: Create a new organizational unit for AFT (recommended)
We recommend that you create a separate OU in your AWS Organization, where you will deploy the AFT management account. Create an OU through your AWS Control Tower management account
Step 3: Deploy AFT module to management account
Step 4: Configure repositories and pipelines
Step 5: Validate pipeline execution
Initializing AFT with Terraform
The value for Account should match your ctmanagementaccount_id input variable.
$ aws sts get-caller-identity
{
"UserId": "AAAA….",
"Account": "CONTROL TOWER MANAGEMENT ACCOUNT ID",
"Arn": "arn:aws:iam::ACCOUNT_ID:user/USER"
}
Initialize the configuration to install the AWS provider and download the AFT module.
$ terraform init
Initializing modules...
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/local from the dependency lock file
- Reusing previous version of hashicorp/archive from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Reusing previous version of hashicorp/time from the dependency lock file
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/random v3.1.0
- Using previously-installed hashicorp/time v0.7.2
- Using previously-installed hashicorp/aws v3.66.0
- Using previously-installed hashicorp/local v2.1.0
- Using previously-installed hashicorp/archive v2.2.0
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory
Account Request Workflow
To create and update the AWS account using AFT, use the aft-account-request Terraform module. Provide the mandatory input, such as account root email address and the OU. Each time that you add or modify the account request, the Terraform file is committed to the repository and will trigger the AFT pipeline.
From the IDE terminal, run the following command to copy the example account customization. Replace the placeholder AWS_REGION value with your Control Tower home region.
Updating to this repository triggers the account request pipeline.
Navigate to CodePipeline and confirm that your ct-aft-account-request pipeline status is Succeeded. It may take a few minutes for the pipeline to complete. So far, we only populate the boilerplate without yet submitting a real account request. In the next section, we’ll submit a new account request.
Provision new account
Now we’ll provision a new AWS account via AFT using the SANDOX customization that we configured earlier.
From your IDE, navigate to the aft-account-request/terraform directory. Create a new file, and give it a name account-requests.tf
Add the following Terraform code and replace the placeholder {{PLACEHOLDER NAME}} with your own value, for example for the account email, name, OU, and SSO
Account Level Customization Options
Open the main.tf file on the aft-account-customizations/SANDBOX/terraform directory. This is a Terraform configuration which sets a monthly budget of $100 on the account that you’re creating with this customization.
Open the api_helpers directory, which is where you add bash/python script to further customize your account.
To add additional account level customization, create a new directory following the same structure. You specify the accountcustomizationname when creating a new account request, and AFT applies all of the Terraform configurations specified in the specific customization directory.
To use custom variables in your Terraform configuration, you pass the customfields value during the account request. These custom fields will be available as the AWS Systems Manager (SSM) Parameter Store in the vended AWS account under path /aft/account-request/custom-fields/{field-name}. In your Terraform configuration, you can retrieve these custom fields using data source. We’ll discuss in depth about customfields in a later section.
We add Terraform customization in the aft-global-customizations repository to apply Amazon S3 Block public access for all accounts managed by AFT. We also add Terraform customization in aft-account-customizations for two categories: PRODUCTION and SANDBOX. For PRODUCTION, we add a custom guardrail using an AWS Config Rule to check if VPC Flow Logs is enabled. In SANDBOX customization, we add Terraform configuration to setup monthly AWS Budget. Inside the account request, we specify whether or not to use PRODUCTION or SANDBOX category for account-level customization.
From the IDE terminal, run the following command
Global Customizations
You can apply customizations to all of the accounts managed by AFT. For example, in this post, we’ll configure Amazon S3 Block Public Access to block public access to every Amazon Simple Storage Service (Amazon S3) bucket in all of the accounts managed by AFT.
After the pipeline has completed successfully, navigate to Step Functions and locate the aft-account-provisioning-customizations state machine.
| Customization Scope | Example |
|---|---|
| Global | S3 Block Public Access for all accounts |
| Account category PRODUCTION | AWS Config Rule for VPC Flow Logs enabled |
| Account category SANDBOX | Monthly AWS Budget of $100 |
Workflow Summary
AFT follows a GitOps model and sets up a Terraform pipeline to provision and customize AWS accounts in AWS Control Tower. You create an account request in Terraform and commit to the repository that triggers the AFT workflow for Account Factory. After Account Factory execution is complete, AFT runs additional customization steps automatically.
The workflow stages are:
- Account request commit triggers CodePipeline ct-aft-account-request
- Account Factory provisions the account in AWS Organizations and Control Tower
- AFT runs account level customizations based on accountcustomizationname
- AFT runs global customizations for all managed accounts
- State machine aft-account-provisioning-customizations tracks completion
Conclusion
AWS Control Tower Account Factory for Terraform provides a repeatable, GitOps driven method to create and customize AWS accounts that comply with organizational security guidelines. Deployment begins with a working Control Tower landing zone and a dedicated AFT management account, followed by creation of a recommended Organizational Unit for AFT isolation. Terraform initialization against the management account establishes provider dependencies and downloads the AFT module maintained by AWS.
Once the pipeline is deployed, account requests are managed through the aft-account-request repository using the AFT Terraform module. Each commit triggers CodePipeline execution and subsequent Account Factory provisioning. Customizations are separated into account level and global repositories, allowing teams to define SANDBOX configurations such as monthly budgets, PRODUCTION guardrails such as VPC Flow Logs checks, and global controls such as S3 Block Public Access. Custom fields passed during the account request are surfaced as SSM Parameter Store values in the vended account, enabling dynamic Terraform data sources.
The architecture requires Terraform v0.15+, AdministratorAccess credentials for a non-root user, a long-lived credential session for steps that may take up to 30 minutes, and an IDE with Git, Terraform, and AWS CLI. With these prerequisites satisfied, AFT delivers consistent, auditable, and automated account creation integrated with AWS Control Tower governance.