Open-source project
aws-ia/terraform-aws-control_tower_account_factory avatar
aws-ia/terraform-aws-control_tower_account_factory

AWS Control Tower Account Factory for Terraform runs account requests as GitOps

AWS Control Tower Account Factory

823 stars599 forksHCLApache-2.0

At a glance

What is it?
AFT is the AWS-maintained Terraform module that turns Control Tower account requests into pipeline-driven provisioning. It needs a landing zone, a separate management account, administrator credentials and a state backend you provide yourself, and it is still on a 1.x version line.
Who is it for?
AWS landing zone teams that provision accounts repeatedly and already have pipelines for Terraform should adopt AFT, because it moves account requests into a versioned, auditable workflow instead of a Service Catalog form. It is the wrong choice for a single account, for an organisation without AWS Control Tower, and for teams without the operational capacity to own a separate AFT management account and a protected state file.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 36 days ago.
What is it written in?
Mainly HCL, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Account requests as versioned Terraform files

AWS Control Tower Account Factory for Terraform, abbreviated AFT throughout the documentation, follows a GitOps model to automate account provisioning and account updating in Control Tower.

The mechanism is deliberately narrow. You create an account request as a Terraform file. That file carries the inputs for a new account, and its presence is what triggers the AFT workflow that provisions the account. The account request is therefore a reviewed, versioned artefact in a repository rather than a form filled in a console.

That shape only pays off at a certain volume. For a team that creates a handful of accounts a year, AFT adds a management account, a pipeline and a set of IAM roles to do what a single Service Catalog provisioning action does. For a platform team creating accounts continuously across many organizational units, the GitOps model is the point: the request is reviewable, repeatable and auditable, and updating an account becomes a change to a file.

The audience is administrators of AWS Control Tower environments. The README is written for that person and says so: it is intended for administrators of AWS Control Tower environments who wish to set up AFT in their environment, and it describes setting up an AFT environment with a new, dedicated AFT management account.

The project is published by the AWS infrastructure automation organisation under the Apache-2.0 licence, and the topic metadata marks it as a service-team-owned repository that does not accept pull requests, which tells you where changes come from.

Five deployment steps, and the first three are all AWS-side

The README lays out five steps, and it is worth noticing that the first three happen before any Terraform runs.

Step one is launching the AWS Control Tower landing zone. AFT cannot be launched before you have a working landing zone, and the deployment is done from the Control Tower management account.

Step two is creating an organizational unit for AFT. The recommendation is a separate OU in your AWS Organization, created through the Control Tower management account, and it is where the AFT management account will live. Creating the OU through the landing zone rather than by hand keeps your guardrails consistent.

Step three is provisioning the AFT management account. AFT requires a separate AWS account to manage and orchestrate its own requests, and you provision it from the Control Tower management account associated with your landing zone. The naming matters operationally: when specifying the OU, select the one from step two, and when specifying a name, use AFT-Management. The README warns that it can take up to 30 minutes for the account to be fully provisioned, and tells you to validate that you have access to it before going further.

Step four is checking that your Terraform environment is ready, and it assumes you already have procedures in place for running Terraform. AFT supports Terraform version 0.15.x or later.

Step five is calling the AFT module to deploy the factory. The module is vended by Control Tower through the management account, and it establishes all the infrastructure needed to orchestrate your account factory requests. The README sends you to the module's own README for its inputs, and notes that if you already have pipelines for managing Terraform you can integrate the module into that workflow, otherwise you run it from any environment with the right credentials.

AdministratorAccess credentials and the sixty minute STS timeout

The module call carries two requirements that decide whether your deployment succeeds, and both are stated as non-negotiable in the README.

First, the Account Factory for Terraform module must be called while you are authenticated with AdministratorAccess credentials in your AWS Control Tower management account. There is no lesser permission described for the bootstrap call.

