You are viewing a preview of this lesson. Sign in to start learning
Back to Mastering AWS

Multi-Account & Compliance

AWS Organizations, SCPs, Control Tower, and compliance automation

Multi-Account Strategies and Compliance in AWS

Master AWS multi-account architectures and compliance frameworks with free flashcards and spaced repetition practice. This lesson covers AWS Organizations, Control Tower, Service Control Policies (SCPs), compliance automation, and audit strategiesβ€”essential concepts for building secure, governable cloud environments at scale.

Welcome to Multi-Account & Compliance 🏒

As your AWS footprint grows, managing resources in a single account becomes increasingly complex and risky. A multi-account strategy provides security isolation, billing separation, compliance boundaries, and operational flexibility. Combined with robust compliance frameworks, this approach enables enterprises to maintain governance while empowering teams to innovate safely.

In this lesson, you'll learn how to architect multi-account environments using AWS Organizations, enforce policies with SCPs, automate compliance checks with AWS Config and Security Hub, and implement continuous audit strategies. Whether you're preparing for AWS certifications or designing production architectures, these patterns form the foundation of enterprise cloud governance.

Why Multi-Account Architecture? πŸ”

Running everything in a single AWS account creates several challenges:

Security Blast Radius: A compromised resource can potentially access everything in the account. Multi-account isolation limits damage.

Billing Complexity: Without account separation, attributing costs to specific teams, projects, or environments becomes difficult.

Compliance Boundaries: Many regulations require logical or physical separation between production and non-production data, or between different data classifications.

Resource Limits: AWS service quotas apply per-account. Multi-account architectures increase effective limits.

Operational Independence: Teams can work independently without interfering with each other's resources or hitting conflicting configurations.

πŸ’‘ Best Practice: Start with a multi-account strategy early, even for small deployments. Migrating from single-account to multi-account later is significantly more complex.

AWS Organizations: The Foundation πŸ—οΈ

AWS Organizations is a free service that enables you to centrally manage multiple AWS accounts. It provides:

Consolidated Billing: Single payment method for all accounts with combined volume discounts

Hierarchical Organization: Group accounts into Organizational Units (OUs) reflecting your business structure

Policy-Based Control: Apply Service Control Policies (SCPs) to restrict permissions across accounts

Account Creation Automation: Programmatically create new accounts via API

Service Enablement: Centrally enable AWS services across all accounts

AWS Organizations Structure

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Root (Management Account)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚                         β”‚
β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”             β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚Production β”‚             β”‚Non-Prod     β”‚
β”‚    OU     β”‚             β”‚    OU       β”‚
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”‚                        β”‚
  β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚        β”‚           β”‚       β”‚        β”‚
β”Œβ”€β–Όβ”€β”€β”  β”Œβ”€β–Όβ”€β”€β”     β”Œβ”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β”  β”Œβ”€β”€β–Όβ”€β”€β”
β”‚App1β”‚  β”‚App2β”‚     β”‚Dev  β”‚ β”‚Test β”‚  β”‚Stageβ”‚
β”‚Acctβ”‚  β”‚Acctβ”‚     β”‚Acct β”‚ β”‚Acct β”‚  β”‚Acct β”‚
β””β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”˜

Management Account (formerly Master Account): The root account that creates the organization. Use this ONLY for billing and organization managementβ€”avoid running workloads here.

Member Accounts: All other accounts in the organization. These run your actual workloads.

Organizational Units (OUs): Logical groupings of accounts. Common OU structures:

  • By environment (Production, Staging, Development)
  • By function (Security, Infrastructure, Logging)
  • By business unit (Finance, Marketing, Engineering)
  • By lifecycle (Suspended, Active, Sandbox)

🧠 Memory Device - OU Structure: Think "PEBS" - Production, Environment separation, Business units, Security/infrastructure accounts.

Service Control Policies (SCPs): The Guardrails 🚧

Service Control Policies are JSON policy documents that define the maximum permissions available in an account. They act as guardrailsβ€”even if an IAM policy grants permission, an SCP can deny it.

Key Characteristics:

  • Deny by Default: SCPs don't grant permissions, they filter what IAM can grant
  • Hierarchical Inheritance: SCPs attached to parent OUs affect all child accounts
  • Management Account Immunity: SCPs don't apply to the management account
  • Override Everything: Even the root user in a member account is restricted by SCPs

