Skip to main content
AWSArchitectureadvanced

AWS Control Tower Guide

Build landing zones with Control Tower: guardrails, Account Factory, customizations, and governance at scale.

CloudToolStack Team25 min readPublished Mar 14, 2026

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

AccountPurposeOU
Management AccountOrganization root, billing, Control Tower managementRoot
Log Archive AccountCentralized CloudTrail and Config logsSecurity OU
Audit AccountSecurity team access, cross-account audit rolesSecurity OU

Recommended OU Structure

bash
# 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

GuardrailTypeBehavior
Disallow root user access keysPreventive (mandatory)Blocks creation of root access keys
Enable CloudTrail in all regionsDetective (mandatory)Alerts if CloudTrail is disabled
Disallow public S3 bucketsPreventive (strongly recommended)Blocks S3 public access settings
Require MFA for root userDetective (strongly recommended)Detects root accounts without MFA
Disallow internet-facing RDSPreventive (elective)Blocks publicly accessible RDS instances
Require encryption at rest for EBSDetective (elective)Detects unencrypted EBS volumes
bash
# 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.

bash
# 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)

hcl
# 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.

yaml
# 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:
        - Workloads

Centralized 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.

bash
# 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.

bash
# 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

AreaBest PracticeFrequency
Landing zone updatesApply new landing zone versions promptlyWhen available (quarterly)
Drift detectionMonitor and resolve drift immediatelyDaily (automated alerts)
Guardrail reviewEvaluate and enable new guardrailsMonthly
Account cleanupClose unused accounts to reduce costsQuarterly
Config rule costsMonitor Config evaluations per regionMonthly (billing review)
SSO permissionsReview and audit permission set assignmentsQuarterly

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.

AWS Organizations & SCPs GuideIAM Best Practices: Securing Your AWS Account

Key Takeaways

  1. 1Control Tower automates multi-account landing zone setup with centralized logging and guardrails.
  2. 2Guardrails are preventive (SCPs), detective (Config rules), or proactive (CloudFormation hooks).
  3. 3Account Factory provisions pre-configured accounts with consistent baselines.
  4. 4Customizations for Control Tower (CfCT) and AFT extend the landing zone with additional resources.

Frequently Asked Questions

Is Control Tower free?
Control Tower itself is free. You pay for underlying services: AWS Config rules (primary cost driver at ~$2-5 per account per region per month), CloudTrail, and S3 storage for logs. The governance benefits typically justify these costs.
Can I use Control Tower with existing Organizations?
Yes. You can register existing OUs with Control Tower, extending governance to accounts created before Control Tower. This applies guardrails and account baselines to existing accounts without disrupting running workloads.

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.