Table of Contents

Enterprise AWS environments require multiple accounts for isolation, security, and billing separation. AWS Organizations provides centralized governance across accounts, while Control Tower automates landing zone setup with guardrails and account factory. This lab teaches you to design and implement multi-account architectures that scale from startup to enterprise.

Lab Overview & Multi-Account Strategy

The single-account model breaks down quickly in enterprise environments. Multi-account architecture provides workload isolation, blast radius reduction, simplified billing, and separation of duties. AWS Organizations is free and provides centralized management, while Control Tower adds automated governance with pre-configured guardrails.

Prerequisites

  • LAB 10 Completed: AWS IAM fundamentals
  • AWS Account: This becomes your Management Account
  • Valid Email Addresses: Unique email per AWS account (use + aliases: admin+security@company.com)
  • AWS CLI v2: Configured with admin credentials

Enterprise Scenario: Scaling CloudFirst Inc.

You're the Cloud Platform Architect at CloudFirst Inc. The company has grown from 1 AWS account to chaos:

  • Problem: Dev, staging, and prod all in one account—devs can accidentally affect production
  • Problem: No way to track costs by team or project
  • Problem: Security team can't enforce policies across all workloads
  • Solution: Multi-account architecture with Organizations and Control Tower

Target Architecture

MULTI-ACCOUNT ORGANIZATION STRUCTURE

Root

Organization Root

Security OU

Log Archive, Audit

Infrastructure OU

Network, Shared Services

Workloads OU

Dev, Staging, Prod

Sandbox OU

Individual Sandboxes

Account Types

Module 1: Create AWS Organization

Module 1: Establish Your AWS Organization

Create the organization and understand the management account.

30-45 minutes5 steps
1

Create Organization

AWS Console
Navigate to: AWS Organizations Click "Create an organization" This account becomes the Management Account: - Owns the organization - Pays all member account bills (consolidated billing) - Can create/invite member accounts - Applies SCPs to OUs and accounts IMPORTANT: Management account should have minimal workloads! Use it only for organization management and billing.
2

Enable All Features

AWS Console
Navigate to: Organizations Settings Verify "All features" is enabled: - Consolidated billing: ✓ (always on) - Service control policies: ✓ - Tag policies: ✓ - AI services opt-out policies: ✓ - Backup policies: ✓ If only "Consolidated billing" is enabled: Click "Enable all features" Send request to all existing member accounts Wait for acceptance
3

Create Member Account

AWS Console
Navigate to: Organizations AWS accounts Click "Add an AWS account" Select "Create an AWS account" Account details: - AWS account name: Security-Audit - Email: admin+security@yourcompany.com (Use + alias for unique emails with same inbox) - IAM role name: OrganizationAccountAccessRole (Default role for cross-account access from management) Click "Create AWS account" Wait for account creation (few minutes). Repeat for additional accounts: - Log-Archive (admin+logs@yourcompany.com) - Network-Hub (admin+network@yourcompany.com) - Workload-Dev (admin+dev@yourcompany.com) - Workload-Prod (admin+prod@yourcompany.com)
4

Access Member Account

AWS CLI
# From management account, assume role into member account MEMBER_ACCOUNT_ID="111111111111" # Replace with actual ID aws sts assume-role \ --role-arn "arn:aws:iam::${MEMBER_ACCOUNT_ID}:role/OrganizationAccountAccessRole" \ --role-session-name "OrgAccess" # Export returned credentials export AWS_ACCESS_KEY_ID="ASIA..." export AWS_SECRET_ACCESS_KEY="..." export AWS_SESSION_TOKEN="..." # Verify you're in member account aws sts get-caller-identity # Or add to ~/.aws/config for easier access: [profile security-audit] role_arn = arn:aws:iam::111111111111:role/OrganizationAccountAccessRole source_profile = management region = us-east-1
5

View Organization via CLI

