AWS Control Tower Guide
Build landing zones with Control Tower: guardrails, Account Factory, customizations, and governance at scale.
Prerequisites
- Understanding of AWS Organizations and SCPs
- AWS account with management account access
What Is AWS Control Tower?
AWS Control Tower is a managed service that automates the setup and governance of a secure, multi-account AWS environment based on AWS best practices. It builds on top of AWS Organizations, AWS IAM Identity Center, AWS CloudTrail, AWS Config, and AWS Service Catalog to provide a pre-configured landing zone with guardrails, account provisioning, and centralized logging out of the box.
Without Control Tower, setting up a well-architected multi-account environment requires manually configuring Organizations, creating SCPs, setting up centralized logging, provisioning accounts, and enforcing baseline security controls. Control Tower automates all of this and provides a dashboard to monitor compliance across your entire organization.
This guide covers the landing zone architecture, guardrail types and selection, Account Factory for provisioning, customizations with the Customizations for Control Tower (CfCT) solution, and operational best practices for managing a Control Tower environment.
No Additional Cost
Control Tower itself is free. You pay only for the underlying AWS services it configures: AWS Config rules, CloudTrail, S3 storage for logs, and any resources created by guardrails. The primary cost driver is AWS Config, which charges per rule evaluation per region. Plan for approximately $2-5 per account per region per month for Config rule evaluations.
Landing Zone Architecture
When you set up Control Tower, it creates a landing zone: a well-architected multi-account baseline. The landing zone includes a root organization with organizational units (OUs), shared accounts for logging and auditing, and a set of preventive and detective guardrails applied to all accounts.
Default Account Structure
| Account | Purpose | OU |
|---|---|---|
| Management Account | Organization root, billing, Control Tower management | Root |
| Log Archive Account | Centralized CloudTrail and Config logs | Security OU |
| Audit Account | Security team access, cross-account audit roles | Security OU |
Recommended OU Structure
# Control Tower creates these OUs by default:
# Root
# ├── Security OU (Log Archive + Audit accounts)
# └── Sandbox OU (optional)
# Recommended additional OUs for production:
# Root
# ├── Security OU
# │ ├── Log Archive Account
# │ └── Audit Account
# ├── Infrastructure OU
# │ ├── Network Account (Transit Gateway, DNS)
# │ └── Shared Services Account (CI/CD, artifacts)
# ├── Workloads OU
# │ ├── Prod OU
# │ │ ├── App-A-Prod Account
# │ │ └── App-B-Prod Account
# │ └── Non-Prod OU
# │ ├── App-A-Dev Account
# │ └── App-B-Dev Account
# ├── Policy Staging OU (test guardrails here first)
# └── Sandbox OU (developer experimentation)
# Create additional OUs via AWS CLI
aws organizations create-organizational-unit \
--parent-id r-abc1 \
--name "Infrastructure"
aws organizations create-organizational-unit \
--parent-id r-abc1 \
--name "Workloads"Register Existing OUs
If you have an existing AWS Organizations structure, you can register existing OUs with Control Tower. This extends Control Tower governance (guardrails, account baseline) to accounts that were created before Control Tower was set up. Go to the Control Tower console, select "Organization", and register each OU.
Guardrails: Preventive and Detective
Guardrails are pre-packaged governance rules that enforce policies across your landing zone. Control Tower provides three types of guardrails:
Preventive guardrails are implemented as Service Control Policies (SCPs) that prevent actions before they occur. For example, a preventive guardrail can block the creation of IAM access keys for the root user.
Detective guardrails are implemented as AWS Config rules that detect non-compliant resources after they are created. For example, a detective guardrail can identify S3 buckets without encryption.
Proactive guardrails are implemented as CloudFormation hooks that check resource configurations before CloudFormation creates them.
Key Guardrails by Category
| Guardrail | Type | Behavior |
|---|---|---|
| Disallow root user access keys | Preventive (mandatory) | Blocks creation of root access keys |
| Enable CloudTrail in all regions | Detective (mandatory) | Alerts if CloudTrail is disabled |
| Disallow public S3 buckets | Preventive (strongly recommended) | Blocks S3 public access settings |
| Require MFA for root user | Detective (strongly recommended) | Detects root accounts without MFA |
| Disallow internet-facing RDS | Preventive (elective) | Blocks publicly accessible RDS instances |
| Require encryption at rest for EBS | Detective (elective) | Detects unencrypted EBS volumes |
# List all available guardrails (controls)
aws controltower list-enabled-controls \
--target-identifier "arn:aws:organizations::123456789012:ou/o-abc123/ou-abc1-def23456"
# Enable a guardrail on an OU
aws controltower enable-control \
--control-identifier "arn:aws:controltower:us-east-1::control/AWS-GR_ENCRYPTED_VOLUMES" \
--target-identifier "arn:aws:organizations::123456789012:ou/o-abc123/ou-abc1-def23456"
# Disable a guardrail
aws controltower disable-control \
--control-identifier "arn:aws:controltower:us-east-1::control/AWS-GR_ENCRYPTED_VOLUMES" \
--target-identifier "arn:aws:organizations::123456789012:ou/o-abc123/ou-abc1-def23456"
# Check guardrail compliance status
aws controltower list-enabled-controls \
--target-identifier "arn:aws:organizations::123456789012:ou/o-abc123/ou-abc1-def23456" \
--query 'EnabledControls[].{Control:ControlIdentifier, Status:StatusSummary.Status}'Test Guardrails Before Production
Always test new guardrails in a Policy Staging OU before applying them to production OUs. Preventive guardrails (SCPs) can break existing workloads if they rely on actions that the guardrail blocks. Detective guardrails are less risky since they only report non-compliance, but they still generate Config rule evaluations that cost money.
Account Factory
Account Factory is Control Tower's mechanism for provisioning new AWS accounts with a standardized baseline. When you create an account through Account Factory, Control Tower automatically configures CloudTrail, AWS Config, IAM Identity Center access, and applies all guardrails from the target OU. You can provision accounts through the console, Service Catalog, or the Control Tower API.
# Create a new account via Control Tower API
aws controltower create-managed-account \
--account-name "app-team-prod" \
--account-email "app-team-prod@company.com" \
--organizational-unit-id "ou-abc1-def23456"
# Or provision via Service Catalog (Account Factory product)
PRODUCT_ID=$(aws servicecatalog search-products \
--filters '{"FullTextSearch": ["AWS Control Tower Account Factory"]}' \
--query 'ProductViewSummaries[0].ProductId' --output text)
aws servicecatalog provision-product \
--product-id "$PRODUCT_ID" \
--provisioned-product-name "app-team-prod" \
--provisioning-parameters \
Key=AccountName,Value="App Team Prod" \
Key=AccountEmail,Value="app-team-prod@company.com" \
Key=SSOUserEmail,Value="admin@company.com" \
Key=SSOUserFirstName,Value="Admin" \
Key=SSOUserLastName,Value="User" \
Key=ManagedOrganizationalUnit,Value="Workloads/Prod"Account Factory for Terraform (AFT)
# Account Factory for Terraform (AFT) - account request
# File: aft-account-request/terraform/main.tf
module "aft_account_request" {
source = "github.com/aws-ia/terraform-aws-control_tower_account_factory//modules/aft-account-request"
control_tower_parameters = {
AccountEmail = "workload-prod@company.com"
AccountName = "workload-prod"
ManagedOrganizationalUnit = "Workloads/Prod"
SSOUserEmail = "admin@company.com"
SSOUserFirstName = "Admin"
SSOUserLastName = "User"
}
account_tags = {
Environment = "production"
CostCenter = "engineering"
Team = "platform"
}
account_customizations_name = "production-baseline"
change_management_parameters = {
change_requested_by = "Platform Team"
change_reason = "New production workload account"
}
}Customizations for Control Tower (CfCT)
The Customizations for Control Tower (CfCT) solution extends Control Tower by deploying additional resources and configurations to accounts automatically. CfCT uses a CodePipeline that triggers when you push changes to a CodeCommit repository. It deploys CloudFormation StackSets to apply custom configurations like VPC baselines, security tools, and compliance agents to all accounts in specified OUs.
# CfCT manifest.yaml example
---
region: us-east-1
version: 2021-03-15
resources:
# Deploy a VPC baseline to all production accounts
- name: vpc-baseline
description: "Standard VPC with private subnets and VPN"
resource_file: templates/vpc-baseline.yaml
deploy_method: stack_set
deployment_targets:
organizational_units:
- Workloads/Prod
parameters:
- parameter_key: VPCCidr
parameter_value: "10.0.0.0/16"
- parameter_key: EnableFlowLogs
parameter_value: "true"
regions:
- us-east-1
- us-west-2
# Deploy GuardDuty to all accounts
- name: guardduty-baseline
resource_file: templates/guardduty-enable.yaml
deploy_method: stack_set
deployment_targets:
organizational_units:
- Security
- Infrastructure
- Workloads
# Apply additional SCPs
- name: deny-regions-scp
resource_file: policies/deny-unused-regions.json
deploy_method: scp
deployment_targets:
organizational_units:
- WorkloadsCentralized Logging and Auditing
Control Tower automatically configures centralized logging in the Log Archive account. CloudTrail logs from all accounts are stored in a centralized S3 bucket with server-side encryption, and AWS Config snapshots are stored in a separate bucket. The Audit account has cross-account roles that security teams can assume to investigate findings.
# List CloudTrail logs in the Log Archive account
aws s3 ls s3://aws-controltower-logs-123456789012-us-east-1/ \
--recursive --summarize | tail -5
# Query CloudTrail logs with Athena
# First, create the Athena table (run once):
# CREATE EXTERNAL TABLE cloudtrail_logs (
# eventVersion STRING,
# eventTime STRING,
# eventSource STRING,
# eventName STRING,
# awsRegion STRING,
# sourceIPAddress STRING,
# userIdentity STRUCT<...>,
# ...
# )
# PARTITIONED BY (account STRING, region STRING, year STRING, month STRING, day STRING)
# ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
# LOCATION 's3://aws-controltower-logs-123456789012-us-east-1/AWSLogs/o-abc123/'
# Query for root user activity across all accounts
# SELECT eventtime, eventname, recipientaccountid, sourceipaddress
# FROM cloudtrail_logs
# WHERE useridentity.type = 'Root'
# AND year = '2026' AND month = '03'
# ORDER BY eventtime DESC
# LIMIT 50;
# Check Config compliance across accounts
aws configservice describe-compliance-by-config-rule \
--config-rule-names "AWSControlTower_AWS-GR_ENCRYPTED_VOLUMES" \
--query 'ComplianceByConfigRules[].{Rule:ConfigRuleName,Compliance:Compliance.ComplianceType}'Drift Detection and Remediation
Landing zone drift occurs when someone modifies Control Tower-managed resources outside of Control Tower. This can include deleting Config rules, modifying SCPs, changing CloudTrail settings, or altering IAM roles that Control Tower relies on. Control Tower detects drift and displays it on the dashboard.
# Check for landing zone drift
aws controltower list-landing-zones \
--query 'LandingZones[].{Identifier:LandingZoneIdentifier, Status:Status, DriftStatus:DriftStatus}'
# Common drift scenarios and fixes:
# 1. Deleted Config rule -> Re-register the OU or re-enable the guardrail
# 2. Modified SCP -> Update the SCP to match the expected configuration
# 3. Deleted CloudTrail -> Re-register the affected account
# 4. Modified Control Tower roles -> Reset the landing zone
# Re-register an OU to fix drift
aws controltower update-enabled-control \
--control-identifier "arn:aws:controltower:us-east-1::control/AWS-GR_AUDIT_BUCKET_POLICY_CHANGES_PROHIBITED" \
--target-identifier "arn:aws:organizations::123456789012:ou/o-abc123/ou-abc1-def23456" \
--parameters '[]'
# Update the landing zone version (when new version available)
aws controltower update-landing-zone \
--landing-zone-identifier "arn:aws:controltower:us-east-1:123456789012:landingzone/abc123" \
--version "3.3"Best Practices for Control Tower Operations
Operating a Control Tower landing zone effectively requires attention to several operational areas beyond the initial setup.
Operational Checklist
| Area | Best Practice | Frequency |
|---|---|---|
| Landing zone updates | Apply new landing zone versions promptly | When available (quarterly) |
| Drift detection | Monitor and resolve drift immediately | Daily (automated alerts) |
| Guardrail review | Evaluate and enable new guardrails | Monthly |
| Account cleanup | Close unused accounts to reduce costs | Quarterly |
| Config rule costs | Monitor Config evaluations per region | Monthly (billing review) |
| SSO permissions | Review and audit permission set assignments | Quarterly |
Control Tower vs Manual Organizations
Use Control Tower when you want a prescriptive, automated multi-account setup with minimal custom configuration. Use manual Organizations with custom SCPs when you need fine-grained control over every aspect of your multi-account architecture or when Control Tower's guardrails are too restrictive for your use case. Many organizations start with Control Tower and customize with CfCT or AFT as they mature.
Key Takeaways
- 1Control Tower automates multi-account landing zone setup with centralized logging and guardrails.
- 2Guardrails are preventive (SCPs), detective (Config rules), or proactive (CloudFormation hooks).
- 3Account Factory provisions pre-configured accounts with consistent baselines.
- 4Customizations for Control Tower (CfCT) and AFT extend the landing zone with additional resources.
Frequently Asked Questions
Is Control Tower free?
Can I use Control Tower with existing Organizations?
Written by CloudToolStack Team
Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.
Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.