Second, there is a timeout, and it is a real failure mode. The README states that deploying AFT through the Terraform module requires several minutes, that an initial deployment may require up to 30 minutes, and that as a best practice you should use AWS Security Token Service credentials with a timeout sufficient for a full deployment, because a timeout causes the deployment to fail. The stated minimum for STS credentials is 60 minutes or more. The alternative offered is using any IAM user that has AdministratorAccess permissions in the Control Tower management account.

So the failure mode is specific: an STS session that expires halfway through a 30 minute apply leaves infrastructure in a half-built state and the module reports failure. This is the kind of detail that only shows up in the first run, and it is why the recommendation to size the session for the whole deployment matters.

For teams that already run Terraform through HCP Terraform or Terraform Enterprise, the integration path is the terraform_oidc_integration setting, which switches AFT over to OIDC-based authentication instead of static keys.

AFT does not manage state, and state holds the sensitive values

The single most important operational line in the README is the note about Terraform state, and it deserves to be read twice.

The AFT Terraform module does not manage a backend Terraform state. You either preserve the state file that is generated after applying the module, or you set up a Terraform backend using Amazon S3 and DynamoDB. There is no default, and there is no warning at apply time.

The second note explains why this matters. Certain input variables may contain sensitive values, such as a private ssh key or a Terraform token. Depending on your deployment method those values may be viewable as plain text in the Terraform state file, and the README states plainly that it is your responsibility to protect that state file because it may contain sensitive data.

Read together, the two notes define a specific obligation. If you let the module write a local state file and then lose the machine or the workspace that holds it, you have lost the state of your account factory, and you have possibly left private keys and tokens sitting in plain text on disk. Setting up the S3 and DynamoDB backend before the first apply is the difference between a recoverable factory and an orphaned one.

The README also points at the Terraform documentation for more detail on protecting state, which is the right place to look for the mechanics of encryption, locking and access control.

The OIDC trust policy allows any workspace in the project

The security considerations section is the most detailed part of the README, and it deals with the HCP Terraform and Terraform Enterprise OIDC integration.

When the OIDC integration is enabled, AFT configures an IAM role named AWSAFTAdmin with a trust policy that allows any workspace within your configured TFC or TFE organization and project to assume the role via OIDC. The trust policy scopes the sub claim condition to your organization, project and audience, but uses a wildcard for the workspace name, workspace:*.

The README then sets out the existing mitigations and the customer responsibility. The mitigation is that the policy is scoped to a specific organization, project and audience, so only workspaces inside the configured project can obtain credentials, and that the role itself is narrow:

text
- The `AWSAFTAdmin` role is limited to `sts:AssumeRole` permissions only (to assume `AWSAFTExecution` and `AWSAFTService` roles). It has no direct permissions to access or modify AWS resources.

The customer responsibility is workspace governance. The README states that any workspace created within the project named by terraform_project_name can assume the AWSAFTAdmin role via OIDC, and instructs you to restrict who can create new workspaces inside that project, referring to TFC and TFE team permissions.

This is the sharpest edge in the whole design. The security boundary is not the IAM policy but your workspace creation rights. A developer who can spin up a workspace in the right project can obtain credentials for a role that orchestrates account creation, and no setting in AFT narrows that beyond the project.

Operational metrics, the example matrix, and the boundaries of AFT

Since version 1.6.0, AFT collects anonymous operational metrics, and the README points at AWS documentation for the details including how to disable the capability.

The examples directory is the most useful part of the repository for orientation. It carries one example per source control arrangement: azuredevops+tf_cloud, bitbucket+tf_enterprise, codecommit+tf_oss, github+tf_oss, githubenterprise+tf_cloud, gitlab+tf_oss, gitlabselfmanaged+tf_cloud, multiple-account-customizations and multiple-regions-customization. The naming convention tells you that the differences that matter are the version control platform and the Terraform execution model, cloud or self-managed, plus the multi-account and multi-region variations.