Common SCP Patterns:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRegionRestriction",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": [
            "us-east-1",
            "us-west-2"
          ]
        },
        "ForAllValues:StringNotLike": {
          "aws:PrincipalOrgPaths": [
            "o-*/r-*/ou-*/*"
          ]
        }
      }
    }
  ]
}

This SCP restricts all actions to specific regionsβ€”a common compliance requirement for data residency.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PreventLeavingOrganization",
      "Effect": "Deny",
      "Action": [
        "organizations:LeaveOrganization"
      ],
      "Resource": "*"
    },
    {
      "Sid": "PreventDeletingCloudTrail",
      "Effect": "Deny",
      "Action": [
        "cloudtrail:StopLogging",
        "cloudtrail:DeleteTrail"
      ],
      "Resource": "*"
    }
  ]
}

This SCP prevents security control tamperingβ€”accounts can't disable auditing or leave the organization.

πŸ’‘ Pro Tip: Start with a permissive SCP (AllowAll) and gradually add deny statements. Overly restrictive SCPs can break legitimate operations.

⚠️ Critical: SCPs use explicit deny logic. If any SCP in the hierarchy denies an action, it's denied regardless of other allows.

SCP EffectIAM PolicyEffective Permission
Allow (implicit)Allowβœ… Allowed
Allow (implicit)Deny❌ Denied (IAM deny wins)
Deny (explicit)Allow❌ Denied (SCP deny wins)
Deny (explicit)Deny❌ Denied

AWS Control Tower: Automated Landing Zones πŸš€

AWS Control Tower provides automated setup of a secure, multi-account AWS environment based on best practices. It builds on Organizations, adding:

Landing Zone: Pre-configured multi-account environment with:

  • Management account
  • Log Archive account (centralized logging)
  • Audit account (security/compliance tools)
  • Shared services account (networking, Active Directory)

Guardrails: High-level rules implemented via SCPs and AWS Config:

  • Mandatory: Always enforced (e.g., disallow public S3 buckets)
  • Strongly Recommended: Best practices you should enable
  • Elective: Optional based on your requirements

Account Factory: Automated account provisioning with:

  • Pre-configured VPCs and networking
  • Baseline security controls
  • CloudFormation StackSets deployment
  • Service Catalog integration

Dashboard: Centralized view of compliance status across all accounts

Control Tower Landing Zone Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        Management Account                  β”‚
β”‚  - AWS Organizations                       β”‚
β”‚  - Control Tower Console                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                 β”‚
β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Security   β”‚   β”‚ Foundational β”‚
β”‚    OU      β”‚   β”‚     OU       β”‚
β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚                 β”‚
β”Œβ”€β”€β”€β”΄β”€β”€β”€β”         β”Œβ”€β”€β”€β”΄β”€β”€β”€β”
β”‚ Log   β”‚         β”‚ Audit β”‚
β”‚Archiveβ”‚         β”‚ Acct  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚                     β”‚
β”‚ CloudTrail logs     β”‚ Config, Security Hub
β”‚ VPC Flow Logs       β”‚ Cross-account access
β”‚ S3 Access Logs      β”‚ Read-only visibility

When to Use Control Tower: βœ… Starting fresh AWS deployments βœ… Need standardized account provisioning βœ… Want pre-built governance guardrails βœ… Limited AWS expertise

When to Skip Control Tower: ❌ Existing complex multi-account structure ❌ Need highly customized architectures ❌ Already have mature account vending process

πŸ”§ Try This: Use Control Tower's Account Factory to create a sandbox account. Notice how networking, logging, and security baselines are automatically configured.

Compliance Automation with AWS Config πŸ“‹

AWS Config continuously monitors and records AWS resource configurations, enabling:

Configuration History: Timeline of all configuration changes

Compliance Auditing: Evaluate resources against rules

Resource Relationships: Track dependencies (e.g., which EC2 instances use which security groups)

Change Notifications: SNS alerts when resources become non-compliant

Config Rules: Automated compliance checks, either:

  • AWS Managed Rules: Pre-built rules for common requirements (80+ available)
  • Custom Rules: Lambda functions for organization-specific requirements

Common Config Rules:

## Custom Config Rule (Lambda function)
import boto3
import json

config = boto3.client('config')