AWS CLI
# Describe organization aws organizations describe-organization # List all accounts aws organizations list-accounts # List roots (should be one) aws organizations list-roots # Get root ID for creating OUs ROOT_ID=$(aws organizations list-roots --query 'Roots[0].Id' --output text) echo "Root ID: $ROOT_ID"

Module 2: Organizational Units (OUs)

Module 2: Structure Your Organization with OUs

Create organizational units to group accounts by function.

30-45 minutes4 steps
6

Create OUs

AWS CLI
# Get root ID ROOT_ID=$(aws organizations list-roots --query 'Roots[0].Id' --output text) # Create Security OU aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Security" # Create Infrastructure OU aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Infrastructure" # Create Workloads OU aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Workloads" # Create Sandbox OU aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Sandbox" # List OUs aws organizations list-organizational-units-for-parent \ --parent-id $ROOT_ID
7

Create Nested OUs

AWS CLI
# Get Workloads OU ID WORKLOADS_OU=$(aws organizations list-organizational-units-for-parent \ --parent-id $ROOT_ID \ --query "OrganizationalUnits[?Name=='Workloads'].Id" \ --output text) # Create nested OUs under Workloads aws organizations create-organizational-unit \ --parent-id $WORKLOADS_OU \ --name "Development" aws organizations create-organizational-unit \ --parent-id $WORKLOADS_OU \ --name "Staging" aws organizations create-organizational-unit \ --parent-id $WORKLOADS_OU \ --name "Production" # Structure: # Root # Security # Infrastructure # Workloads # Development # Staging # Production # Sandbox
8

Move Accounts to OUs

AWS CLI
# Get account IDs aws organizations list-accounts --query 'Accounts[*].[Name,Id]' --output table # Get OU IDs SECURITY_OU=$(aws organizations list-organizational-units-for-parent \ --parent-id $ROOT_ID \ --query "OrganizationalUnits[?Name=='Security'].Id" \ --output text) # Move Security-Audit account to Security OU SECURITY_ACCOUNT_ID="111111111111" # Replace with actual aws organizations move-account \ --account-id $SECURITY_ACCOUNT_ID \ --source-parent-id $ROOT_ID \ --destination-parent-id $SECURITY_OU # Verify account location aws organizations list-accounts-for-parent \ --parent-id $SECURITY_OU
9

Visualize in Console

AWS Console
Navigate to: Organizations AWS accounts View shows hierarchical structure: Root Security (OU) Security-Audit (Account) Log-Archive (Account) Infrastructure (OU) Network-Hub (Account) Workloads (OU) Development (OU) Workload-Dev (Account) Production (OU) Workload-Prod (Account) Sandbox (OU) SCPs applied to an OU affect ALL accounts in that OU (and nested OUs).

Module 3: Service Control Policies (SCPs)

Module 3: Implement Organization-Wide Guardrails

Create SCPs to enforce security policies across all accounts.

60-90 minutes6 steps

How SCPs Work

SCPs don't grant permissions—they set maximum permissions boundaries:

  • SCPs filter what IAM policies can allow
  • If SCP denies an action, no IAM policy can override it
  • SCPs don't affect management account
  • SCPs are inherited from parent OUs
10

Enable SCPs

AWS Console
Navigate to: Organizations Policies Service control policies Click "Enable service control policies" Default SCP: FullAWSAccess - Attached to Root by default - Allows all actions (no restrictions) - You'll add restrictive policies on top of this
11

Create Deny Regions SCP

AWS CLI
# Create SCP to restrict regions cat > deny-regions-scp.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyNonApprovedRegions", "Effect": "Deny", "NotAction": [ "iam:*", "organizations:*", "support:*", "budgets:*", "cloudfront:*", "route53:*", "waf:*", "wafv2:*" ], "Resource": "*", "Condition": { "StringNotEquals": { "aws:RequestedRegion": [ "us-east-1", "us-west-2", "eu-west-1" ] } } } ] } EOF aws organizations create-policy \ --name "DenyNonApprovedRegions" \ --description "Restrict resources to approved regions only" \ --content file://deny-regions-scp.json \ --type SERVICE_CONTROL_POLICY
12

