AWS CDK Landing Zone

StackSets

All 9 CloudFormation StackSets in the AWS CDK Landing Zone, with their purpose, resources, deployment targets, and the baseline constructs they compose.

CloudFormation StackSets let a single template deploy simultaneously to multiple accounts and regions. The landing zone uses StackSets to roll out its account baseline, so every account that joins a targeted OU automatically receives the full baseline without manual intervention. Each StackSet composes one or more single-purpose constructs from @towardsthecloud/cdk-landing-zone-constructs into the template it ships.

All landing-zone StackSets are created from the landing zone account, which the organization phase registers as the CloudFormation StackSets delegated administrator. The landing zone uses two permission models:

  • Service-managed (default): CloudFormation manages the required IAM roles and targets OUs directly, running with CallAs: DELEGATED_ADMIN from the landing zone account. New accounts that join a targeted OU receive the StackSet automatically. This model cannot deploy to the management account.
  • Self-managed: used when the target is a specific account rather than an OU. It relies on the StackSet IAM roles the landing zone foundation creates, and it is the only model that can reach the management account.

At a glance

StackSetStackPermissionDeployed to
LogArchiveStackSetFoundationSelf-managedLog archive account, primary region
CentralAlertsStackSetFoundationSelf-managedSecurity account, all configured regions
ProvisionManagementStackSetFoundationSelf-managedManagement account, all configured regions
AccountSecurityStackSetProvisioningService-managedAll member accounts, all configured regions
OrganizationSecurityStackSetProvisioningSelf-managedSecurity account, all configured regions
CostControlStackSetProvisioningService-managedAll member accounts, primary region
CdkBootstrapStackSetProvisioningService-managedDevelopment and Production OUs, all configured regions
ServiceQuotasStackSetProvisioningService-managedDevelopment, Production, and Security OUs, all regions
SecurityHubV2StackSetProvisioningSelf-managedSecurity account, primary region

"Foundation" StackSets deploy from LandingZoneFoundationStack; "Provisioning" StackSets from LandingZoneAccountProvisioningStack. Both stacks run in the landing-zone phase, from the landing zone account. Delegated administration for the security services is registered earlier, in the organization phase, through delegated-admins.ts, so by the time these StackSets run the security account is already the delegated administrator.

Foundation StackSets

LogArchiveStackSet

Creates the centralized CloudTrail storage in the log archive account. Composes raw CDK resources rather than a baseline construct.

ResourceDetails
CloudTrail log S3 bucketcloudtrail-logs-{account}, SSL-only, S3-managed encryption, public access blocked, 365-day expiry
Access logging bucketcloudtrail-access-logs-{account} capturing S3 access logs for the CloudTrail bucket
Bucket policyScoped to the organization trail: writes allowed only for the fixed trail ARN under the AWSLogs/<organizationId>/ and AWSLogs/<managementAccountId>/ key paths, plus read access for the security account's Athena queries

Both buckets use a DESTROY removal policy with object auto-deletion, so removing the StackSet cleans up the storage rather than stranding it.

Target: Log archive account, primary region. Targeted directly by the account's published LogArchiveAccountId output, which makes it self-managed. Deployed by: LandingZoneFoundationStack. Must deploy before ProvisionManagementStackSet.

CentralAlertsStackSet

Creates the centralized CloudTrail notification topic in the security account. The organization trail's CIS alarms publish to this topic.

ResourceDetails
CloudTrail notifications topicEncrypted SNS topic for CloudTrail notifications, subscribed to the security contact email

Composes: EncryptedSNSTopicConstruct. Target: Security account, all configured regions. Targeted directly by the account's published SecurityAccountId output, which makes it self-managed. Deployed by: LandingZoneFoundationStack. Must deploy before ProvisionManagementStackSet.

ProvisionManagementStackSet

Provisions the management account. Service-managed StackSets cannot deploy to the management account, so this self-managed StackSet handles the two things that only reach it this way: the secure-defaults baseline and the optional AWS Organizations account-quota request. Delegated administrator registration is owned by the organization phase; the management account's CloudTrail coverage and its IAM centralized root access both come from the Organization Security StackSet, which runs org-wide from the security account.