def lambda_handler(event, context):
    # Get the invoking event
    invoking_event = json.loads(event['invokingEvent'])
    configuration_item = invoking_event['configurationItem']
    
    # Check if S3 bucket has encryption enabled
    compliance_type = 'NON_COMPLIANT'
    annotation = 'Bucket encryption is disabled'
    
    if configuration_item['resourceType'] == 'AWS::S3::Bucket':
        bucket_name = configuration_item['resourceName']
        s3 = boto3.client('s3')
        
        try:
            encryption = s3.get_bucket_encryption(Bucket=bucket_name)
            compliance_type = 'COMPLIANT'
            annotation = 'Bucket has encryption enabled'
        except:
            pass
    
    # Report evaluation result
    config.put_evaluations(
        Evaluations=[
            {
                'ComplianceResourceType': configuration_item['resourceType'],
                'ComplianceResourceId': configuration_item['resourceId'],
                'ComplianceType': compliance_type,
                'Annotation': annotation,
                'OrderingTimestamp': configuration_item['configurationItemCaptureTime']
            }
        ],
        ResultToken=event['resultToken']
    )

This custom rule checks S3 bucket encryption compliance.

AWS Config Aggregator: Centralize compliance data from multiple accounts/regions into a single view.

{
  "AccountAggregationSources": [
    {
      "AccountIds": ["111111111111", "222222222222"],
      "AllAwsRegions": true
    }
  ],
  "OrganizationAggregationSource": {
    "RoleArn": "arn:aws:iam::999999999999:role/ConfigAggregatorRole",
    "AllAwsRegions": true
  }
}

πŸ’‘ Cost Optimization: Config charges per configuration item recorded. Use recording strategies to focus on critical resources:

  • Record only specific resource types
  • Exclude resource types that change frequently but aren't compliance-critical
  • Use organization-level rules instead of per-account deployment

Security Hub: Centralized Security Findings πŸ›‘οΈ

AWS Security Hub aggregates security findings from:

  • AWS Config (compliance violations)
  • Amazon GuardDuty (threat detection)
  • Amazon Inspector (vulnerability scanning)
  • Amazon Macie (data privacy)
  • IAM Access Analyzer
  • Third-party tools (Palo Alto, Trend Micro, etc.)

Security Standards:

  • AWS Foundational Security Best Practices: AWS-defined baseline
  • CIS AWS Foundations Benchmark: Center for Internet Security standards
  • PCI DSS: Payment Card Industry requirements
  • NIST: National Institute of Standards framework

Findings Workflow:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Security Finding Sources                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚GuardDuty β”‚Inspector β”‚  Config  β”‚  Macie     β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚          β”‚          β”‚            β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
            β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
            β”‚  Security Hub  β”‚
            β”‚  - Normalize   β”‚
            β”‚  - Prioritize  β”‚
            β”‚  - Enrich      β”‚
            β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚              β”‚              β”‚
β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”
β”‚EventBridgeβ”‚ β”‚Custom Actionsβ”‚ β”‚Insightsβ”‚
β”‚Automation β”‚ β”‚SIEM/SOAR/Ticketβ”‚ β”‚Trendsβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Integrations:

## Forward Security Hub findings to Slack
import boto3
import json
import urllib3

http = urllib3.PoolManager()

def lambda_handler(event, context):
    finding = event['detail']['findings'][0]
    
    # Extract key information
    severity = finding['Severity']['Label']
    title = finding['Title']
    resource = finding['Resources'][0]['Id']
    description = finding['Description']
    
    # Format Slack message
    slack_message = {
        'text': f":warning: Security Finding: {severity}",
        'attachments': [
            {
                'color': 'danger' if severity == 'CRITICAL' else 'warning',
                'fields': [
                    {'title': 'Title', 'value': title},
                    {'title': 'Resource', 'value': resource},
                    {'title': 'Description', 'value': description}
                ]
            }
        ]
    }
    
    # Send to Slack
    webhook_url = 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
    response = http.request(
        'POST',
        webhook_url,
        body=json.dumps(slack_message),
        headers={'Content-Type': 'application/json'}
    )
    
    return {'statusCode': 200}

Multi-Account Security Hub:

  • Designate an administrator account (typically the Audit account)
  • Member accounts send findings to the administrator
  • Centralized dashboard shows all findings across the organization

Compliance Frameworks and Mapping πŸ“œ

AWS provides tools to map controls to common compliance frameworks:

AWS Artifact: Access compliance reports and agreements

  • SOC 1, 2, 3 reports
  • PCI DSS Attestation of Compliance
  • ISO certifications
  • HIPAA Business Associate Addendum

AWS Audit Manager: Automate evidence collection for audits

## Example Audit Manager Framework Mapping
Framework: PCI-DSS v3.2.1
  Requirement 1.1.4: Firewall configuration standards
    Controls:
      - Security Group ingress rules (AWS Config)
      - NACL configurations (AWS Config)
      - VPC Flow Logs enabled (CloudWatch)
    Evidence:
      - Config snapshots
      - CloudTrail logs
      - Automated assessments
  
  Requirement 10.2.1: Audit logs for privileged access
    Controls:
      - CloudTrail enabled all regions (Config Rule)
      - Log file validation (Config Rule)
      - S3 bucket encryption (Config Rule)
    Evidence:
      - CloudTrail trails configuration
      - S3 bucket policies
      - Log integrity validation

Compliance Mapping Table:

FrameworkKey AWS ServicesAutomation Tools
HIPAAKMS, CloudTrail, Config, VPCConfig Rules, Security Hub
PCI DSSCloudTrail, Config, GuardDuty, VPCSecurity Hub PCI standard
SOC 2CloudTrail, IAM, Config, KMSAudit Manager, Artifact
GDPRMacie, S3, KMS, CloudWatchMacie findings, Config Rules
FedRAMPCloudTrail, Config, GuardDuty, IAMSecurity Hub, Audit Manager

🌍 Real-World Scenario: A healthcare company needs HIPAA compliance. They:

  1. Enable CloudTrail in all regions (audit trail requirement)
  2. Create Config rule to enforce S3 bucket encryption (PHI protection)
  3. Use KMS for encryption key management (access control)
  4. Deploy Security Hub with custom insights for HIPAA-relevant findings
  5. Use Audit Manager to continuously collect evidence for annual audits

Account Vending and Automation 🏭

Account Factory automates new account creation with:

## Automated account creation with Control Tower
import boto3
import time

service_catalog = boto3.client('servicecatalog')
control_tower_product_id = 'prod-xxxxxxxxxxxx'

def create_account(account_name, email, ou_name, sso_user_email):
    # Provision new account through Service Catalog
    response = service_catalog.provision_product(
        ProductId=control_tower_product_id,
        ProvisioningArtifactId='pa-xxxxxxxxxxxx',
        ProvisionedProductName=f'{account_name}-provisioning',
        ProvisioningParameters=[
            {'Key': 'AccountName', 'Value': account_name},
            {'Key': 'AccountEmail', 'Value': email},
            {'Key': 'ManagedOrganizationalUnit', 'Value': ou_name},
            {'Key': 'SSOUserEmail', 'Value': sso_user_email},
            {'Key': 'SSOUserFirstName', 'Value': 'Admin'},
            {'Key': 'SSOUserLastName', 'Value': 'User'}
        ]
    )
    
    record_id = response['RecordDetail']['RecordId']
    
    # Wait for provisioning to complete
    while True:
        record = service_catalog.describe_record(Id=record_id)
        status = record['RecordDetail']['Status']
        
        if status == 'SUCCEEDED':
            account_id = record['RecordOutputs'][0]['OutputValue']
            print(f'Account created: {account_id}')
            return account_id
        elif status == 'FAILED':
            raise Exception('Account creation failed')
        
        time.sleep(10)

## Create accounts for different teams
create_account('team-alpha-prod', 'alpha-prod@company.com', 'Production', 'alpha-lead@company.com')
create_account('team-beta-dev', 'beta-dev@company.com', 'Development', 'beta-lead@company.com')

Baseline Configuration with StackSets:

## CloudFormation StackSet for security baseline
AWSTemplateFormatVersion: '2010-09-09'
Description: Security baseline for all accounts

Resources:
  CloudTrailBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub 'cloudtrail-${AWS::AccountId}'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  
  CloudTrailLog:
    Type: AWS::CloudTrail::Trail
    Properties:
      S3BucketName: !Ref CloudTrailBucket
      IsLogging: true
      IsMultiRegionTrail: true
      IncludeGlobalServiceEvents: true
      EnableLogFileValidation: true
  
  ConfigRecorder:
    Type: AWS::Config::ConfigurationRecorder
    Properties:
      RoleArn: !GetAtt ConfigRole.Arn
      RecordingGroup:
        AllSupported: true
        IncludeGlobalResourceTypes: true
  
  SecurityHubEnablement:
    Type: AWS::SecurityHub::Hub
    Properties:
      Tags:
        Environment: All

