Scenario Advanced Aws AWS Governance

Implement AWS Control Tower for a 20-Account Organization

Set up AWS Control Tower with Account Factory, custom guardrails via SCPs, account vending automation with AFT, and developer self-service sandbox accounts.

January 20, 2025 5 min read ~35 min to complete DB
The Situation

Your company has grown from 3 accounts to 20 in the past year, all created manually with inconsistent naming, tagging, and security baselines. The platform team spends 4 hours setting up each new account. Engineers complain they wait 2 weeks for a dev account. You're asked to implement AWS Control Tower to automate account vending and enforce governance without slowing teams down.

6 Steps
6 Services Used
~35 min Duration
Advanced Difficulty

The Problem

Without Control Tower, each new AWS account is a blank canvas. Security baselines drift. CloudTrail might be enabled in one account, disabled in another. IAM roles get created inconsistently. Compliance evidence collection requires manual effort across 20 accounts.

Control Tower provides: a single enrollment process, automated guardrails, and a landing zone that every new account inherits.

Step 1: OU Structure Design

Design your OU hierarchy before enabling Control Tower — reorganizing OUs after enrollment is disruptive:

Root
└── AWS Control Tower (managed by Control Tower)
    ├── Security OU  ← Log Archive + Audit accounts (auto-created)
    │
    ├── Infrastructure OU
    │   ├── Network Account     ← Transit Gateway, DNS
    │   └── Shared Services     ← ECR, artifact repos
    │
    ├── Workloads OU
    │   ├── Production OU       ← Strict SCPs, change control
    │   │   └── prod-app-* accounts
    │   └── Non-Production OU   ← Relaxed SCPs
    │       ├── staging-app-* accounts
    │       └── dev-app-* accounts
    │
    └── Sandbox OU  ← Self-service, auto-expires 30 days
        └── eng-sandbox-* accounts

Guardrail strategy per OU:

OUPreventive GuardrailsDetective Guardrails
All OUsDeny root usage, deny non-compliant regionsCloudTrail enabled, MFA on root
Production OUDeny internet gateway creation without approval, deny direct S3 public accessDetect unencrypted EBS volumes
Sandbox OUBudget alert at $200/monthDetect EC2 without required tags

Step 2: Enable Control Tower

# Control Tower is enabled via the AWS Console only (no CLI/API)
# Navigate to: AWS Console → Control Tower → Set up landing zone

# Pre-requisites:
# 1. Management account must NOT have existing CloudTrail or AWS Config in target regions
# 2. IAM Identity Center must not already be configured
# 3. You need 3 accounts minimum: management, log archive, audit

# After enabling, Control Tower creates:
# - AWSControlTowerAdminRole (assume from management account)
# - AWSControlTowerCloudTrailRole (for centralized CloudTrail)
# - AWSControlTowerConfigAggregatorRole (for centralized Config)
Existing Accounts Warning
Control Tower doesn’t automatically manage accounts created before it was enabled. You must manually enroll existing accounts via Account Factory. Enrolling an existing account may reset some configuration — always test in a non-critical account first.

Step 3: Account Factory for Terraform (AFT)

AFT replaces the manual account setup process with a Git-based workflow. Engineers submit a PR to request a new account; AFT provisions it automatically.

# Deploy AFT (one-time setup in management account)
git clone https://github.com/aws-ia/terraform-aws-control_tower_account_factory
# aft-bootstrap/main.tf
module "aft" {
  source = "github.com/aws-ia/terraform-aws-control_tower_account_factory"
  
  ct_management_account_id    = "123456789012"
  log_archive_account_id      = "234567890123"
  audit_account_id            = "345678901234"
  aft_management_account_id   = "456789012345"
  
  ct_home_region              = "us-east-1"
  tf_backend_secondary_region = "us-west-2"
  
  # Store AFT state in S3
  terraform_s3_bucket_sse_algorithm = "aws:kms"
}

Account request — engineers submit a PR to this repo:

# accounts/prod-app-payments/account-request.tf
module "account_request" {
  source = "github.com/aws-ia/terraform-aws-control_tower_account_factory//modules/aft-account-request"
  
  control_tower_parameters = {
    AccountEmail              = "[email protected]"
    AccountName               = "prod-app-payments"
    ManagedOrganizationalUnit = "Workloads/Production"
    SSOUserEmail              = "[email protected]"
    SSOUserFirstName          = "Alice"
    SSOUserLastName           = "Smith"
  }
  
  account_tags = {
    team        = "payments"
    environment = "production"
    cost-center = "CC-PAYMENTS-001"
    owner       = "[email protected]"
  }
  
  change_management_parameters = {
    change_requested_by = "[email protected]"
    change_reason       = "New payments service — Q2 2025 launch"
  }
}

