aws
β€’ Markdown

Singapore Secure Enterprise CT

Complete AWS Control Tower + CDK v2 Guide (Singapore 2025 Edition)

This comprehensive guide creates a modern AWS Control Tower setup with Hello World applications using CDK v2.201.0+ in Singapore region with current 2025 best practices using dev/staging/prod environments.


Phase 1: Prerequisites and Modern Environment Setup

1.1 Verify System Requirements (2025 Standards)

# Check Node.js (CRITICAL: Need 20+ minimum, 22+ recommended)
node --version
# Expected: v22.x.x (recommended) or v20.x.x (minimum)
# NOTE: Node.js 18 will be deprecated November 30, 2025

# Check npm (need latest)
npm --version
# Expected: 10.x.x or higher

# Check AWS CLI (need v2.15+)
aws --version
# Expected: aws-cli/2.15.x or higher

# Check Git
git --version
# Expected: git version 2.40.x or higher

1.2 Install Latest Tools

# Install Node.js 22 (recommended for 2025)
# macOS with Homebrew
brew install node@22
brew link node@22

# Ubuntu/Debian
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs

# Verify Node.js 22 installation
node --version
# Should show v22.x.x

# Install/Update AWS CLI v2 (latest)
# macOS
brew install awscli
brew upgrade awscli

# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \
  -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --update

1.3 Configure AWS CLI for Singapore Region

# Configure AWS credentials for your management account
aws configure
# AWS Access Key ID: [Your management account access key]
# AWS Secret Access Key: [Your management account secret key]
# Default region name: ap-southeast-1
# Default output format: json

# Verify configuration
aws sts get-caller-identity
# Should show your account ID, user ARN, and user ID

# Enable MFA for CLI (recommended for production)
aws configure set mfa_serial arn:aws:iam::YOUR_ACCOUNT:mfa/YOUR_MFA_DEVICE

1.4 Install Latest CDK v2 with Modern Features

# Install CDK v2 globally (latest version)
npm install -g aws-cdk@latest

# Verify installation (should be 2.201.0+)
cdk --version
# Expected: 2.201.x or higher

# Verify CDK v2 features are available
cdk --help | grep -E "(migrate|rollback|watch)"
# Should show modern CDK commands

# Bootstrap all accounts in Singapore
echo "πŸ—οΈ  Bootstrapping accounts with Singapore security standards..."

bootstrap_account $DEV_ACCOUNT "Development"
bootstrap_account $STAGING_ACCOUNT "Staging"
bootstrap_account $SHARED_ACCOUNT "Shared Services"
bootstrap_account $PROD_ACCOUNT "Production"

echo ""
echo "βœ… All Singapore accounts bootstrapped with modern CDK toolkit!"
echo "πŸ” Features enabled:"
echo "   β”œβ”€β”€ Customer managed KMS keys"
echo "   β”œβ”€β”€ Termination protection"
echo "   β”œβ”€β”€ Cross-account trust"
echo "   β”œβ”€β”€ Enhanced security policies"
echo "   β”œβ”€β”€ Singapore data residency compliance"
echo "   └── PDPA/MAS/CSA compliance tags"

6.3 Enhanced Deployment Script for Singapore

Create scripts/deploy-applications-singapore.sh:

#!/bin/bash

# Load environment variables
source .env

echo "πŸš€ Deploying Hello World Applications (Singapore 2025 Edition)"
echo "============================================================="

# Function to deploy to specific account in Singapore
deploy_to_account() {
    local env_name="$1"
    local account_id="$2"
    local stack_name="HelloWorld-$env_name"

    echo "πŸ“¦ Deploying $stack_name to account $account_id in Singapore..."

    # Set context for the Singapore deployment
    cdk deploy $stack_name \
        --context accountId=$account_id \
        --context qualifier=sgcdk2025 \
        --context region=ap-southeast-1 \
        --context country=Singapore \
        --require-approval never \
        --rollback false \
        --outputs-file "outputs-$env_name-singapore.json" \
        --tags Environment=$env_name \
        --tags ManagedBy=CDK \
        --tags Version=2025.1.0 \
        --tags Region=ap-southeast-1 \
        --tags Country=Singapore \
        --tags DataResidency=Singapore \
        --tags ComplianceFramework=PDPA-MAS-CSA

    if [ $? -eq 0 ]; then
        echo "βœ… $stack_name deployed successfully to Singapore"

        # Extract API URL from outputs
        API_URL=$(cat "outputs-$env_name-singapore.json" | \
          jq -r ".[\"$stack_name\"].ApiUrl" 2>/dev/null)
        if [ "$API_URL" != "null" ] && [ ! -z "$API_URL" ]; then
            echo "🌐 API URL: $API_URL"

            # Test the endpoint
            echo "πŸ§ͺ Testing Singapore endpoint..."
            RESPONSE=$(curl -s "$API_URL" 2>/dev/null)
            if echo "$RESPONSE" | grep -q "Singapore"; then
                echo "βœ… Singapore endpoint test successful"
                echo "πŸ‡ΈπŸ‡¬ Response includes Singapore metadata"
            else
                echo "⚠️  Endpoint test failed or missing Singapore metadata"
            fi
        fi
    else
        echo "❌ Failed to deploy $stack_name to Singapore"
        return 1
    fi

    echo ""
}

# Deploy to each environment in Singapore (dev -> staging -> shared -> prod)
echo "🎯 Starting Singapore deployments..."

deploy_to_account "dev" $DEV_ACCOUNT
deploy_to_account "staging" $STAGING_ACCOUNT
deploy_to_account "shared" $SHARED_ACCOUNT
deploy_to_account "prod" $PROD_ACCOUNT

echo "πŸŽ‰ All applications deployed successfully to Singapore!"
echo ""
echo "πŸ“Š Deployment Summary (Singapore):"
echo "β”œβ”€β”€ Development: HelloWorld-dev"
echo "β”œβ”€β”€ Staging: HelloWorld-staging"
echo "β”œβ”€β”€ Shared Services: HelloWorld-shared"
echo "└── Production: HelloWorld-prod"
echo ""
echo "πŸ”— Access your Singapore applications:"
if [ -f "outputs-dev-singapore.json" ]; then
    echo "β”œβ”€β”€ Dev: $(cat outputs-dev-singapore.json | \\
          jq -r '.["HelloWorld-dev"].ApiUrl' 2>/dev/null)"
fi
if [ -f "outputs-staging-singapore.json" ]; then
    echo "β”œβ”€β”€ Staging: $(cat outputs-staging-singapore.json | \\
          jq -r '.["HelloWorld-staging"].ApiUrl' 2>/dev/null)"
fi
if [ -f "outputs-shared-singapore.json" ]; then
    echo "β”œβ”€β”€ Shared: $(cat outputs-shared-singapore.json | \\
          jq -r '.["HelloWorld-shared"].ApiUrl' 2>/dev/null)"
fi
if [ -f "outputs-prod-singapore.json" ]; then
    echo "└── Prod: $(cat outputs-prod-singapore.json | \\
          jq -r '.["HelloWorld-prod"].ApiUrl' 2>/dev/null)"
fi

echo ""
echo "πŸ‡ΈπŸ‡¬ Singapore Compliance Features:"
echo "β”œβ”€β”€ Data residency: ap-southeast-1 only"
echo "β”œβ”€β”€ PDPA compliance: Enabled for prod/staging/shared"
echo "β”œβ”€β”€ MAS compliance: Enabled for prod"
echo "β”œβ”€β”€ CSA certification: Enabled for prod/shared"
echo "β”œβ”€β”€ MTCS Level-3: AWS Singapore certified"
echo "└── Local timezone: Asia/Singapore"

Phase 7: Enhanced Control Tower Stack (Singapore 2025)

7.1 Control Tower Stack with Dev/Staging/Prod Structure

Create lib/stacks/control-tower-stack.ts:

import { Stack, StackProps, CfnOutput, Aspects } from "aws-cdk-lib";
import { Construct } from "constructs";
import {
  CfnLandingZone,
  CfnEnabledControl,
} from "aws-cdk-lib/aws-controltower";
import {
  CfnAccount,
  CfnOrganization,
  CfnOrganizationalUnit,
} from "aws-cdk-lib/aws-organizations";
import { ACCOUNTS, CORE_ACCOUNTS } from "../config/accounts";
import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag";

export class ControlTowerStack extends Stack {
  public readonly accounts: Record<string, CfnAccount> = {};
  public readonly landingZone: CfnLandingZone;

  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Add CDK-nag for security compliance
    Aspects.of(this).add(new AwsSolutionsChecks({ verbose: true }));

    // βœ… UPDATED 2025: IAM Identity Center is now automatically set up
    // during Control Tower deployment

    // Create Control Tower Landing Zone using L1 constructs
    // (Singapore optimized)
    this.landingZone = new CfnLandingZone(this, "ControlTowerLandingZone", {
      version: "3.3", // Latest version as of 2025
      manifest: {
        // Enhanced manifest for Singapore 2025 best practices
        governedRegions: [
          "ap-southeast-1", "ap-southeast-2"
        ], // Singapore + Sydney for DR
        organizationStructure: {
          security: {
            name: "Security",
          },
          sandbox: {
            name: "Workloads",
          },
        },
        centralizedLogging: {
          accountId: "LOG_ARCHIVE", // Will be resolved by Control Tower
          configurations: {
            loggingBucket: {
              retentionConfiguration: {
                retentionPeriod: 2555, // 7 years for Singapore compliance
              },
            },
            accessLoggingBucket: {
              retentionConfiguration: {
                retentionPeriod: 365, // 1 year for access logs
              },
            },
          },
        },
        securityConfiguration: {
          accountId: "AUDIT",
        },
        accessManagement: {
          enabled: true, // IAM Identity Center automatically configured
        },
        // 2025 enhancement: Additional security controls for Singapore
        kmsConfiguration: {
          kmsEncryption: true,
        },
        // Singapore data residency controls
        dataResidencyControls: {
          enabled: true,
          regions: ["ap-southeast-1"], // Restrict to Singapore only
          // for sensitive data
        },
      },
      tags: [
        { key: "ManagedBy", value: "CDK" },
        { key: "Version", value: "2025.1" },
        { key: "Environment", value: "Management" },
        { key: "Region", value: "ap-southeast-1" },
        { key: "Country", value: "Singapore" },
        { key: "DataResidency", value: "Singapore" },
        { key: "ComplianceFramework", value: "PDPA-MAS-CSA" },
      ],
    });