Deploy this StackSet to all accounts in your organization for consistent security baselines.

Continuous Audit and Remediation πŸ”„

Automated Remediation Workflow:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Resource becomes non-compliant          β”‚
β”‚    (e.g., S3 bucket made public)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. AWS Config detects violation            β”‚
β”‚    (s3-bucket-public-read-prohibited rule) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. EventBridge captures Config event       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. Lambda function triggered               β”‚
β”‚    - Analyze violation                     β”‚
β”‚    - Execute remediation                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. Remediation applied                     β”‚
β”‚    (Remove public access policy)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 6. Notification sent                       β”‚
β”‚    - SNS alert to security team            β”‚
β”‚    - Ticket created in ITSM                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Auto-Remediation Lambda Example:

import boto3
import json

s3 = boto3.client('s3')
sns = boto3.client('sns')

def lambda_handler(event, context):
    # Parse Config rule evaluation
    message = json.loads(event['Records'][0]['Sns']['Message'])
    config_item = message['configurationItem']
    
    if config_item['resourceType'] == 'AWS::S3::Bucket':
        bucket_name = config_item['resourceName']
        
        # Remove public access
        try:
            s3.put_public_access_block(
                Bucket=bucket_name,
                PublicAccessBlockConfiguration={
                    'BlockPublicAcls': True,
                    'IgnorePublicAcls': True,
                    'BlockPublicPolicy': True,
                    'RestrictPublicBuckets': True
                }
            )
            
            # Remove any public bucket policy
            try:
                policy = s3.get_bucket_policy(Bucket=bucket_name)
                # Analyze and remove public statements
                # (simplified for example)
                s3.delete_bucket_policy(Bucket=bucket_name)
            except:
                pass
            
            # Send notification
            sns.publish(
                TopicArn='arn:aws:sns:us-east-1:123456789012:security-alerts',
                Subject=f'Auto-remediated: Public S3 bucket {bucket_name}',
                Message=f'Automatically removed public access from bucket {bucket_name} due to compliance violation.'
            )
            
            return {'status': 'remediated', 'bucket': bucket_name}
            
        except Exception as e:
            print(f'Remediation failed: {e}')
            return {'status': 'failed', 'error': str(e)}

⚠️ Caution: Test auto-remediation thoroughly in non-production environments first. Incorrect remediation logic can disrupt legitimate operations.

Multi-Region Considerations 🌐

Global Services:

  • IAM (global, but visible from all regions)
  • CloudFront (global edge distribution)
  • Route 53 (global DNS)
  • WAF (can be global or regional)

Regional Services require per-region configuration:

  • VPCs
  • EC2 instances
  • RDS databases
  • Lambda functions

Multi-Region Compliance Strategy:

## Enable Config in all regions
import boto3

regions = ['us-east-1', 'us-west-2', 'eu-west-1', 'ap-southeast-1']

for region in regions:
    config = boto3.client('config', region_name=region)
    
    # Create configuration recorder
    config.put_configuration_recorder(
        ConfigurationRecorder={
            'name': 'default',
            'roleARN': f'arn:aws:iam::123456789012:role/ConfigRole',
            'recordingGroup': {
                'allSupported': True,
                'includeGlobalResourceTypes': (region == 'us-east-1')
            }
        }
    )
    
    # Create delivery channel
    config.put_delivery_channel(
        DeliveryChannel={
            'name': 'default',
            's3BucketName': 'config-bucket-123456789012',
            'configSnapshotDeliveryProperties': {
                'deliveryFrequency': 'TwentyFour_Hours'
            }
        }
    )
    
    # Start configuration recorder
    config.start_configuration_recorder(
        ConfigurationRecorderName='default'
    )

πŸ’‘ Optimization: Record global resources (IAM, CloudFront) only in one region (typically us-east-1) to avoid duplicate charges.

Common Mistakes to Avoid ⚠️

1. Running Workloads in the Management Account

  • ❌ Deploying applications in the root account
  • βœ… Use the management account ONLY for organization administration
  • Why: Security blast radiusβ€”if compromised, attacker controls entire organization