Those examples also mark the limits of the project. AFT assumes AWS Control Tower already exists, that a Service Catalog provisioning path is available for the management account, and that the account request workflow is the unit of work. It is not a landing zone, not a general account management tool, and not a way to provision accounts into an organization without Control Tower.

There is also a cost consideration that is easy to overlook: an entire AWS account, permanently, exists solely to orchestrate requests. The README is explicit that AFT requires a separate AWS account to manage and orchestrate its own requests, and it recommends isolating that account in its own organizational unit. For an organisation that provisions a few accounts a year, that fixed overhead is usually the wrong trade.

Release cadence, licence and the limits of a service-owned repository

The version history shows steady work. Releases 1.21.0 on 2026-07-15, 1.21.1 on 2026-07-16 and 1.22.0 on 2026-09-17 put the project on a 1.x line with patch releases in between. The repository is not archived and the last push was on 2026-09-17, the same day as the 1.22.0 tag, so the source and the release are aligned.

The licence is Apache-2.0, with LICENSE and NOTICE files at the root. For a module that runs inside your own Terraform pipeline with your own credentials, Apache-2.0 is a permissive fit, and the NOTICE obligations apply to redistribution rather than to internal use.

The repository layout is what you would expect from a Terraform module collection. main.tf, variables.tf, outputs.tf, locals.tf, providers.tf, versions.tf and data.tf sit at the root, with modules, sources and src directories for the internal pieces, plus examples and a src tree for the supporting tooling. The VERSION file, the PYTHON_VERSION file, a CODEOWNERS file and SECURITY.md are all present, and CONTRIBUTING.md and CODE_OF_CONDUCT.md cover how changes get proposed.

One governance fact changes how you plan upgrades. The topic metadata marks this repository as service-team-owned and states that it does not accept pull requests. There is no upstream merge path for your fix, so your options are to raise an issue against a service-owned repository or to fork and carry the divergence yourself. That is a routine consideration for AWS-managed infrastructure repositories, but it belongs in the decision rather than the fine print.

Editorial conclusion

AWS landing zone teams that provision accounts repeatedly and already have pipelines for Terraform should adopt AFT, because it moves account requests into a versioned, auditable workflow instead of a Service Catalog form. It is the wrong choice for a single account, for an organisation without AWS Control Tower, and for teams without the operational capacity to own a separate AFT management account and a protected state file. Before deploying, set up the backend in Amazon S3 with DynamoDB first, since the module does not manage state, and read the OIDC trust policy section, because the workspace name is matched with a wildcard when the HCP Terraform integration is enabled.

Frequently asked questions

What prerequisites does AWS Control Tower Account Factory for Terraform need?

You need a working AWS Control Tower landing zone, a separate organizational unit for AFT, and a dedicated AFT management account named AFT-Management that can take up to 30 minutes to provision. The module call itself must run with AdministratorAccess credentials in the Control Tower management account.

Does the AFT Terraform module manage state?

No. The README states that the AFT Terraform module does not manage a backend Terraform state, so you must preserve the generated state file or set up a backend using Amazon S3 and DynamoDB. That matters because input variables such as a private ssh key or a Terraform token can appear as plain text in the state.

What is the security risk of the HCP Terraform OIDC integration?

When terraform_oidc_integration is enabled, the AWSAFTAdmin role trust policy allows any workspace in your configured TFC or TFE organization and project to assume it, using a wildcard for the workspace name. The role itself is limited to sts:AssumeRole, so the README places responsibility for restricting workspace creation on you.

Which Terraform version does AFT support?

AFT supports Terraform version 0.15.x or later. The README also notes that deploying the module requires several minutes, up to 30 minutes for an initial deployment, so STS credentials need a timeout of at least 60 minutes or a timeout will fail the deployment.

Official sources

  1. aws-ia/terraform-aws-control_tower_account_factory on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/aws-ia-terraform-aws-control-tower-account-factory.svg)](https://hysenlabs.com/projects/aws-ia-terraform-aws-control-tower-account-factory)

Was this useful?