    // Create Organizational Units with enhanced structure for dev/staging/prod
    const securityOU = new CfnOrganizationalUnit(this, "SecurityOU", {
      name: "Security",
      parentId: "ROOT", // Will be replaced with actual root ID
      tags: [
        { key: "Purpose", value: "Security" },
        { key: "ManagedBy", value: "CDK" },
        { key: "DataResidency", value: "Singapore" },
      ],
    });

    const workloadsOU = new CfnOrganizationalUnit(this, "WorkloadsOU", {
      name: "Workloads",
      parentId: "ROOT",
      tags: [
        { key: "Purpose", value: "Application-Workloads" },
        { key: "ManagedBy", value: "CDK" },
        { key: "DataResidency", value: "Singapore" },
      ],
    });

    // Create production and non-production sub-OUs
    const prodOU = new CfnOrganizationalUnit(this, "ProductionOU", {
      name: "Production",
      parentId: workloadsOU.ref,
      tags: [
        { key: "Environment", value: "Production" },
        { key: "CriticalityLevel", value: "High" },
        { key: "DataResidency", value: "Singapore" },
        { key: "PDPACompliant", value: "true" },
      ],
    });

    const nonProdOU = new CfnOrganizationalUnit(this, "NonProductionOU", {
      name: "NonProduction",
      parentId: workloadsOU.ref,
      tags: [
        { key: "Environment", value: "NonProduction" },
        { key: "CriticalityLevel", value: "Medium" },
        { key: "DataResidency", value: "Singapore" },
      ],
    });

    // Create workload accounts using Organizations API with proper
    // dev/staging/prod placement
    Object.entries(ACCOUNTS).forEach(([key, config]) => {
      // Production account goes to Production OU, dev and staging
      // go to NonProduction OU
      const parentOU =
        config.environment === "prod"
          ? prodOU.ref
          : config.environment === "shared"
            ? prodOU.ref // Shared services treated as production
            : nonProdOU.ref;

      this.accounts[key] = new CfnAccount(this, `${key}Account`, {
        accountName: config.name,
        email: config.email,
        parentIds: [parentOU],
        tags: [
          { key: "Environment", value: config.environment },
          { key: "ManagedBy", value: "CDK" },
          { key: "Project", value: "ControlTowerSingapore2025" },
          {
            key: "CostCenter",
            value:
              config.environment === "prod"
                ? "Production"
                : config.environment === "staging"
                  ? "PreProduction"
                  : "Development",
          },
          { key: "ComplianceLevel", value: config.complianceLevel },
          {
            key: "BillingThreshold",
            value: config.billingThreshold.toString(),
          },
          { key: "Region", value: "ap-southeast-1" },
          { key: "Country", value: "Singapore" },
          { key: "DataResidency", value: "Singapore" },
          { key: "PDPACompliant", value: config.pdpaCompliant.toString() },
          { key: "MASCompliant", value: config.masCompliant.toString() },
          { key: "CSACertified", value: config.csaCertified.toString() },
        ],
      });

      // Add dependency on Landing Zone and OUs
      this.accounts[key].addDependency(this.landingZone);
      this.accounts[key].addDependency(parentOU);
    });

    // Enhanced Control Tower controls for Singapore 2025 compliance
    const securityControls = [
      // Data protection controls (PDPA compliance)
      "AWS-GR_EBS_OPTIMIZED_INSTANCE",
      "AWS-GR_ENCRYPTED_VOLUMES",
      "AWS-GR_EBS_SNAPSHOT_PUBLIC_READ_PROHIBITED",

      // Network security controls (CSA requirements)
      "AWS-GR_SUBNET_AUTO_ASSIGN_PUBLIC_IP_DISABLED",
      "AWS-GR_VPC_DEFAULT_SECURITY_GROUP_CLOSED",

      // IAM security controls (MAS compliance)
      "AWS-GR_ROOT_ACCESS_KEY_CHECK",
      "AWS-GR_MFA_ENABLED_FOR_ROOT",
      "AWS-GR_STRONG_PASSWORD_POLICY",

      // Monitoring and logging (audit requirements)
      "AWS-GR_CLOUDTRAIL_ENABLED",
      "AWS-GR_CLOUDWATCH_EVENTS_ENABLED",

      // Cost optimization controls
      "AWS-GR_LAMBDA_FUNCTION_PUBLIC_READ_PROHIBITED",
      "AWS-GR_S3_BUCKET_PUBLIC_READ_PROHIBITED",

      // Singapore data residency controls
      "AWS-GR_REGION_DENY", // Prevents deployment outside ap-southeast-1
    ];

    securityControls.forEach((controlId, index) => {
      new CfnEnabledControl(this, `Control${index}`, {
        controlIdentifier: controlId,
        targetIdentifier: workloadsOU.ref,
      });
    });

    // Output account information with enhanced Singapore metadata
    Object.entries(ACCOUNTS).forEach(([key, config]) => {
      new CfnOutput(this, `${key}AccountId`, {
        value: this.accounts[key].ref,
        description: `Account ID for ${config.name} environment ` +
          `(${config.environment}) - Singapore`,
        exportName: `AccountId-${key}-sg`,
      });

      new CfnOutput(this, `${key}AccountEmail`, {
        value: config.email,
        description: `Email for ${config.name} account - Singapore`,
        exportName: `AccountEmail-${key}-sg`,
      });
    });

    // Control Tower metadata outputs
    new CfnOutput(this, "ControlTowerLandingZoneId", {
      value: this.landingZone.ref,
      description: "Control Tower Landing Zone ID - Singapore",
    });

    new CfnOutput(this, "ControlTowerVersion", {
      value: "3.3",
      description: "Control Tower version deployed",
    });

    new CfnOutput(this, "HomeRegion", {
      value: "ap-southeast-1",
      description: "Control Tower home region (Singapore)",
    });

    new CfnOutput(this, "ManagementAccountEmail", {
      value: CORE_ACCOUNTS.management,
      description: "Management account email",
    });

    new CfnOutput(this, "AuditAccountEmail", {
      value: CORE_ACCOUNTS.audit,
      description: "Audit account email",
    });

    new CfnOutput(this, "LogArchiveAccountEmail", {
      value: CORE_ACCOUNTS.logArchive,
      description: "Log Archive account email",
    });

    // CDK-nag suppressions for Control Tower specific requirements
    NagSuppressions.addResourceSuppressions(
      this,
      [
        {
          id: "AwsSolutions-CT1",
          reason:
            "Control Tower Landing Zone requires specific configuration " +
            "that may not align with all rules",
        },
        {
          id: "AwsSolutions-ORG1",
          reason:
            "Organizations structure is designed for Control Tower compliance",
        },
      ],
      true,
    );
  }
}

Phase 8: Enhanced Validation Script for Dev/Staging/Prod

8.1 Comprehensive Singapore Validation Script

Create scripts/validate-deployment-singapore.sh:

#!/bin/bash

echo "πŸ” Comprehensive Singapore Deployment Validation (2025 Edition)"
echo "==============================================================="

# Load environment variables
source .env 2>/dev/null || echo "⚠️  .env file not found, some checks may fail"

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Function to print colored output
print_status() {
    local status="$1"
    local message="$2"

    case $status in
        "success") echo -e "${GREEN}βœ… $message${NC}" ;;
        "warning") echo -e "${YELLOW}⚠️  $message${NC}" ;;
        "error") echo -e "${RED}❌ $message${NC}" ;;
        "info") echo -e "${BLUE}ℹ️  $message${NC}" ;;
        "singapore") echo -e "\033[0;35mπŸ‡ΈπŸ‡¬ $message${NC}" ;;
    esac
}

# 1. Check Environment and Singapore Region
echo "πŸ“‹ 1. Checking Singapore Environment..."
CDK_VERSION=$(cdk --version 2>/dev/null)
NODE_VERSION=$(node --version 2>/dev/null)
CURRENT_REGION=$(aws configure get region)

if echo "$CDK_VERSION" | grep -q "2\."; then
    print_status "success" "CDK Version: $CDK_VERSION (CDK v2 βœ“)"
else
    print_status "error" "CDK Version: $CDK_VERSION (Expected CDK v2)"
fi

if echo "$NODE_VERSION" | grep -qE "v(20|22)\."; then
    print_status "success" \
      "Node.js Version: $NODE_VERSION (Singapore 2025 compatible βœ“)"
elif echo "$NODE_VERSION" | grep -q "v18\."; then
    print_status "warning" \
      "Node.js Version: $NODE_VERSION (Will be deprecated Nov 30, 2025)"
else
    print_status "error" \
      "Node.js Version: $NODE_VERSION (Need 20+ for Singapore deployment)"
fi

if [ "$CURRENT_REGION" = "ap-southeast-1" ]; then
    print_status "singapore" "Region: $CURRENT_REGION (Singapore βœ“)"
else
    print_status "warning" \
      "Region: $CURRENT_REGION (Should be ap-southeast-1 for Singapore)"