ResourceDetails
Secure defaultsDeletes default VPCs, enables EBS encryption, hardens default security groups, configures SSM service settings, sets S3 Block Public Access and password policy
Organizations account quotaWhen organizationAccountLimit is set in settings, requests the AWS Organizations maximum-accounts quota for the account

Composes: SecureDefaultsConstruct and (when organizationAccountLimit is set) IncreaseServiceQuotaConstruct. Target: Management account, all configured regions. Deployed by: LandingZoneFoundationStack, after LogArchiveStackSet and CentralAlertsStackSet.

Account-baseline StackSets

AccountSecurityStackSet

Hardens each member account individually with security settings that have no organization-wide control, in every configured region. It is the per-account counterpart to OrganizationSecurityStackSet, which configures org-wide services once from the security account. It currently applies the secure account defaults; more per-account hardening will be added over time.

ResourceDetails
Default VPC deletionRemoves the default VPC in each region so workloads must use explicitly created VPCs
EBS encryptionEnables EBS encryption by default for all new volumes
Security group hardeningStrips all rules from the default security group of any newly created VPC
SSM service settingsBlocks public sharing of SSM documents and routes automation script logs to CloudWatch
S3 Block Public AccessEnables account-level S3 Block Public Access (global settings region only)
Password policySets the IAM account password policy: 18 characters, 90-day expiry, reuse prevention (global settings region only)

Composes: SecureDefaultsConstruct. Target: All member accounts (root OU), all configured regions. The management account gets the same hardening via ProvisionManagementStackSet. Deployed by: LandingZoneAccountProvisioningStack.

OrganizationSecurityStackSet

Provisions the organization-wide security measures that must run from the security account, which the organization phase registers as the CloudTrail, IAM, and IAM Access Analyzer delegated administrator: the single AWS Organizations CloudTrail trail, IAM centralized root access, and the IAM Access Analyzer organization external access analyzer. One trail covers every account in the organization, including the management account, so there are no per-account trails.

ResourceDetails
Organization trailMulti-region organization trail with log file validation and global service events, covering every account in the organization including the management account
KMS keyRotating key in the security account that encrypts the delivered log files, scoped to the management-account trail ARN
Athena queryingA Glue database (cloudtrail), an Athena cloudtrail_logs table over the log archive bucket, and a cloudtrail workgroup with a local results bucket (30-day expiry)
CIS alarmsThe 14 CIS AWS Foundations Benchmark alarms, publishing to the shared notifications topic. The StackSet enables CloudWatch Logs delivery so the alarms ship by default
Centralized root accessEnables IAM centralized root access for organization member accounts, applied once from the primary region
Access AnalyzerAn IAM Access Analyzer organization external access analyzer, reporting resources shared with principals outside the organization (satisfies Security Hub control IAM.28 / CIS v3.0.0 1.20)

Data events (S3, Lambda, DynamoDB) and CloudTrail Insights are opt-in construct props, disabled by default. The trail sends its logs to the centralized log archive bucket. The organization trail and centralized root access are organization/account global, so their resources are conditioned to the primary region; the external access analyzer is regional and deploys in every configured region.

Composes: OrganizationTrailConstruct, CentralizedRootAccessConstruct, IamAccessAnalyzerConstruct. Target: Security account, all configured regions. Self-managed, targeted by the published SecurityAccountId output. Deployed by: LandingZoneAccountProvisioningStack. Relies on the CloudTrail, IAM, and IAM Access Analyzer delegated-admin registrations owned by the organization phase and the log archive bucket created by the foundation stack.

CostControlStackSet

Sets up cost monitoring in every account with AWS Budgets and Cost Anomaly Detection.

ResourceDetails
AWS BudgetMonthly budget that alerts on actual and forecast spend
Cost Anomaly DetectionMonitor that alerts when an anomaly's total impact reaches 100%
SNS topicEncrypted SNS topic budgets-notifications, subscribed to the security contact email

AWS Budgets does not support cross-account SNS topics, so each account creates its own notification topic.

Composes: BudgetConstruct, CostAnomalyConstruct, EncryptedSNSTopicConstruct. Target: All member accounts (root OU), primary region. Deployed by: LandingZoneAccountProvisioningStack.