Create Deny Root User SCP

AWS CLI
cat > deny-root-scp.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyRootUser", "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "StringLike": { "aws:PrincipalArn": "arn:aws:iam::*:root" } } } ] } EOF aws organizations create-policy \ --name "DenyRootUserAccess" \ --description "Prevent root user from performing any actions" \ --content file://deny-root-scp.json \ --type SERVICE_CONTROL_POLICY
13

Create Protect Security Resources SCP

AWS CLI
cat > protect-security-scp.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "ProtectCloudTrail", "Effect": "Deny", "Action": [ "cloudtrail:DeleteTrail", "cloudtrail:StopLogging", "cloudtrail:UpdateTrail" ], "Resource": "*" }, { "Sid": "ProtectConfig", "Effect": "Deny", "Action": [ "config:DeleteConfigRule", "config:DeleteConfigurationRecorder", "config:DeleteDeliveryChannel", "config:StopConfigurationRecorder" ], "Resource": "*" }, { "Sid": "ProtectGuardDuty", "Effect": "Deny", "Action": [ "guardduty:DeleteDetector", "guardduty:DisassociateFromMasterAccount", "guardduty:StopMonitoringMembers" ], "Resource": "*" }, { "Sid": "DenyLeaveOrganization", "Effect": "Deny", "Action": "organizations:LeaveOrganization", "Resource": "*" } ] } EOF aws organizations create-policy \ --name "ProtectSecurityResources" \ --description "Prevent deletion of security infrastructure" \ --content file://protect-security-scp.json \ --type SERVICE_CONTROL_POLICY
14

Attach SCPs to OUs

AWS CLI
# Get policy IDs aws organizations list-policies --filter SERVICE_CONTROL_POLICY \ --query 'Policies[*].[Name,Id]' --output table DENY_REGIONS_POLICY_ID="p-xxxxxxxx" DENY_ROOT_POLICY_ID="p-yyyyyyyy" PROTECT_SECURITY_POLICY_ID="p-zzzzzzzz" # Attach to Root (affects all accounts except management) ROOT_ID=$(aws organizations list-roots --query 'Roots[0].Id' --output text) aws organizations attach-policy \ --policy-id $DENY_REGIONS_POLICY_ID \ --target-id $ROOT_ID aws organizations attach-policy \ --policy-id $DENY_ROOT_POLICY_ID \ --target-id $ROOT_ID aws organizations attach-policy \ --policy-id $PROTECT_SECURITY_POLICY_ID \ --target-id $ROOT_ID # Verify attachments aws organizations list-policies-for-target \ --target-id $ROOT_ID \ --filter SERVICE_CONTROL_POLICY
15

Create Sandbox Restrictions SCP

AWS CLI
# Extra restrictions for sandbox accounts cat > sandbox-restrictions-scp.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyExpensiveServices", "Effect": "Deny", "Action": [ "redshift:*", "rds:CreateDBInstance", "rds:CreateDBCluster", "ec2:RunInstances" ], "Resource": "*", "Condition": { "ForAnyValue:StringNotLike": { "ec2:InstanceType": [ "t2.*", "t3.*", "t3a.*" ] } } }, { "Sid": "DenyNetworkChanges", "Effect": "Deny", "Action": [ "ec2:CreateVpc", "ec2:CreateTransitGateway", "ec2:CreateVpnGateway", "directconnect:*" ], "Resource": "*" } ] } EOF aws organizations create-policy \ --name "SandboxRestrictions" \ --description "Additional restrictions for sandbox accounts" \ --content file://sandbox-restrictions-scp.json \ --type SERVICE_CONTROL_POLICY # Attach only to Sandbox OU SANDBOX_OU=$(aws organizations list-organizational-units-for-parent \ --parent-id $ROOT_ID \ --query "OrganizationalUnits[?Name=='Sandbox'].Id" \ --output text) aws organizations attach-policy \ --policy-id $SANDBOX_POLICY_ID \ --target-id $SANDBOX_OU

