Skip to main content

Account factory (AFT)

Account Factory for Terraform turns account creation from a manual checklist into a reviewed pull request. The account arrives with identity, logging, guardrails and the organisation's customisations already applied.

Why it exists​

Creating accounts by hand produces accounts that differ. One has CloudTrail, one does not; one has the standard IAM roles, one has a variant; one has tags, one was created at 2 a.m. AFT makes the baseline a property of the account's creation, not of someone's memory.

How it works​

account request (pull request)
│
▼
AFT pipeline ──► Control Tower Account Factory
│ │
│ ▼
│ new account in target OU
│ │
▼ ▼
global customisations ─► account customisations
(all accounts) (by OU / account)

Four repositories define the behaviour:

RepositoryPurpose
aft-account-requestThe requested accounts — one entry per account, reviewed like code
aft-global-customizationsApplied to every account: baseline roles, Config, tags, logging
aft-account-customizationsApplied by OU or by account: network, service quotas, specific roles
aft-account-provisioning-customizationsRuns during provisioning, before the account is handed over

Account request​

Each account is a Terraform resource in the request repository:

module "prod_payments" {
source = "./modules/aft-account-request"

control_tower_parameters = {
AccountEmail = "aws-prod-payments@example.com"
AccountName = "prod-payments"
ManagedOrganizationalUnit = "Workloads-Prod"
SSOUserEmail = "platform-owner@example.com"
SSOUserFirstName = "Platform"
SSOUserLastName = "Owner"
}

account_tags = {
Environment = "prod"
Project = "payments"
Owner = "payments-team"
CostCenter = "cc-1042"
DataClassification = "confidential"
}

change_management_parameters = {
change_requested_by = "platform-team"
change_reason = "New payment service workload"
}

account_customizations_name = "payments"
}

What global customisations apply​

  • Standard IAM roles for pipeline access, with OIDC trust to the CI provider.
  • The Terraform state lock table in us-east-1.
  • Config recorder and delivery to the log archive account.
  • CloudTrail organisation trail enrolment.
  • Default EBS encryption.
  • Baseline tags.
  • GuardDuty membership in the delegated administrator account.
  • Service quota increases required by the workload profile.

What provisioning customisations apply​

  • VPC and subnet layout for the environment.
  • Transit Gateway attachment and route table entries.
  • DNS delegation.
  • Initial service-linked roles.

Controls on the process​

Review
An account request is a pull request. Two reviewers, at least one from platform, approve before the pipeline runs.
Unique root email
Each account uses a distinct root email address. Reuse causes provisioning failure and is a security problem.
OU placement
The OU determines the guardrail profile. A production account is never created in a non-production OU.
Verification
Provisioning ends with a compliance check. An account that fails the check is not released to the workload team.
Audit
Every account has a recorded requester, reason and approval trail in version control.

Common problems​

ProblemCauseResponse
Account provisioning failsRoot email already used, or OU not enrolledUse an unused alias; confirm the OU exists and is enrolled in Control Tower
Customisation did not applyAccount request applied before the customisation repository was updatedRe-run the customisation pipeline for the account
Account cannot assume baseline rolesTrust policy or permission set mismatchCorrect through the customisation repository; never patch the role in the console
Drift after handoverManual changes in the accountDetect with Config, revert via pipeline, investigate access