fi

# 2. Check Singapore Account Structure
echo ""
echo "πŸ“‹ 2. Checking Singapore Account Structure..."

ACCOUNT_COUNT=$(aws organizations list-accounts \\
    --query 'Accounts[?Status==`ACTIVE`] | length(@)' \\
    --output text 2>/dev/null)
if [ "$ACCOUNT_COUNT" -ge 3 ]; then
    print_status "singapore" "Active Accounts: $ACCOUNT_COUNT"

    echo ""
    print_status "info" "Singapore Account Details:"
    aws organizations list-accounts \\
        --query 'Accounts[?Status==`ACTIVE`].[Name,Email,Id]' \\
        --output table 2>/dev/null
else
    print_status "warning" \
      "Active Accounts: $ACCOUNT_COUNT (Expected 7+ for full Singapore setup)"
fi

# 3. Test Hello World Applications in Singapore (Dev/Staging/Prod)
echo ""
echo "πŸ“‹ 3. Testing Hello World Applications in Singapore..."

environments=("dev" "staging" "shared" "prod")
declare -A env_names=(
    ["dev"]="Development"
    ["staging"]="Staging"
    ["shared"]="Shared Services"
    ["prod"]="Production"
)

declare -A env_priorities=(
    ["dev"]="Low"
    ["staging"]="Medium"
    ["shared"]="High"
    ["prod"]="Critical"
)

for env in "${environments[@]}"; do
    echo ""
    print_status "info" "Testing $env environment (${env_names[$env]}) - " \\
        "Priority: ${env_priorities[$env]}..."

    # Get API URL from Singapore outputs file or CloudFormation
    API_URL=""
    if [ -f "outputs-$env-singapore.json" ]; then
        API_URL=$(cat "outputs-$env-singapore.json" | \\
            jq -r ".\"HelloWorld-$env\".ApiUrl" 2>/dev/null)
    fi

    if [ -z "$API_URL" ] || [ "$API_URL" = "null" ]; then
        API_URL=$(aws cloudformation describe-stacks \
            --stack-name "HelloWorld-$env" \
            --query 'Stacks[0].Outputs[?OutputKey==`ApiUrl`].OutputValue' \
            --output text \
            --region ap-southeast-1 2>/dev/null)
    fi

    if [ ! -z "$API_URL" ] && [ "$API_URL" != "None" ]; then
        print_status "info" "API URL: $API_URL"

        # Test main endpoint
        RESPONSE=$(curl -s --max-time 10 "$API_URL" 2>/dev/null)
        if echo "$RESPONSE" | grep -q "Singapore"; then
            print_status "singapore" \
              "Main endpoint working with Singapore metadata βœ“"

            # Extract Singapore-specific data
            REGION_FROM_RESPONSE=$(echo "$RESPONSE" | \
              jq -r '.location.country' 2>/dev/null)
            if [ "$REGION_FROM_RESPONSE" = "Singapore" ]; then
                print_status "singapore" \
                  "Singapore location validation passed βœ“"
            else
                print_status "warning" \
                  "Singapore location validation failed: " \\
                    "got $REGION_FROM_RESPONSE"
            fi

            # Check compliance flags based on environment
            PDPA_COMPLIANT=$(echo "$RESPONSE" | \
              jq -r '.features.pdpaCompliant' 2>/dev/null)
            MAS_COMPLIANT=$(echo "$RESPONSE" | \
              jq -r '.features.masCompliant' 2>/dev/null)
            CSA_CERTIFIED=$(echo "$RESPONSE" | \
              jq -r '.features.csaCertified' 2>/dev/null)

            # Validate compliance settings per environment
            case $env in
                "prod")
                    if [ "$PDPA_COMPLIANT" = "true" ]; then
                        print_status "singapore" "PDPA compliance: Enabled βœ“"
                    else
                        print_status "error" \
                          "PDPA compliance should be enabled for production"
                    fi

                    if [ "$MAS_COMPLIANT" = "true" ]; then
                        print_status "singapore" "MAS compliance: Enabled βœ“"
                    else
                        print_status "warning" \
                          "MAS compliance: $MAS_COMPLIANT " \\
                            "(consider enabling for production)"
                    fi

                    if [ "$CSA_CERTIFIED" = "true" ]; then
                        print_status "singapore" "CSA certification: Enabled βœ“"
                    else
                        print_status "warning" \
                          "CSA certification: $CSA_CERTIFIED " \\
                            "(consider enabling for production)"
                    fi
                    ;;
                "staging")
                    if [ "$PDPA_COMPLIANT" = "true" ]; then
                        print_status "singapore" \
                          "PDPA compliance: Enabled (staging) βœ“"
                    else
                        print_status "warning" \
                          "PDPA compliance: $PDPA_COMPLIANT " \\
                            "(consider enabling for staging)"
                    fi

                    print_status "info" \
                      "MAS compliance: $MAS_COMPLIANT (staging environment)"
                    print_status "info" \
                      "CSA certification: $CSA_CERTIFIED (staging environment)"
                    ;;
                "shared")
                    if [ "$PDPA_COMPLIANT" = "true" ]; then
                        print_status "singapore" \
                          "PDPA compliance: Enabled (shared services) βœ“"
                    else
                        print_status "warning" \\
                            "PDPA compliance should be enabled for " \
                            "shared services"
                    fi

                    if [ "$CSA_CERTIFIED" = "true" ]; then
                        print_status "singapore" \
                          "CSA certification: Enabled (shared services) βœ“"
                    else
                        print_status "warning" \
                          "CSA certification: $CSA_CERTIFIED"
                    fi
                    ;;
                "dev")
                    print_status "info" \
                      "PDPA compliance: $PDPA_COMPLIANT (dev environment)"
                    print_status "info" \
                      "MAS compliance: $MAS_COMPLIANT (dev environment)"
                    print_status "info" \
                      "CSA certification: $CSA_CERTIFIED (dev environment)"
                    ;;
            esac

            # Check if using Node.js 22
            RUNTIME=$(echo "$RESPONSE" | jq -r '.runtime' 2>/dev/null)
            if [ "$RUNTIME" = "nodejs22.x" ]; then
                print_status "success" "Runtime: $RUNTIME (2025 standard βœ“)"
            else
                print_status "warning" \
                  "Runtime: $RUNTIME (should be nodejs22.x for 2025)"
            fi

            # Environment-specific memory and performance checks
            MEMORY_LIMIT=$(echo "$RESPONSE" | \
              jq -r '.metadata.memoryLimit' 2>/dev/null)
            case $env in
                "prod")
                    if [ "$MEMORY_LIMIT" = "512" ]; then
                        print_status "success" \
                          "Memory: ${MEMORY_LIMIT}MB (production optimized βœ“)"
                    else
                        print_status "warning" "Memory: ${MEMORY_LIMIT}MB " \\
                            "(expected 512MB for production)"
                    fi
                    ;;
                "staging")
                    if [ "$MEMORY_LIMIT" = "384" ]; then
                        print_status "success" \
                          "Memory: ${MEMORY_LIMIT}MB (staging optimized βœ“)"
                    else
                        print_status "info" \
                          "Memory: ${MEMORY_LIMIT}MB (staging environment)"
                    fi
                    ;;
                "dev")
                    if [ "$MEMORY_LIMIT" = "256" ]; then
                        print_status "success" \
                          "Memory: ${MEMORY_LIMIT}MB (dev cost-optimized βœ“)"
                    else
                        print_status "info" \
                          "Memory: ${MEMORY_LIMIT}MB (dev environment)"
                    fi
                    ;;
            esac

        else
            print_status "error" \
              "Main endpoint test failed or missing Singapore metadata"
            print_status "info" "Response: ${RESPONSE:0:100}..."
        fi

        # Test health endpoint
        HEALTH_URL="${API_URL%/}/health"
        HEALTH_RESPONSE=$(curl -s --max-time 10 "$HEALTH_URL" 2>/dev/null)
        if echo "$HEALTH_RESPONSE" | grep -q "Singapore"; then
            print_status "singapore" \
              "Health endpoint working with Singapore data βœ“"
        else
            print_status "warning" \
              "Health endpoint test failed or missing Singapore data"
        fi

        # Test info endpoint for Singapore debugging
        INFO_URL="${API_URL%/}/info"
        INFO_RESPONSE=$(curl -s --max-time 10 "$INFO_URL" 2>/dev/null)
        if echo "$INFO_RESPONSE" | grep -q "Singapore"; then
            print_status "singapore" \
              "Info endpoint working with Singapore metadata βœ“"

            # Validate Singapore-specific configuration
            SG_DATA_RESIDENCY=$(echo "$INFO_RESPONSE" | \\
                jq -r '.singapore.dataResidency' 2>/dev/null)
            if [ "$SG_DATA_RESIDENCY" = "ap-southeast-1" ]; then
                print_status "singapore" \
                  "Data residency compliance: Singapore βœ“"
            else
                print_status "warning" "Data residency: $SG_DATA_RESIDENCY"
            fi

        else
            print_status "warning" \
              "Info endpoint test failed or missing Singapore metadata"
        fi

    else
        print_status "error" \
          "Stack not found or not deployed: HelloWorld-$env in Singapore"
    fi
done

# Summary for Dev/Staging/Prod deployment
echo ""
echo "🎯 Singapore Dev/Staging/Prod Validation Summary"
echo "==============================================="
print_status "info" \
  "Validation completed at $(date) ($(TZ=Asia/Singapore date))"

echo ""
echo "πŸ“Š Environment Summary:"
echo "β”œβ”€β”€ πŸ”§ Development: Cost-optimized, basic security"
echo "β”œβ”€β”€ πŸ§ͺ Staging: Pre-production testing, enhanced security"
echo "β”œβ”€β”€ πŸ”§ Shared Services: Production-grade, shared resources"
echo "└── πŸš€ Production: Full compliance, maximum security"