Module 4: AWS Control Tower Setup

Module 4: Deploy Control Tower Landing Zone

Automate governance with Control Tower's managed guardrails.

60-90 minutes5 steps

Control Tower Prerequisites

  • Must be deployed in us-east-1, us-west-2, eu-west-1, or other supported regions
  • Requires 2 unique email addresses for Log Archive and Audit accounts
  • Takes 30-60 minutes to deploy
  • Creates infrastructure that incurs costs (minimal)
16

Launch Control Tower

Control Tower
Navigate to: AWS Control Tower Click "Set up landing zone" Home Region: us-east-1 (or your preferred) Click "Next" Foundation OUs: - Security OU: Created automatically - Sandbox OU: Optional, recommended Click "Next" Core accounts (created automatically): - Log Archive account: Email: admin+logs@yourcompany.com - Audit account: Email: admin+audit@yourcompany.com Click "Next" Additional configurations: - ✓ Enable AWS CloudTrail - ✓ Enable AWS Config - ✓ Enable AWS IAM Identity Center - KMS key: Create new (recommended) Review and click "Set up landing zone" Wait 30-60 minutes for deployment
17

Understand Control Tower Resources

Control Tower
Control Tower creates: 1. Log Archive Account: - Centralized CloudTrail logs - AWS Config snapshots - Immutable audit trail 2. Audit Account: - Cross-account security access - Security Hub aggregation - GuardDuty administrator 3. IAM Identity Center (SSO): - Centralized user management - Permission sets for access - MFA enforcement 4. Guardrails: - Preventive (SCPs) - Detective (Config Rules) 5. CloudFormation StackSets: - Baseline deployed to all accounts
18

View Landing Zone Dashboard

Control Tower
Navigate to: Control Tower Dashboard Dashboard shows: - Landing zone status: Active - Guardrails enabled: XX - Accounts enrolled: XX - Drift detected: None (hopefully!) Organization section: - OUs and accounts created by Control Tower - Security OU with Log Archive and Audit Guardrails section: - Mandatory (always on) - Strongly Recommended (enable these) - Elective (optional) Accounts section: - All enrolled accounts - Compliance status per account
19

Register Existing OUs

Control Tower
If you created OUs before Control Tower: Navigate to: Control Tower Organization Find your existing OU (e.g., "Workloads") Click "Register OU" Registration: - Extends guardrails to this OU - Deploys baseline CloudFormation stacks - Enrolls all accounts in the OU Wait for registration to complete. All accounts in the OU now under governance. Repeat for: - Infrastructure OU - Sandbox OU - Any other custom OUs
20

Enable Strongly Recommended Guardrails

Control Tower
Navigate to: Control Tower Guardrails Strongly Recommended Guardrails to enable: Preventive (SCPs): ✓ Disallow changes to encryption configuration for S3 buckets ✓ Disallow changes to replication configuration for S3 buckets ✓ Disallow deletion of log archive ✓ Disallow public access to S3 buckets ✓ Disallow internet connection through RDS instances Detective (Config Rules): ✓ Detect whether MFA is enabled for root user ✓ Detect whether public access is enabled on S3 buckets ✓ Detect whether EBS volumes are attached to EC2 instances ✓ Detect whether encryption is enabled for EBS volumes For each guardrail: Click guardrail name Click "Enable guardrail on OU" Select target OU (e.g., Workloads) Click "Enable"

Module 5: Account Factory & Provisioning

Module 5: Automated Account Provisioning

Use Account Factory to create governed accounts on demand.

45-60 minutes4 steps
21

Configure Account Factory