PR is approved → AFT runs:

  1. Creates the account in AWS Organizations
  2. Enrolls it in Control Tower (applies landing zone baseline)
  3. Runs account customizations (installs GuardDuty, sets budget alerts, configures VPC)
  4. Sets up SSO permissions for the requesting team

Total time: ~20 minutes vs. the previous 4-hour manual process.

Step 4: Account Customizations — Baseline Every Account

AFT supports customizations that run on every new account. Add your security baseline here:

# aft-account-customizations/terraform/main.tf (runs on every new account)

# Enable GuardDuty
resource "aws_guardduty_detector" "main" {
  enable = true
  datasources {
    s3_logs { enable = true }
    kubernetes { audit_logs { enable = true } }
    malware_protection { scan_ec2_instance_with_findings { ebs_volumes { enable = true } } }
  }
}

# Budget alert
resource "aws_budgets_budget" "account_budget" {
  name         = "account-monthly-budget"
  budget_type  = "COST"
  limit_amount = "500"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"
  
  notification {
    comparison_operator = "GREATER_THAN"
    threshold           = 80
    threshold_type      = "PERCENTAGE"
    notification_type   = "ACTUAL"
    subscriber_email_addresses = [var.account_owner_email]
  }
}

# Default VPC removal (security best practice)
resource "aws_default_vpc" "default" {
  force_destroy = true
}

Step 5: Self-Service Sandbox Accounts

Give engineers self-service sandbox accounts with automatic expiry and spending caps:

# accounts/eng-sandbox-alice/account-request.tf
module "account_request" {
  source = "github.com/aws-ia/terraform-aws-control_tower_account_factory//modules/aft-account-request"
  
  control_tower_parameters = {
    AccountEmail              = "[email protected]"
    AccountName               = "eng-sandbox-alice"
    ManagedOrganizationalUnit = "Sandbox"
    SSOUserEmail              = "[email protected]"
  }
  
  custom_fields = {
    expiry_date = "2025-07-01"   # Auto-suspend after 30 days
    owner       = "[email protected]"
  }
}
# Lambda: check sandbox account expiry daily
import boto3
from datetime import datetime

def check_sandbox_expiry(event, context):
    org = boto3.client('organizations')
    accounts = org.list_accounts_for_parent(
        ParentId=SANDBOX_OU_ID
    )
    
    for account in accounts['Accounts']:
        tags = org.list_tags_for_resource(ResourceId=account['Id'])
        expiry = next((t['Value'] for t in tags['Tags'] if t['Key'] == 'expiry_date'), None)
        
        if expiry and datetime.strptime(expiry, '%Y-%m-%d') < datetime.now():
            # Suspend account
            org.close_account(AccountId=account['Id'])

Step 6: Migrate Existing Accounts

For the 20 accounts already in use, enroll them into Control Tower incrementally:

# Enroll existing account via Control Tower console
# OR use Account Factory with the existing account's email:

# In Account Factory, choose "Enroll account"
# Provide: existing account ID, email, target OU
# Control Tower will:
#   - Add mandatory guardrails
#   - Configure centralized CloudTrail
#   - Set up AWS Config aggregation
#   - Apply Security Hub standards

Risk mitigation: Test enrollment on your least-critical accounts first. Some existing SCPs or IAM configurations may conflict with Control Tower’s required roles.

Summary

Before Control TowerAfter Control Tower
4+ hours to create account~20 minutes (automated)
2-week wait for dev accountsSelf-service sandbox in 20 minutes
Inconsistent security baselineMandatory guardrails enforced on every account
Manual compliance evidenceCentralized Config + CloudTrail in Log Archive
Engineers share admin credsSSO federation, individual attribution
Interview Angle
Mention the tension between governance and developer velocity. Control Tower guardrails can block legitimate workflows if not tuned carefully. The solution: start with detective guardrails (alert but don’t block), watch for false positives for 30 days, then promote the ones that never trigger false positives to preventive (blocking) guardrails.
Services Used
AWS Control TowerAWS OrganizationsAccount Factory for Terraform (AFT)IAM Identity CenterCloudTrailAWS Config
Prerequisites
  • Understanding of AWS Organizations and multi-account strategy
  • Familiarity with Terraform
  • Basic knowledge of SCPs
What You Learned
  • How to structure OUs for compliance and developer agility
  • How Account Factory for Terraform (AFT) automates account creation
  • Which guardrails to make mandatory vs optional per OU
  • How to give developers self-service sandbox accounts
  • How to migrate existing accounts into Control Tower without disruption

Have a similar scenario to share?

Production incidents are the best teachers. Submit your real-world scenario and help others learn.

Open Google Form

Related Scenarios