echo ""
echo "πŸ’‘ Next Steps:"
echo "β”œβ”€β”€ πŸ”— Access your Singapore Hello World applications using the URLs above"
echo "β”œβ”€β”€ πŸ“Š Monitor costs per environment in AWS Cost Explorer"
echo "β”œβ”€β”€ πŸ”’ Review security findings in Singapore Security Hub"
echo "β”œβ”€β”€ πŸ“ˆ Check application metrics in Singapore CloudWatch"
echo "β”œβ”€β”€ 🌏 Verify data residency compliance (ap-southeast-1)"
echo "β”œβ”€β”€ πŸ”„ Set up CI/CD pipeline: dev β†’ staging β†’ prod"
echo "└── πŸš€ Deploy additional applications using Singapore patterns"

echo ""
echo "πŸŽ‰ Your Singapore AWS Control Tower + CDK v2 deployment is ready!"
echo ""
echo "πŸ“š Key Singapore Features Deployed:"
echo "β”œβ”€β”€ βœ… Modern CDK v2 with aws-cdk-lib (Singapore region)"
echo "β”œβ”€β”€ βœ… Node.js 22 Lambda runtime (2025 standard)"
echo "β”œβ”€β”€ βœ… HTTP API Gateway (cost optimized for Singapore)"
echo "β”œβ”€β”€ βœ… ARM64 Lambda architecture (cost optimized)"
echo "β”œβ”€β”€ βœ… Dev/Staging/Prod environment structure"
echo "β”œβ”€β”€ βœ… Environment-specific resource sizing"
echo "β”œβ”€β”€ βœ… Graduated compliance controls"
echo "β”œβ”€β”€ βœ… Singapore data residency controls"
echo "└── βœ… Singapore timezone and currency support"

echo ""
echo "πŸ‡ΈπŸ‡¬ Singapore Compliance Status by Environment:"
echo "β”œβ”€β”€ πŸš€ Production: Full PDPA + MAS + CSA compliance"
echo "β”œβ”€β”€ πŸ§ͺ Staging: PDPA compliance, pre-production testing"
echo "β”œβ”€β”€ πŸ”§ Shared: PDPA + CSA compliance, shared resources"
echo "β”œβ”€β”€ πŸ’» Development: Minimal compliance, cost-optimized"
echo "β”œβ”€β”€ πŸ›οΈ  Data Residency: ap-southeast-1 (Singapore) βœ“"
echo "β”œβ”€β”€ ⏰ Local Time: Asia/Singapore timezone"
echo "└── πŸ’° Currency: SGD cost tracking"

Phase 9: Complete Command Sequence (Singapore 2025)

9.1 Full Singapore Deployment Script with Dev/Staging/Prod

Create scripts/complete-setup-singapore.sh:

#!/bin/bash

set -e

echo "πŸš€ Complete Singapore AWS Control Tower + CDK v2 Setup (2025 Edition)"
echo "====================================================================="
echo "πŸ—οΈ  Environment Structure: Development β†’ Staging β†’ Production"
echo ""

# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m'

print_step() {
    echo -e "${BLUE}$1${NC}"
}

print_success() {
    echo -e "${GREEN}βœ… $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠️  $1${NC}"
}

print_error() {
    echo -e "${RED}❌ $1${NC}"
}

print_singapore() {
    echo -e "${PURPLE}πŸ‡ΈπŸ‡¬ $1${NC}"
}

# Step 1: Prerequisites for Singapore
print_step "πŸ“‹ Step 1: Checking Prerequisites for Singapore..."

# Check Node.js version
NODE_VERSION=$(node --version)
if echo "$NODE_VERSION" | grep -qE "v(20|22)\."; then
    print_success "Node.js version: $NODE_VERSION (Singapore 2025 compatible)"
else
    print_error "Node.js version $NODE_VERSION not supported. " \\
        "Need v20+ or v22+ for Singapore deployment"
    echo "Install Node.js 22: https://nodejs.org/"
    exit 1
fi

# Check AWS CLI
AWS_VERSION=$(aws --version 2>/dev/null | cut -d' ' -f1 | cut -d'/' -f2)
if [[ "$AWS_VERSION" > "2.15" ]]; then
    print_success "AWS CLI version: $AWS_VERSION"
else
    print_error \
      "AWS CLI version $AWS_VERSION not supported. Need v2.15+ for Singapore deployment"
    exit 1
fi

# Check Singapore region access
aws sts get-caller-identity --region ap-southeast-1 > /dev/null 2>&1
if [ $? -eq 0 ]; then
    print_singapore "Singapore region access: Verified"
else
    print_error "Cannot access Singapore region (ap-southeast-1)"
    exit 1
fi

# Check CDK version
CDK_VERSION=$(cdk --version 2>/dev/null)
if echo "$CDK_VERSION" | grep -q "2\."; then
    print_success "CDK version: $CDK_VERSION"
else
    print_error \
      "CDK version $CDK_VERSION not supported. Need CDK v2 for Singapore deployment"
    exit 1
fi

# Step 2: Project Setup for Singapore
print_step "πŸ“‹ Step 2: Setting up Singapore CDK Project..."

# Check if already in project directory
if [ ! -f "package.json" ]; then
    print_error "Not in CDK project directory. Please run from project root."
    exit 1
fi

# Build project
print_step "πŸ”¨ Building Singapore project..."
npm run build

if [ $? -eq 0 ]; then
    print_success "Project built successfully"
else
    print_error "Project build failed"
    exit 1
fi

# Run tests
print_step "πŸ§ͺ Running Singapore tests..."
npm run test

if [ $? -eq 0 ]; then
    print_success "Tests passed"
else
    print_warning "Some tests failed, continuing with deployment"
fi

# Step 3: CDK Synthesis for Singapore
print_step "πŸ“‹ Step 3: Synthesizing CDK for Singapore..."

npm run synth

if [ $? -eq 0 ]; then
    print_success "CDK synthesis completed for Singapore"
else
    print_error "CDK synthesis failed"
    exit 1
fi

# Step 4: Control Tower Check
print_step "πŸ“‹ Step 4: Checking Control Tower Status in Singapore..."

CT_STATUS=$(aws controltower list-landing-zones \\
    --region ap-southeast-1 \\
    --query 'landingZones[0].status' \\
    --output text 2>/dev/null || echo "NOT_FOUND")

if [ "$CT_STATUS" = "ACTIVE" ]; then
    print_singapore "Control Tower: ACTIVE in Singapore"

    # Get home region
    HOME_REGION=$(aws controltower list-landing-zones \\
        --region ap-southeast-1 \\
        --query 'landingZones[0].deploymentMetadata.homeRegion' \\
        --output text 2>/dev/null)
    if [ "$HOME_REGION" = "ap-southeast-1" ]; then
        print_singapore "Home Region: Singapore (ap-southeast-1) βœ“"
    else
        print_warning "Home Region: $HOME_REGION (expected ap-southeast-1)"
    fi

elif [ "$CT_STATUS" = "NOT_FOUND" ]; then
    print_warning "Control Tower not found in Singapore. Manual setup required:"
    echo ""
    print_singapore "Manual Singapore Control Tower Setup:"
    echo "1. 🌐 Go to: " \
      "https://ap-southeast-1.console.aws.amazon.com/controltower/"
    echo "2. πŸ“‹ Click 'Set up landing zone'"
    echo "3. 🏠 Select home region: Asia Pacific (Singapore) ap-southeast-1"
    echo "4. 🌏 Additional regions: Asia Pacific (Sydney) " \
      "ap-southeast-2 (for DR)"
    echo "5. πŸ“Š Configure logging and monitoring:"
    echo "   - Log Archive Account: testawsrahardjalogs@gmail.com"
    echo "   - Audit Account: testawsrahardjaaudit@gmail.com"
    echo "6. πŸ”’ Enable data residency controls for Singapore compliance"
    echo "7. βœ… Review and click 'Set up landing zone'"
    echo "8. ⏰ Wait 30-45 minutes for completion"
    echo ""
    echo "πŸ”„ Re-run this script after Control Tower setup is complete"
    exit 0
else
    print_error "Control Tower status: $CT_STATUS"
    exit 1
fi

# Step 5: Get Account IDs for Dev/Staging/Prod
print_step "πŸ“‹ Step 5: Getting Singapore Account IDs..."

./scripts/get-account-ids-singapore.sh

if [ $? -eq 0 ]; then
    print_success "Account IDs retrieved successfully"
    source .env
else
    print_error "Failed to get account IDs"
    exit 1
fi

# Step 6: Bootstrap Accounts for Singapore
print_step "πŸ“‹ Step 6: Bootstrapping Singapore Accounts..."

./scripts/bootstrap-accounts-singapore.sh

if [ $? -eq 0 ]; then
    print_success "All accounts bootstrapped successfully"
else
    print_error "Account bootstrap failed"
    exit 1
fi

# Step 7: Deploy Applications to Dev/Staging/Prod
print_step \
  "πŸ“‹ Step 7: Deploying Applications to Singapore (Dev β†’ Staging β†’ Shared β†’ Prod)..."

./scripts/deploy-applications-singapore.sh

if [ $? -eq 0 ]; then
    print_success "All applications deployed successfully to Singapore"
else
    print_error "Application deployment failed"
    exit 1
fi

# Step 8: Validate Deployment
print_step "πŸ“‹ Step 8: Validating Singapore Deployment..."

./scripts/validate-deployment-singapore.sh

if [ $? -eq 0 ]; then
    print_success "Deployment validation completed"
else
    print_warning \
      "Some validation checks failed, but deployment may still be functional"