Control Tower
Navigate to: Control Tower Account Factory Network configuration: Click "Edit" VPC configuration for new accounts: - Internet-accessible subnet: Yes/No - Maximum number of private subnets: 3 - Address range: 10.0.0.0/16 (default) - Regions for VPC creation: us-east-1, us-west-2 These settings apply to ALL new accounts created through Account Factory.
22

Create Account via Account Factory

Control Tower
Navigate to: Control Tower Account Factory Click "Create account" Account details: - Account email: admin+newapp@yourcompany.com - Display name: NewApp-Production - IAM Identity Center user email: developer@yourcompany.com - IAM Identity Center user name: First Last Organizational unit: Select: Workloads/Production Click "Create account" Account provisioning: - Creates AWS account - Deploys baseline CloudFormation - Applies guardrails - Creates IAM Identity Center user - Sends welcome email Wait 20-30 minutes for completion.
23

Account Factory with Service Catalog

AWS Console
Account Factory uses AWS Service Catalog: Navigate to: Service Catalog Portfolios Find: AWS Control Tower Account Factory Portfolio Products: - AWS Control Tower Account Factory This allows delegated account creation: 1. Grant portfolio access to specific users/groups 2. They can request new accounts through Service Catalog 3. Accounts are created with governance automatically For automation, use Service Catalog API or Account Factory for Terraform (AFT).
24

Enroll Existing Account

Control Tower
To bring existing accounts under Control Tower: Navigate to: Control Tower Organization Find the account to enroll Click "Enroll account" Prerequisites for enrollment: - Account must be in a registered OU - Account must not have conflicting resources - IAM Identity Center must be configured Enrollment process: - Deploys baseline StackSet - Applies guardrails - Creates IAM Identity Center access - Configures CloudTrail and Config Review potential conflicts before enrolling!

Module 6: Guardrails & Compliance

Module 6: Monitor and Enforce Compliance

Use detective and preventive guardrails for continuous compliance.

45-60 minutes4 steps
25

View Compliance Status

Control Tower
Navigate to: Control Tower Dashboard Compliance Overview: - Resources in compliance: XX% - Non-compliant resources: XX - Accounts with issues: X Click on non-compliant item: - Shows which guardrail failed - Which account/resource - Remediation guidance Navigate to: Control Tower Guardrails Click on specific guardrail View "Accounts" tab for compliance per account
26

Handle Drift Detection

Control Tower
Drift occurs when someone modifies Control Tower resources: Types of drift: - SCP modified or deleted - OU deleted or moved - Account moved out of governed OU - Member account deleted - IAM Identity Center config changed Navigate to: Control Tower Settings View drift status If drift detected: Click "Repair" Control Tower restores expected state Prevention: - Use SCPs to protect Control Tower resources - Limit who can modify organization structure - Enable CloudTrail alerts on Organizations API
27

Create Custom Guardrail

Control Tower
Control Tower supports custom guardrails via Config Rules: Navigate to: Control Tower Guardrails Create guardrail Option 1: Use AWS managed Config rule - Select from existing AWS Config rules - Apply to specific OUs Option 2: Create custom rule (Advanced) 1. Create custom Config Rule in Audit account 2. Deploy via StackSet to all accounts 3. Register as Control Tower guardrail Example custom rule: Require specific tags on resources - Lambda function evaluates tag compliance - Reports non-compliant resources - Can trigger auto-remediation
28

Export Compliance Reports

AWS Console
For audit purposes, export compliance data: Option 1: AWS Config Aggregator Navigate to: Config Aggregators - View aggregated compliance across accounts - Export to CSV/JSON Option 2: Security Hub Navigate to: Security Hub Findings - Cross-account security findings - Export compliance reports Option 3: Custom Reports - Query Config data via API - Use Athena on CloudTrail logs - Build custom compliance dashboards Store reports in Log Archive account S3 bucket.

Module 7: Centralized Logging & Security

Module 7: Aggregate Logs and Security Findings

Configure centralized logging, Security Hub, and GuardDuty.