2. Overly Restrictive SCPs from the Start

  • ❌ Implementing dozens of deny rules before understanding needs
  • βœ… Start permissive, add restrictions based on actual requirements
  • Why: Can lock out legitimate operations and delay projects

3. Not Testing SCPs in Isolation

  • ❌ Applying SCPs directly to production OUs
  • βœ… Test on a sandbox OU first, verify impact
  • Why: SCPs affect all users including administrators

4. Ignoring Config Rule Costs

  • ❌ Enabling all Config rules for all resource types
  • βœ… Focus on compliance-critical resources, exclude noisy types
  • Why: Config charges per item recorded; costs add up quickly

5. Single Region CloudTrail

  • ❌ Enabling CloudTrail in only one region
  • βœ… Always use multi-region trails
  • Why: Attackers can operate in regions you're not monitoring

6. No Automated Remediation

  • ❌ Relying solely on manual responses to findings
  • βœ… Implement auto-remediation for common, low-risk violations
  • Why: Reduces response time from hours to seconds

7. Forgetting IAM Permission Boundaries

  • ❌ Assuming SCPs alone provide sufficient control
  • βœ… Use SCPs (account-level) + IAM permission boundaries (user/role-level)
  • Why: Defense in depthβ€”multiple layers catch different scenarios

8. Not Aggregating Security Hub Findings

  • ❌ Checking each account's Security Hub individually
  • βœ… Set up cross-account aggregation to administrator account
  • Why: Centralized visibility essential for large environments

9. Lack of Account Tagging Strategy

  • ❌ Creating accounts without consistent metadata
  • βœ… Tag accounts with owner, cost center, environment, compliance level
  • Why: Enables automated policy application and cost allocation

10. Not Planning for Account Closure

  • ❌ Creating accounts without decommissioning process
  • βœ… Document account lifecycle including deletion procedures
  • Why: Zombie accounts accumulate costs and security risks

🧠 Memory Device - Common Mistakes: "SCOTS RAIN" - SCPs too restrictive, Costs ignored (Config), Org admin in wrong account, Testing skipped, Single region trails, Remediation manual, Aggregation missing, IAM boundaries forgotten, No tagging strategy.

Key Takeaways 🎯

βœ… Multi-account architecture provides security isolation, billing clarity, and compliance boundaries

βœ… AWS Organizations centralizes management; OUs provide logical grouping; SCPs enforce guardrails

βœ… Control Tower automates landing zone creation with pre-built best practices and account vending

βœ… Service Control Policies define maximum permissions but don't grant themβ€”they filter what IAM can allow

βœ… AWS Config monitors resource configurations and evaluates compliance against rules (managed or custom)

βœ… Security Hub aggregates findings from multiple sources and maps to compliance frameworks

βœ… Audit Manager automates evidence collection for continuous compliance

βœ… CloudTrail must be multi-region and log-file-validated for audit integrity

βœ… Automated remediation via EventBridge + Lambda reduces response time to violations

βœ… StackSets deploy baseline configurations consistently across all accounts

βœ… Tag accounts with metadata for automated policy application and reporting

βœ… Test SCPs in sandbox environments before production deployment

πŸ“‹ Quick Reference Card

ServicePurposeKey Feature
OrganizationsMulti-account managementConsolidated billing, SCPs
Control TowerAutomated landing zonesGuardrails, Account Factory
SCPsPermission boundariesMaximum allowed permissions
ConfigResource complianceContinuous evaluation, remediation
Security HubFindings aggregationMulti-account, multi-service
CloudTrailAPI audit loggingWho did what, when, where
Audit ManagerCompliance evidenceAutomated evidence collection
StackSetsMulti-account deploymentConsistent baselines

SCP Evaluation Logic:
Explicit Deny (SCP) > Explicit Allow (IAM) > Implicit Deny (default)

Account Structure Best Practice:
Management (billing only) β†’ Security OU (Log Archive, Audit) β†’ Workload OUs (Prod, Non-Prod)

Compliance Automation Stack:
CloudTrail (logging) β†’ Config (evaluation) β†’ Security Hub (aggregation) β†’ EventBridge (orchestration) β†’ Lambda (remediation)

Further Study πŸ“š

  1. AWS Organizations Best Practices: https://docs.aws.amazon.com/organizations/latest/userguide/orgs_best-practices.html
  2. AWS Control Tower Guide: https://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html
  3. AWS Security Hub Standards: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards.html