fi

# Step 9: Final Summary
print_step "πŸ“‹ Step 9: Singapore Deployment Summary"

echo ""
print_singapore "πŸŽ‰ Singapore AWS Control Tower + CDK v2 Setup Complete!"
echo ""
echo "πŸ“Š Environment Structure Deployed:"
echo "β”œβ”€β”€ πŸ’» Development: Cost-optimized, minimal compliance"
echo "β”œβ”€β”€ πŸ§ͺ Staging: Pre-production testing, enhanced security"
echo "β”œβ”€β”€ πŸ”§ Shared Services: Production-grade shared resources"
echo "└── πŸš€ Production: Full compliance, maximum security"
echo ""

echo "πŸ”— Your Singapore Hello World Applications:"
if [ -f "outputs-dev-singapore.json" ]; then
    DEV_URL=$(cat outputs-dev-singapore.json | \
      jq -r '.["HelloWorld-dev"].ApiUrl' 2>/dev/null)
    echo "β”œβ”€β”€ πŸ’» Development: $DEV_URL"
fi
if [ -f "outputs-staging-singapore.json" ]; then
    STAGING_URL=$(cat outputs-staging-singapore.json | \\
        jq -r '.["HelloWorld-staging"].ApiUrl' 2>/dev/null)
    echo "β”œβ”€β”€ πŸ§ͺ Staging: $STAGING_URL"
fi
if [ -f "outputs-shared-singapore.json" ]; then
    SHARED_URL=$(cat outputs-shared-singapore.json | \\
        jq -r '.["HelloWorld-shared"].ApiUrl' 2>/dev/null)
    echo "β”œβ”€β”€ πŸ”§ Shared: $SHARED_URL"
fi
if [ -f "outputs-prod-singapore.json" ]; then
    PROD_URL=$(cat outputs-prod-singapore.json | \\
        jq -r '.["HelloWorld-prod"].ApiUrl' 2>/dev/null)
    echo "└── πŸš€ Production: $PROD_URL"
fi

echo ""
echo "πŸ‡ΈπŸ‡¬ Singapore Compliance Features:"
echo "β”œβ”€β”€ πŸ›οΈ  Data Residency: ap-southeast-1 (Singapore) βœ“"
echo "β”œβ”€β”€ πŸ“‹ PDPA Compliance: Enabled for staging/shared/production"
echo "β”œβ”€β”€ 🏦 MAS Compliance: Enabled for production"
echo "β”œβ”€β”€ πŸ”’ CSA Certification: Enabled for shared/production"
echo "β”œβ”€β”€ πŸ’° Cost Optimization: Environment-specific resource sizing"
echo "β”œβ”€β”€ ⏰ Local Time: Asia/Singapore timezone"
echo "└── πŸ’± Currency: SGD cost tracking"

echo ""
echo "πŸš€ Next Steps:"
echo "1. πŸ”— Test all your Singapore applications using the URLs above"
echo "2. πŸ“Š Set up monitoring and alerting in CloudWatch"
echo "3. πŸ” Review security configurations in Security Hub"
echo "4. πŸ’° Monitor costs by environment in Cost Explorer"
echo "5. πŸ”„ Set up CI/CD pipeline: dev β†’ staging β†’ prod"
echo "6. πŸ“ˆ Add custom business applications to each environment"
echo "7. 🌏 Configure disaster recovery to Sydney (ap-southeast-2)"
echo "8. πŸ“‹ Review compliance settings for your specific requirements"

echo ""
print_singapore "Singapore AWS Control Tower + CDK v2 deployment is ready! πŸŽ‰"

Phase 10: Enhanced Package.json Scripts for Dev/Staging/Prod

10.1 Updated Package.json Scripts

Update package.json to add environment-specific scripts:

{
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "cdk": "cdk",
    "synth": "cdk synth",
    "deploy": "cdk deploy",
    "destroy": "cdk destroy",
    "diff": "cdk diff",
    "lint": "eslint . --ext .ts",
    "lint:fix": "eslint . --ext .ts --fix",
    "security:check": "npm audit --audit-level moderate",
    "cdk:watch": "cdk watch",
    "cdk:hotswap": "cdk deploy --hotswap",
    "validate": "npm run build && npm run test && npm run lint && cdk synth",
    "bootstrap": "cdk bootstrap",
    "doctor": "cdk doctor",
    "singapore:validate": \
      "npm run validate && echo 'Singapore deployment ready'",
    "deploy:dev": "cdk deploy HelloWorld-dev --require-approval never",
    "deploy:staging": "cdk deploy HelloWorld-staging --require-approval never",
    "deploy:prod": "cdk deploy HelloWorld-prod --require-approval never",
    "deploy:shared": "cdk deploy HelloWorld-shared --require-approval never",
    "deploy:all": "npm run deploy:dev && npm run deploy:staging && \\
                   npm run deploy:shared && npm run deploy:prod",
    "destroy:dev": "cdk destroy HelloWorld-dev --force",
    "destroy:staging": "cdk destroy HelloWorld-staging --force",
    "destroy:prod": "cdk destroy HelloWorld-prod --force",
    "destroy:shared": "cdk destroy HelloWorld-shared --force",
    "test:endpoints": "./scripts/validate-deployment-singapore.sh",
    "setup:complete": "./scripts/complete-setup-singapore.sh"
  },
  "devDependencies": {
    "@types/jest": "^29.5.5",
    "@types/node": "^22.0.0",
    "@typescript-eslint/eslint-plugin": "^6.7.2",
    "@typescript-eslint/parser": "^6.7.2",
    "aws-cdk": "2.201.0",
    "eslint": "^8.50.0",
    "jest": "^29.7.0",
    "ts-jest": "^29.1.1",
    "ts-node": "^10.9.1",
    "typescript": "~5.2.2"
  },
  "dependencies": {
    "aws-cdk-lib": "2.201.0",
    "constructs": "^10.3.0",
    "@aws-sdk/client-organizations": "^3.421.0",
    "@aws-sdk/client-sts": "^3.421.0",
    "cdk-nag": "^2.27.138",
    "@taimos/cdk-controltower": "^1.0.0",
    "@pepperize/cdk-organizations": "^0.7.0"
  }
}

Phase 11: Updated CDK App Entry Point

11.1 Main CDK App with Dev/Staging/Prod

Update bin/aws-control-tower-cdk-singapore-2025.ts:

#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { ControlTowerStack } from "../lib/stacks/control-tower-stack";
import { ApplicationStack } from "../lib/stacks/application-stack";
import { ACCOUNTS } from "../lib/config/accounts";
import { ENVIRONMENTS } from "../lib/config/environments";

const app = new cdk.App();

// Deploy Control Tower stack (only once in management account)
const controlTowerStack = new ControlTowerStack(app, "ControlTowerSingapore", {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: "ap-southeast-1", // Singapore
  },
  description:
    "AWS Control Tower Landing Zone for Singapore (2025 Edition) " +
  "with Dev/Staging/Prod structure",
  tags: {
    Project: "ControlTowerSingapore2025",
    Environment: "Management",
    Region: "ap-southeast-1",
    Country: "Singapore",
    DataResidency: "Singapore",
    Structure: "Dev-Staging-Prod",
  },
});

// Deploy application stacks for each environment (dev/staging/shared/prod)
Object.entries(ACCOUNTS).forEach(([key, accountConfig]) => {
  const env = ENVIRONMENTS[key];

  new ApplicationStack(app, `HelloWorld-${key}`, {
    accountConfig: accountConfig,
    env: {
      account:
        process.env[`${key.toUpperCase()}_ACCOUNT_ID`] ||
        process.env.CDK_DEFAULT_ACCOUNT,
      region: "ap-southeast-1", // Singapore
    },
    description: `Hello World application for ${accountConfig.name} ` +
      `environment (Singapore 2025 Edition)`,
    stackName: `HelloWorld-${key}`,
    tags: {
      Project: "HelloWorldSingapore2025",
      Environment: accountConfig.environment,
      Account: accountConfig.name,
      Region: "ap-southeast-1",
      Country: "Singapore",
      DataResidency: "Singapore",
      CostCenter:
        accountConfig.environment === "prod"
          ? "Production"
          : accountConfig.environment === "staging"
            ? "PreProduction"
            : "Development",
      ComplianceLevel: accountConfig.complianceLevel,
      PDPACompliant: accountConfig.pdpaCompliant.toString(),
      MASCompliant: accountConfig.masCompliant.toString(),
      CSACertified: accountConfig.csaCertified.toString(),
      CostOptimization: accountConfig.costOptimizationLevel,
      BillingThreshold: accountConfig.billingThreshold.toString(),
    },
  });
});

// Add global tags for Singapore compliance
cdk.Tags.of(app).add("ManagedBy", "CDK");
cdk.Tags.of(app).add("Version", "2025.1.0");
cdk.Tags.of(app).add("Region", "ap-southeast-1");
cdk.Tags.of(app).add("Country", "Singapore");
cdk.Tags.of(app).add("DataResidency", "Singapore");
cdk.Tags.of(app).add("Timezone", "Asia/Singapore");
cdk.Tags.of(app).add("Currency", "SGD");
cdk.Tags.of(app).add("Structure", "Dev-Staging-Prod");
cdk.Tags.of(app).add("ComplianceFramework", "PDPA-MAS-CSA");

Phase 12: Quick Start Commands

12.1 Quick Setup Commands for Singapore

# πŸš€ Quick Start for Singapore AWS Control Tower + CDK v2 (Dev/Staging/Prod)

# 1. Prerequisites Check
node --version  # Should be v20+ or v22+
aws --version   # Should be v2.15+
cdk --version   # Should be v2.201+