45-60 minutes4 steps
29

Explore Log Archive Structure

AWS Console
Switch to Log Archive account: S3 bucket structure: aws-controltower-logs-[account-id]-[region]/ AWSLogs/ [account-id]/ CloudTrail/ [region]/ YYYY/MM/DD/ Config/ [region]/ o-[org-id]/ [account-id]/ CloudTrail/ Bucket policies: - Cross-account write access for member accounts - Deny delete for everyone - Versioning enabled - Lifecycle rules for archival This is your immutable audit trail!
30

Configure Security Hub Aggregation

AWS Console
In Audit/Security account: Navigate to: Security Hub Settings Regions Enable cross-region aggregation: Add all regions you use Set aggregation region (e.g., us-east-1) Configure organization integration: Settings Accounts Auto-enable Security Hub in new accounts: Yes Enable standards: - AWS Foundational Security Best Practices - CIS AWS Foundations Benchmark - PCI DSS (if applicable) All findings from all accounts aggregate here!
31

Configure GuardDuty Organization

AWS Console
In Audit/Security account (delegated admin): Navigate to: GuardDuty Settings Auto-enable for organization: Toggle: Auto-enable GuardDuty for new accounts Protection plans: ✓ S3 Protection ✓ EKS Protection ✓ Malware Protection ✓ RDS Protection Findings aggregation: - All member account findings visible here - Can suppress or archive findings - Export to S3 for SIEM integration Create SNS topic for alerting: Settings Findings export options Configure S3 bucket and SNS
32

Query Logs with Athena

AWS CLI
# In Log Archive account, create Athena table for CloudTrail CREATE EXTERNAL TABLE cloudtrail_logs ( eventVersion STRING, userIdentity STRUCT< type:STRING, principalId:STRING, arn:STRING, accountId:STRING, invokedBy:STRING, accessKeyId:STRING, userName:STRING>, eventTime STRING, eventSource STRING, eventName STRING, awsRegion STRING, sourceIPAddress STRING, userAgent STRING, errorCode STRING, errorMessage STRING ) ROW FORMAT SERDE 'com.amazon.emr.hive.serde.CloudTrailSerde' STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://aws-controltower-logs-XXXX/AWSLogs/o-xxxxx/' -- Query: Find all root logins across organization SELECT userIdentity.accountId, eventTime, sourceIPAddress FROM cloudtrail_logs WHERE userIdentity.type = 'Root' AND eventName = 'ConsoleLogin' ORDER BY eventTime DESC LIMIT 100;

Security Best Practices

CRITICAL

Management Account Compromise

Management account has implicit admin access to all accounts.

Mitigation
  • No workloads in management account
  • Maximum 2-3 admin users with MFA
  • Use IAM Identity Center for daily access
  • Alert on all management account activity
HIGH

SCP Bypass via Management Account

SCPs don't affect the management account at all.

Mitigation
  • Treat management account as highly privileged
  • Use IAM policies in management account
  • Audit management account actions separately
HIGH

Cross-Account Role Abuse

OrganizationAccountAccessRole grants admin to management account.

Mitigation
  • Limit who can assume this role
  • Use IAM Identity Center instead
  • Monitor AssumeRole calls in CloudTrail
MEDIUM

Log Archive Tampering

Attacker may try to delete or modify audit logs.

Mitigation
  • SCP prevents log deletion
  • S3 Object Lock for immutability
  • Separate AWS account for logs
  • Cross-region replication

Multi-Account Best Practices

  • Use dedicated accounts for security (logs, audit) separate from workloads
  • Apply SCPs at OU level for consistent governance
  • Enable CloudTrail organization trail in management account
  • Use IAM Identity Center for human access (not IAM users per account)
  • Implement preventive guardrails before detective ones
  • Deny root user access via SCP (except management)
  • Restrict regions via SCP to reduce attack surface
  • Centralize Security Hub and GuardDuty in security account

Additional Resources