CdkBootstrapStackSet

Bootstraps your workload accounts for CDK deployments and keeps the bootstrap assets tidy. The StackSet mirrors the default cdk bootstrap deployment (qualifier hnb659fds) so the CDK CLI and DefaultStackSynthesizer work unchanged in the target accounts, with no synthesizer configuration in your workload apps.

ResourceDetails
CDK bootstrap IAM rolescdk-hnb659fds-cfn-exec-role, -deploy-role, -file-publishing-role, -image-publishing-role, -lookup-role
CDK assets S3 bucketcdk-hnb659fds-assets-{account}-{region}, versioned, SSL-only, stores templates and file assets
CDK assets ECR repositorycdk-hnb659fds-container-assets-{account}-{region}, immutable tags, stores Docker image assets
Bootstrap version SSM/cdk-bootstrap/hnb659fds/version so the CDK CLI can validate the environment
Asset cleanerScheduled Lambda that deletes unreferenced S3 and ECR assets each day

The starter sets assetRemovalPolicy to DESTROY (overriding the construct's RETAIN default), so tearing down the StackSet removes the bootstrap buckets and repositories rather than retaining them.

Things to know:

  • Brownfield accounts: an account that already has a manually created CDKToolkit stack collides on the fixed cdk-hnb659fds-* resource names. Delete the old stack, its cdk-hnb659fds-assets-* bucket, and empty its ECR repository before the StackSet rolls out to that account.
  • Workload OUs only: this StackSet targets the Development and Production OUs, and excludes the landing zone account, since those accounts don't run CDK workloads.

Composes: CdkToolkitConstruct, CdkToolkitCleanerConstruct. Target: Development and Production OUs, all configured regions. Deployed by: LandingZoneAccountProvisioningStack.

ServiceQuotasStackSet

Requests regional service quota increases in each targeted account. Requests are idempotent (the construct skips a request when the same or a higher value is already requested) and asynchronous, so the requested value may not be active immediately after the StackSet deploys.

QuotaServiceRequested valueDefault
Lambda concurrent executions (L-B99A9384)lambda2000On
EC2 Elastic IP addresses (L-0263D0A3)ec210Off (commented out; uncomment to enable)

The quota list is configurable in the StackSet, so you can add your own requests or enable the shipped-but-commented EC2 Elastic IP request. The AWS Organizations account limit is handled separately: when you set organizationAccountLimit in landing-zone-settings.ts, the Provision Management StackSet requests it against the management account instead, since that quota is global rather than per-workload-account.

Composes: IncreaseServiceQuotaConstruct. Target: Development, Production, and Security OUs, all configured regions. Deployed by: LandingZoneAccountProvisioningStack.

SecurityHubV2StackSet

Configures the four organization-wide security services from the security account, which the organization phase has already registered as the delegated administrator for each. A single SecurityHubV2Construct coordinates Security Hub CSPM, GuardDuty, Inspector, and Macie behind one shared IAM role.

ResourceDetails
Security Hub V2 hubThe Security Hub V2 hub, enabled in every configured region, with cross-region aggregation
Security Hub CSPMCentral configuration, the AWS Config service-linked recorder, and the organization standards policy
GuardDutyOrganization auto-enable and protection plans
InspectorThe organization scanning policy for EC2, ECR, Lambda, and code repositories
MacieOrganization auto-enable and automated sensitive data discovery

In the starter defaults, all four services ship wired but disabled (enabled: false on each options block). The delegated-admin registration still happens in the organization phase, so when you're ready to turn a service on, you flip its options block (cspmOptions, guardDutyOptions, inspectorOptions, or macieOptions) in securityhub-v2-stackset-stack.ts and redeploy.

GuardDuty and Macie member onboarding does not depend on published account IDs. When you enable them, they discover the eligible member accounts from AWS Organizations at deploy time and associate them, excluding the delegated administrator, the management account, and Suspended OU accounts, so a workload account never needs publishAccountIdOutput just to be covered.

Composes: SecurityHubV2Construct. Target: Security account, primary region. Deployed by: LandingZoneAccountProvisioningStack. Depends on the organization phase having registered the delegated administrators.