# 2. Project Setup
mkdir aws-control-tower-cdk-singapore-2025
cd aws-control-tower-cdk-singapore-2025
cdk init app --language typescript

# 3. Install Dependencies
npm install aws-cdk-lib@latest constructs@latest
npm install --save-dev cdk-nag@latest @types/node@latest

# 4. Configure Singapore Region
aws configure set region ap-southeast-1

# 5. Bootstrap CDK for Singapore
cdk bootstrap --qualifier "sgcdk2025"

# 6. Manual Control Tower Setup (Required)
# Go to: https://ap-southeast-1.console.aws.amazon.com/controltower/
# Set home region: ap-southeast-1 (Singapore)
# Add regions: ap-southeast-2 (Sydney for DR)
# Configure accounts:
#   - Audit: testawsrahardjaaudit@gmail.com
#   - Log Archive: testawsrahardjalogs@gmail.com

# 7. Create Workload Accounts (via AWS Console)
# - Development: testawsrahardjaa+dev@gmail.com
# - Staging: testawsrahardjaa+staging@gmail.com
# - Production: testawsrahardjaa+prod@gmail.com
# - Shared Services: testawsrahardjaa+shared@gmail.com

# 8. Get Account IDs and Bootstrap
./scripts/get-account-ids-singapore.sh
./scripts/bootstrap-accounts-singapore.sh

# 9. Deploy Applications (Dev β†’ Staging β†’ Shared β†’ Prod)
./scripts/deploy-applications-singapore.sh

# 10. Validate Deployment
./scripts/validate-deployment-singapore.sh

# πŸŽ‰ Your Singapore deployment is ready!

12.2 Environment-Specific Quick Commands

# Development Environment (Cost-Optimized)
npm run deploy:dev
curl $(cat outputs-dev-singapore.json | jq -r '.["HelloWorld-dev"].ApiUrl')

# Staging Environment (Pre-Production Testing)
npm run deploy:staging
curl $(cat outputs-staging-singapore.json | \
  jq -r '.["HelloWorld-staging"].ApiUrl')

# Production Environment (Full Compliance)
npm run deploy:prod
curl $(cat outputs-prod-singapore.json | jq -r '.["HelloWorld-prod"].ApiUrl')

# Shared Services Environment
npm run deploy:shared
curl $(cat outputs-shared-singapore.json | \
  jq -r '.["HelloWorld-shared"].ApiUrl')

# Deploy All Environments at Once
npm run deploy:all

# Test All Endpoints
npm run test:endpoints

# Complete Setup (All Steps)
npm run setup:complete

Summary

This comprehensive guide provides a complete AWS Control Tower + CDK v2 setup for Singapore with a dev/staging/prod environment structure. Key features include:

πŸ—οΈ Environment Structure

  • Development: Cost-optimized, minimal compliance
  • Staging: Pre-production testing, enhanced security
  • Production: Full compliance, maximum security
  • Shared Services: Production-grade shared resources

πŸ‡ΈπŸ‡¬ Singapore-Specific Features

  • Data residency compliance (ap-southeast-1)
  • PDPA compliance for staging/shared/production
  • MAS compliance for production
  • CSA certification for shared/production
  • Singapore timezone and currency support

πŸš€ Modern 2025 Technologies

  • CDK v2.201.0+ with aws-cdk-lib
  • Node.js 22 Lambda runtime
  • HTTP API Gateway (cost-optimized)
  • ARM64 Lambda architecture
  • Enhanced security and observability

πŸ“‹ Compliance & Security

  • Environment-specific compliance settings
  • Graduated security controls
  • Cost optimization per environment
  • Comprehensive monitoring and alerting

The guide maintains the step-by-step structure while updating all references from "test" to "staging" environment, providing a more realistic enterprise deployment pattern for Singapore.

Enhanced CDK Bootstrap

# Bootstrap CDK with modern qualifiers for Singapore region
cdk bootstrap \
  aws://$(aws sts get-caller-identity --query Account --output text)/ap-southeast-1 \\
 --qualifier "cdk2025" \\
  --cloudformation-execution-policies \
  "arn:aws:iam::aws:policy/AdministratorAccess"

Phase 2: Singapore-Specific Account Setup

2.1 Prepare Email Accounts (Pre-configured)

NOTE Your Email Configuration for Singapore:

  • Management Account (Root): testawsrahardjaa@gmail.com βœ…
  • Audit Account: testawsrahardjaaudit@gmail.com βœ…
  • Log Archive Account: testawsrahardjalogs@gmail.com βœ…
  • Production Workload: testawsrahardjaa+prod@gmail.com (Gmail alias)
  • Staging Workload: testawsrahardjaa+staging@gmail.com (Gmail alias)
  • Development Workload: testawsrahardjaa+dev@gmail.com (Gmail alias)
  • Shared Services: testawsrahardjaa+shared@gmail.com (Gmail alias)

2.2 IAM Identity Center Setup (NOW AUTOMATED)

βœ… UPDATED 2025: IAM Identity Center is now automatically set up during Control Tower deployment!

# Check if IAM Identity Center is already enabled
aws sso list-instances --region ap-southeast-1

# If Control Tower hasn't been deployed yet, this will be empty
# Identity Center will be automatically configured during Control Tower setup

2.3 Enhanced Security Setup for Singapore Compliance

# Enable CloudTrail for audit logging (MAS compliance requirement)
aws cloudtrail create-trail \
  --name "PreControlTowerAuditTrail" \
  --s3-bucket-name \
    "pre-ct-audit-$(aws sts get-caller-identity --query Account --output text)" \
  --include-global-service-events \
  --is-multi-region-trail \
  --region ap-southeast-1

# Enable GuardDuty in management account (CSA requirement)
aws guardduty create-detector \
  --enable \
  --finding-publishing-frequency FIFTEEN_MINUTES \
  --region ap-southeast-1

Phase 3: Modern CDK Project Structure

3.1 Initialize Project with 2025 Best Practices

# Create project directory
mkdir aws-control-tower-cdk-singapore-2025
cd aws-control-tower-cdk-singapore-2025

# Initialize TypeScript CDK project with modern template
cdk init app --language typescript

# Wait for initialization
sleep 10

3.2 Install Modern Dependencies (CDK v2.201.0+)

# Install core CDK v2 dependencies
npm install aws-cdk-lib@latest constructs@latest

# Install modern development dependencies
npm install --save-dev \
  @types/node@latest \
  jest@^29.7.0 \
  @types/jest@latest \
  ts-jest@latest \
  eslint@latest \
  @typescript-eslint/eslint-plugin@latest \
  @typescript-eslint/parser@latest

# Install additional CDK utilities for 2025
npm install --save-dev \
  cdk-nag@latest \
  @taimos/cdk-controltower@latest \
  @pepperize/cdk-organizations@latest

# Install AWS SDK v3 for modern patterns
npm install @aws-sdk/client-organizations @aws-sdk/client-sts

# Verify modern package versions
npm list aws-cdk-lib
# Should show 2.201.x or higher

3.3 Create Modern Directory Structure

# Create comprehensive directory structure
mkdir -p lib/{stacks,constructs,config,aspects,utils}
mkdir -p test/{unit,integration}
mkdir -p scripts
mkdir -p docs

# Create all required files
touch lib/config/accounts.ts
touch lib/config/environments.ts
touch lib/constructs/account-baseline.ts
touch lib/constructs/hello-world-app.ts
touch lib/constructs/observability-stack.ts
touch lib/stacks/control-tower-stack.ts
touch lib/stacks/application-stack.ts
touch lib/aspects/security-aspects.ts
touch lib/aspects/cost-optimization-aspects.ts
touch scripts/deploy.sh
touch scripts/validate.sh
touch cdk.context.json

Phase 4: Singapore-Optimized Configuration

4.1 Account Configuration with Singapore Compliance

Create lib/config/accounts.ts:

export interface AccountConfig {
  name: string;
  email: string;
  vpcCidr: string;
  environment: "prod" | "staging" | "dev" | "shared";
  billingThreshold: number;
  helloWorldMessage: string;
  // 2025 Singapore additions
  enableGuardDuty: boolean;
  enableSecurityHub: boolean;
  enableVpcFlowLogs: boolean;
  costOptimizationLevel: "basic" | "standard" | "aggressive";
  complianceLevel: "dev" | "prod";
  pdpaCompliant: boolean; // Singapore PDPA requirement
  masCompliant: boolean; // MAS financial services compliance
  csaCertified: boolean; // CSA cybersecurity certification
}

export const ACCOUNTS: Record<string, AccountConfig> = {
  prod: {
    name: "production",
    email: "testawsrahardjaa+prod@gmail.com",
    vpcCidr: "10.0.0.0/16",
    environment: "prod",
    billingThreshold: 1500, // SGD equivalent
    helloWorldMessage: "Hello from Singapore Production! πŸ‡ΈπŸ‡¬πŸš€",
    enableGuardDuty: true,
    enableSecurityHub: true,
    enableVpcFlowLogs: true,
    costOptimizationLevel: "standard",
    complianceLevel: "prod",
    pdpaCompliant: true,
    masCompliant: true,
    csaCertified: true,
  },
  staging: {
    name: "staging",
    email: "testawsrahardjaa+staging@gmail.com",
    vpcCidr: "10.1.0.0/16",
    environment: "staging",
    billingThreshold: 750,
    helloWorldMessage: "Hello from Singapore Staging Environment! πŸ‡ΈπŸ‡¬πŸ§ͺ",
    enableGuardDuty: true,
    enableSecurityHub: true,
    enableVpcFlowLogs: true,
    costOptimizationLevel: "standard",
    complianceLevel: "prod",
    pdpaCompliant: true,
    masCompliant: false,
    csaCertified: false,
  },
  dev: {
    name: "development",
    email: "testawsrahardjaa+dev@gmail.com",
    vpcCidr: "10.2.0.0/16",
    environment: "dev",
    billingThreshold: 300,
    helloWorldMessage: "Hello from Singapore Development! πŸ‡ΈπŸ‡¬πŸ’»",
    enableGuardDuty: false, // Cost optimization for dev
    enableSecurityHub: false,
    enableVpcFlowLogs: false,
    costOptimizationLevel: "aggressive",
    complianceLevel: "dev",
    pdpaCompliant: false,
    masCompliant: false,
    csaCertified: false,
  },
  shared: {
    name: "shared-services",
    email: "testawsrahardjaa+shared@gmail.com",
    vpcCidr: "10.3.0.0/16",
    environment: "shared",
    billingThreshold: 450,
    helloWorldMessage: "Hello from Singapore Shared Services! πŸ‡ΈπŸ‡¬πŸ”§",
    enableGuardDuty: true,
    enableSecurityHub: true,
    enableVpcFlowLogs: true,
    costOptimizationLevel: "basic",
    complianceLevel: "prod",
    pdpaCompliant: true,
    masCompliant: false,
    csaCertified: true,
  },
};

export const CORE_ACCOUNTS = {
  management: "testawsrahardjaa@gmail.com",
  audit: "testawsrahardjaaudit@gmail.com",
  logArchive: "testawsrahardjalogs@gmail.com",
};

// 2025 Feature: Singapore-optimized environment configuration
export const ENVIRONMENT_CONFIG = {
  regions: {
    primary: "ap-southeast-1", // Singapore
    secondary: "ap-southeast-2", // Sydney for DR
  },
  features: {
    enableCrossRegionBackups: true,
    enableAutomatedPatching: true,
    enableCostOptimization: true,
    enableAdvancedMonitoring: true,
    enablePDPACompliance: true,
    enableMASCompliance: true,
  },
  timezone: "Asia/Singapore",
  currency: "SGD",
};

4.2 Environment-Specific Configuration

Create lib/config/environments.ts:

import { Environment } from "aws-cdk-lib";

export interface EnvironmentConfig extends Environment {
  name: string;
  isProd: boolean;
  enableDeletionProtection: boolean;
  logRetentionDays: number;
  backupRetentionDays: number;
  timezone: string;
}

export const ENVIRONMENTS: Record<string, EnvironmentConfig> = {
  dev: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: "ap-southeast-1", // Singapore
    name: "development",
    isProd: false,
    enableDeletionProtection: false,
    logRetentionDays: 7,
    backupRetentionDays: 7,
    timezone: "Asia/Singapore",
  },
  staging: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: "ap-southeast-1", // Singapore
    name: "staging",
    isProd: false,
    enableDeletionProtection: false,
    logRetentionDays: 14,
    backupRetentionDays: 14,
    timezone: "Asia/Singapore",
  },
  prod: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: "ap-southeast-1", // Singapore
    name: "production",
    isProd: true,
    enableDeletionProtection: true,
    logRetentionDays: 365,
    backupRetentionDays: 90,
    timezone: "Asia/Singapore",
  },
  shared: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: "ap-southeast-1", // Singapore
    name: "shared-services",
    isProd: true,
    enableDeletionProtection: true,
    logRetentionDays: 90,
    backupRetentionDays: 30,
    timezone: "Asia/Singapore",
  },
};

Phase 5: Modern Hello World Application (Singapore 2025)

5.1 Enhanced Hello World Construct

Create lib/constructs/hello-world-app.ts:

import { Construct } from "constructs";
import {
  aws_lambda as lambda,
  aws_apigatewayv2 as apigatewayv2, // Using HTTP API (v2) for cost optimization
  aws_apigatewayv2_integrations as integrations,
  aws_logs as logs,
  aws_xray as xray,
  CfnOutput,
  Duration,
  RemovalPolicy,
} from "aws-cdk-lib";
import { AccountConfig } from "../config/accounts";

export interface HelloWorldAppProps {
  accountConfig: AccountConfig;
}

export class HelloWorldApp extends Construct {
  public readonly api: apigatewayv2.HttpApi;
  public readonly lambda: lambda.Function;

  constructor(scope: Construct, id: string, props: HelloWorldAppProps) {
    super(scope, id);

    const { accountConfig } = props;

    // Create log group with proper retention
    const logGroup = new logs.LogGroup(this, "HelloWorldLogGroup", {
      logGroupName: `/aws/lambda/hello-world-${accountConfig.environment}`,
      retention:
        accountConfig.environment === "prod"
          ? logs.RetentionDays.ONE_YEAR
          : accountConfig.environment === "staging"
            ? logs.RetentionDays.ONE_MONTH
            : logs.RetentionDays.ONE_WEEK,
      removalPolicy:
        accountConfig.environment === "prod"
          ? RemovalPolicy.RETAIN
          : RemovalPolicy.DESTROY,
    });

    // Create Lambda function with Node.js 22 (2025 standard)
    this.lambda = new lambda.Function(this, "HelloWorldFunction", {
      runtime: lambda.Runtime.NODEJS_22_X, // Latest runtime for 2025
      handler: "index.handler",
      code: lambda.Code.fromInline(`
        const { NodeSDK } = require('@opentelemetry/sdk-node');
        const { instrumentations } = \
          require('@opentelemetry/auto-instrumentations-node');
        
        // Modern observability setup
        const sdk = new NodeSDK({
          instrumentations: [instrumentations()]
        });
        
        if (process.env.AWS_LAMBDA_FUNCTION_NAME) {
          sdk.start();
        }

        exports.handler = async (event, context) => {
          console.log('Event received:', JSON.stringify(event, null, 2));
          
          // Enhanced response with Singapore 2025 patterns
          const response = {
            statusCode: 200,
            headers: {
              'Content-Type': 'application/json',
              'Access-Control-Allow-Origin': '*',
              'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
              'Access-Control-Allow-Headers': 'Content-Type, Authorization',
              'X-Environment': '${accountConfig.environment}',
              'X-API-Version': '2025.1',
              'X-Region': 'ap-southeast-1',
              'X-Country': 'Singapore',
              'Cache-Control': 'no-cache, no-store, must-revalidate'
            },
            body: JSON.stringify({
              message: '${accountConfig.helloWorldMessage}',
              environment: '${accountConfig.environment}',
              account: '${accountConfig.name}',
              timestamp: new Date().toISOString(),
              requestId: context.awsRequestId,
              region: process.env.AWS_REGION,
              version: '2025.1.0',
              runtime: 'nodejs22.x',
              location: {
                country: 'Singapore',
                region: 'Asia-Pacific',
                timezone: 'Asia/Singapore',
                currency: 'SGD'
              },
              // Enhanced metadata
              metadata: {
                lambdaVersion: context.functionVersion,
                remainingTime: context.getRemainingTimeInMillis(),
                memoryLimit: context.memoryLimitInMB,
                logGroup: context.logGroupName,
                architecture: process.arch,
                nodeVersion: process.version
              },
              features: {
                observability: 'OpenTelemetry',
                security: 'Enhanced',
                costOptimization: '${accountConfig.costOptimizationLevel}',
                compliance: '${accountConfig.complianceLevel}',
                pdpaCompliant: ${accountConfig.pdpaCompliant},
                masCompliant: ${accountConfig.masCompliant},
                csaCertified: ${accountConfig.csaCertified}
              },
              singapore: {
                dataResidency: 'ap-southeast-1',
                complianceFrameworks: ['PDPA', 'MAS', 'CSA'],
                mtcsLevel3Certified: true
              }
            }, null, 2)
          };
          
          return response;
        };
      `),
      environment: {
        ENVIRONMENT: accountConfig.environment,
        ACCOUNT_NAME: accountConfig.name,
        LOG_LEVEL: accountConfig.environment === "prod" ? "WARN" : "DEBUG",
        ENABLE_XRAY: accountConfig.enableGuardDuty ? "true" : "false",
        AWS_REGION: "ap-southeast-1",
        TIMEZONE: "Asia/Singapore",
        PDPA_COMPLIANT: accountConfig.pdpaCompliant.toString(),
        MAS_COMPLIANT: accountConfig.masCompliant.toString(),
      },
      description: `Hello World Lambda for ${accountConfig.name} ` +
        `environment (Singapore 2025 edition)`,
      timeout: Duration.seconds(30),
      memorySize:
        accountConfig.environment === "prod"
          ? 512
          : accountConfig.environment === "staging"
            ? 384
            : 256,
      logGroup: logGroup,
      // Enhanced security and performance
      reservedConcurrentExecutions:
        accountConfig.environment === "prod"
          ? 10
          : accountConfig.environment === "staging"
            ? 5
            : 2,
      deadLetterQueueEnabled:
        accountConfig.environment === "prod" ||
        accountConfig.environment === "staging",
      tracing: accountConfig.enableGuardDuty
        ? lambda.Tracing.ACTIVE
        : lambda.Tracing.DISABLED,
      insightsVersion: lambda.LambdaInsightsVersion.VERSION_1_0_229_0,
      // 2025 feature: Architecture optimization
      architecture: lambda.Architecture.ARM_64, \
        // Graviton2 for cost optimization
    });

    // Create HTTP API (v2) instead of REST API for cost optimization
    this.api = new apigatewayv2.HttpApi(this, "HelloWorldApi", {
      apiName: `Hello World API - ${accountConfig.environment} - Singapore`,
      description: `Hello World HTTP API for ${accountConfig.name} ` +
        `environment (Singapore 2025 edition)`,
      corsPreflight: {
        allowOrigins: ["*"],
        allowMethods: [
          apigatewayv2.CorsHttpMethod.GET,
          apigatewayv2.CorsHttpMethod.POST,
        ],
        allowHeaders: [
          "Content-Type",
          "X-Amz-Date",
          "Authorization",
          "X-Api-Key",
        ],
        maxAge: Duration.days(1),
      },
      // Enhanced throttling for cost control
      defaultIntegration: new integrations.HttpLambdaIntegration(
        "DefaultIntegration",
        this.lambda,
        {
          payloadFormatVersion: apigatewayv2.PayloadFormatVersion.VERSION_2_0,
        },
      ),
    });

    // Add routes with modern patterns
    this.api.addRoutes({
      path: "/",
      methods: [apigatewayv2.HttpMethod.GET],
      integration: new integrations.HttpLambdaIntegration(
        "RootIntegration",
        this.lambda,
      ),
    });

    // Health check endpoint
    const healthLambda = new lambda.Function(this, "HealthFunction", {
      runtime: lambda.Runtime.NODEJS_22_X,
      handler: "index.handler",
      code: lambda.Code.fromInline(`
        exports.handler = async (event, context) => {
          const healthData = {
            status: 'healthy',
            environment: '${accountConfig.environment}',
            timestamp: new Date().toISOString(),
            uptime: process.uptime(),
            memory: process.memoryUsage(),
            version: '2025.1.0',
            location: {
              region: 'ap-southeast-1',
              country: 'Singapore',
              timezone: 'Asia/Singapore'
            },
            checks: {
              database: 'n/a',
              cache: 'n/a', 
              dependencies: 'healthy',
              compliance: {
                pdpa: ${accountConfig.pdpaCompliant},
                mas: ${accountConfig.masCompliant},
                csa: ${accountConfig.csaCertified}
              }
            }
          };
          
          return {
            statusCode: 200,
            headers: {
              'Content-Type': 'application/json',
              'Cache-Control': 'no-cache',
              'X-Region': 'ap-southeast-1'
            },
            body: JSON.stringify(healthData, null, 2)
          };
        };
      `),
      timeout: Duration.seconds(10),
      architecture: lambda.Architecture.ARM_64,
    });

    this.api.addRoutes({
      path: "/health",
      methods: [apigatewayv2.HttpMethod.GET],
      integration: new integrations.HttpLambdaIntegration(
        "HealthIntegration",
        healthLambda,
      ),
    });

    // Info endpoint for debugging
    const infoLambda = new lambda.Function(this, "InfoFunction", {
      runtime: lambda.Runtime.NODEJS_22_X,
      handler: "index.handler",
      code: lambda.Code.fromInline(`
        exports.handler = async (event, context) => {
          return {
            statusCode: 200,
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              accountConfig: {
                name: '${accountConfig.name}',
                environment: '${accountConfig.environment}',
                vpcCidr: '${accountConfig.vpcCidr}',
                costOptimization: '${accountConfig.costOptimizationLevel}',
                compliance: '${accountConfig.complianceLevel}',
                pdpaCompliant: ${accountConfig.pdpaCompliant},
                masCompliant: ${accountConfig.masCompliant},
                csaCertified: ${accountConfig.csaCertified}
              },
              awsInfo: {
                region: process.env.AWS_REGION,
                accountId: event.requestContext?.accountId || 'unknown',
                runtime: 'nodejs22.x',
                architecture: 'arm64'
              },
              singapore: {
                dataResidency: 'Compliant - ap-southeast-1',
                mtcsLevel3: 'Certified',
                localTime: new Date().toLocaleString('en-SG', {
                  timeZone: 'Asia/Singapore'
                }),
                complianceFrameworks: [
                  'PDPA', 'MAS', 'CSA', 'MTCS-SS584-Level3'
                ]
              },
              requestInfo: {
                sourceIp: event.requestContext?.http?.sourceIp,
                userAgent: event.requestContext?.http?.userAgent,
                requestId: event.requestContext?.requestId,
                domainName: event.requestContext?.domainName
              },
              performance: {
                coldStart: !context.coldStartDetected,
                remainingTime: context.getRemainingTimeInMillis(),
                memoryLimit: context.memoryLimitInMB
              }
            }, null, 2)
          };
        };
      `),
      timeout: Duration.seconds(10),
      architecture: lambda.Architecture.ARM_64,
    });

    this.api.addRoutes({
      path: "/info",
      methods: [apigatewayv2.HttpMethod.GET],
      integration: new integrations.HttpLambdaIntegration(
        "InfoIntegration",
        infoLambda,
      ),
    });

    // Modern CloudFormation outputs
    new CfnOutput(this, "ApiUrl", {
      value: this.api.apiEndpoint,
      description: `Hello World HTTP API URL for ` +
        `${accountConfig.environment} environment (Singapore)`,
      exportName: `HelloWorldApiUrl-${accountConfig.environment}-sg`,
    });

    new CfnOutput(this, "HealthCheckUrl", {
      value: `${this.api.apiEndpoint}/health`,
      description: \
        `Health check URL for ${accountConfig.environment} environment (Singapore)`,
    });

    new CfnOutput(this, "InfoUrl", {
      value: `${this.api.apiEndpoint}/info`,
      description: \
        `Info endpoint URL for ${accountConfig.environment} environment (Singapore)`,
    });

    new CfnOutput(this, "LambdaArn", {
      value: this.lambda.functionArn,
      description: \
        `Lambda function ARN for ${accountConfig.environment} (Singapore)`,
    });
  }
}

Phase 6: Enhanced Deployment Scripts for Dev/Staging/Prod

6.1 Get Account IDs (After Control Tower Setup)

Create scripts/get-account-ids-singapore.sh:

#!/bin/bash

echo "πŸ” Getting account IDs from Singapore Control Tower deployment..."

# Function to get account ID by name
get_account_id() {
    local account_name="$1"
    aws organizations list-accounts \
        --query "Accounts[?Name=='$account_name'].Id" \
        --output text 2>/dev/null
}

# Get account IDs
PROD_ACCOUNT=$(get_account_id "production")
STAGING_ACCOUNT=$(get_account_id "staging")
DEV_ACCOUNT=$(get_account_id "development")
SHARED_ACCOUNT=$(get_account_id "shared-services")

# Store in environment file
cat > .env << EOF
# Singapore Account IDs (generated $(date))
PROD_ACCOUNT_ID=$PROD_ACCOUNT
STAGING_ACCOUNT_ID=$STAGING_ACCOUNT
DEV_ACCOUNT_ID=$DEV_ACCOUNT
SHARED_ACCOUNT_ID=$SHARED_ACCOUNT

# Management account
MANAGEMENT_ACCOUNT_ID=$(aws sts get-caller-identity \
  --query Account --output text)

# Singapore configuration
AWS_REGION=ap-southeast-1
COUNTRY=Singapore
TIMEZONE=Asia/Singapore
CURRENCY=SGD
EOF

echo "πŸ“‹ Singapore Account IDs found:"
echo "β”œβ”€β”€ Management: $(aws sts get-caller-identity \
  --query Account --output text)"
echo "β”œβ”€β”€ Production: $PROD_ACCOUNT"
echo "β”œβ”€β”€ Staging: $STAGING_ACCOUNT"
echo "β”œβ”€β”€ Development: $DEV_ACCOUNT"
echo "└── Shared Services: $SHARED_ACCOUNT"

# Verify accounts are in ACTIVE state
echo ""
echo "πŸ” Verifying account status in Singapore..."
aws organizations list-accounts \
    --query 'Accounts[?Status==`ACTIVE`].[Name,Email,Status,Id]' \
    --output table

echo "πŸ’Ύ Singapore account IDs saved to .env file"
echo "🌏 Region: ap-southeast-1 (Singapore)"

6.2 Enhanced Bootstrap Process for Singapore

Create scripts/bootstrap-accounts-singapore.sh:

#!/bin/bash

# Load environment variables
source .env

echo "πŸ”§ Singapore CDK Bootstrap Process (2025)"
echo "=========================================="

# ⚠️ CRITICAL: Control Tower SCP workaround required
echo "⚠️  IMPORTANT: CDK Bootstrap requires AWSControlTowerExecution role"
echo "πŸ”„ You may need to assume the AWSControlTowerExecution role " \
  "to bootstrap successfully"

# Function to bootstrap account with enhanced security for Singapore
bootstrap_account() {
    local account_id="$1"
    local account_name="$2"

    echo "πŸš€ Bootstrapping $account_name ($account_id) in Singapore..."

    # Enhanced bootstrap with Singapore-specific settings
    cdk bootstrap aws://$account_id/ap-southeast-1 \
        --qualifier "sgcdk2025" \
        --toolkit-stack-name "CDKToolkit-Singapore-2025" \
         --cloudformation-execution-policies \
  "arn:aws:iam::aws:policy/AdministratorAccess" \
        --trust-accounts $MANAGEMENT_ACCOUNT_ID \
        --bootstrap-customer-key \
        --termination-protection \
        --context "@aws-cdk/core:bootstrapQualifier=sgcdk2025" \
        --tags Region=ap-southeast-1 \
        --tags Country=Singapore \
        --tags DataResidency=Singapore \
        --tags ComplianceFramework=PDPA-MAS-CSA

    if [ $? -eq 0 ]; then
        echo "βœ… $account_name bootstrapped successfully in Singapore"
    else
        echo "❌ Failed to bootstrap $account_name"
        echo "πŸ’‘ Try assuming AWSControlTowerExecution role first:"
        echo "   aws sts assume-role \\\\"
        echo "     --role-arn arn:aws:iam::$MANAGEMENT_ACCOUNT_ID:role/" \\
        echo "       AWSControlTowerExecution \\\\"
        echo "     --role-session-name CDKBootstrap"
        return 1
    fi
}

# Bootstrap