The landing zone rolls out its account baseline through CloudFormation StackSets. Which StackSets deploy, and to which accounts, OUs, and regions, is controlled by createStackSet calls in two files under src/stacks/. The StackSet implementations themselves live in src/stacksets/ and are separate from the targeting logic.
For a full inventory of what each StackSet deploys, see the StackSets reference.
The two stack files that control deployment
| File | Governs |
|---|---|
src/stacks/landing-zone-foundation-stack.ts | LogArchiveStackSet, CentralAlertsStackSet, ProvisionManagementStackSet |
src/stacks/landing-zone-account-provisioning-stack.ts | AccountSecurityStackSet, OrganizationSecurityStackSet, CostControlStackSet, CdkBootstrapStackSet, ServiceQuotasStackSet, SecurityHubV2StackSet |
Both files belong to the landing-zone phase and deploy from the landing zone account. Do not edit the StackSet implementation files in src/stacksets/ to change targeting. Only edit the target and regions arguments in the stack files above.
Disabling a StackSet
To disable a StackSet, comment out or remove its createStackSet block from the relevant stack file and redeploy. CloudFormation deletes the StackSet and removes its stack instances from all target accounts.
// Disable CostControlStackSet by commenting out the block:
// landingZone.createStackSet(this, {
// name: 'CostControlStackSet',
// description: 'Set up cost control measures for organization accounts',
// stackSetStack: new CostControlStackSetStack(this, 'CostControlStackSetStack', {
// securityAccountEmail,
// }),
// target: StackSetTarget.fromOrganizationalUnits({
// regions: [this.region],
// organizationalUnits: [orgVars.RootOUId],
// }),
// });
To re-enable it, uncomment the block and redeploy.
Dependencies to respect:
ProvisionManagementStackSetdeclares an explicitdependencies: [logArchiveStackSet, centralAlertsStackSet], so it always deploys after both and the shared StackSet roles stay in place until dependent StackSets are torn down.OrganizationSecurityStackSetconsumes the log archive bucket thatLogArchiveStackSetcreates and the notifications topic thatCentralAlertsStackSetcreates, plus the CloudTrail, IAM, and IAM Access Analyzer delegated-admin registrations owned by the organization phase. KeepLogArchiveStackSetandCentralAlertsStackSetenabled wheneverOrganizationSecurityStackSetis.SecurityHubV2StackSetrelies on the delegated-administrator registrations that the organization phase performs from delegated-admins.ts for Security Hub, GuardDuty, Inspector, and Macie. Because that runs in the earlier organization phase, the phase split enforces the ordering rather than adependenciesentry.SecurityHubV2StackSetowns member association itself: GuardDuty and Macie discover the eligible member accounts from AWS Organizations at deploy time rather than from a passed-in account list, so no workload account IDs need to be published for onboarding.AccountSecurityStackSetcovers member accounts through a service-managed StackSet, while the management account receives the same hardening from theSecureDefaultsConstructinsideProvisionManagementStackSet. Disabling one without the other leaves a gap in coverage.
Changing OU and account targets
Each createStackSet call takes a target that controls where the StackSet deploys. The OU and account IDs come from orgVars, which resolves them cross-account from the LandingZoneOrganizationStack CloudFormation outputs. OU IDs are always available; an account ID is only available as orgVars.<Key>Id when that account sets publishAccountIdOutput: true in organization-structure.ts. Two targeting patterns are available:
Target whole OUs or the root (service-managed):
target: StackSetTarget.fromOrganizationalUnits({
regions: [this.region],
organizationalUnits: [orgVars.RootOUId],
}),
New accounts that join the targeted OU automatically receive the StackSet instance; accounts that leave have it removed. Swap orgVars.RootOUId for any OU ID from your organization structure, for example [orgVars.DevelopmentOUId, orgVars.ProductionOUId] to limit a StackSet to workload accounts only.
Target explicit accounts (self-managed):
target: StackSetTarget.fromAccounts({
regions: [this.region, ...secondaryRegions],
accounts: [orgVars.SecurityAccountId],
}),
Use fromAccounts to deploy to specific accounts by ID. It makes the StackSet self-managed: cdk-stacksets selects this model automatically for direct account targets, because a target list without organization root or OU IDs cannot use the service-managed model. The built-in LogArchiveStackSet, CentralAlertsStackSet, ProvisionManagementStackSet, OrganizationSecurityStackSet, and SecurityHubV2StackSet all target a single account this way.
Any account ID you pass here must be resolvable: the management account comes from settings.managementAccountId, while a landing-zone account ID like orgVars.SecurityAccountId is only available when that account sets publishAccountIdOutput: true in organization-structure.ts. This is the main reason the log archive and security accounts opt into their ID outputs.
Self-managed StackSets are also the only model that can reach the management account (service-managed StackSets cannot), and they need the StackSet IAM roles that LandingZoneFoundationConstruct creates in the foundation stack.
Changing regions
The regions array on each target controls which regions receive a StackSet instance. Most StackSets deploy only to the primary region ([this.region]). Region-sensitive StackSets (secure defaults and central alerts) also cover secondaryRegions from your settings.
To add a region to a specific StackSet:
target: StackSetTarget.fromOrganizationalUnits({
regions: [this.region, ...secondaryRegions, 'ap-southeast-1'],
organizationalUnits: [orgVars.RootOUId],
}),
Adding a region that isn't in landing-zone-settings.ts's secondaryRegions is valid, but the region guardrail SCP may block API calls in that region unless you also add it to secondaryRegions. See Landing Zone Settings for how regions are configured.
Deployment rollout behavior
Each createStackSet call accepts an optional deploymentOptions (StackSetDeploymentOptions), which controls how CloudFormation rolls the StackSet out across its target accounts: concurrency (maxConcurrentAccounts or maxConcurrentAccountsPercentage) and failure tolerance (failureToleranceAccounts or failureToleranceAccountsPercentage). Set at most one count-or-percentage variant per option.
Left unset, a StackSet deploys to every target account at once and stops the whole operation if a single account's deployment fails. AccountSecurityStackSet, CostControlStackSet, CdkBootstrapStackSet, and ServiceQuotasStackSet instead pass a shared fastRolloutDeploymentOptions constant (maxConcurrentAccountsPercentage: 100, failureToleranceAccountsPercentage: 99), so a failure in one account does not stop the rollout to the rest of the organization. Pass your own deploymentOptions to any createStackSet call to change this per StackSet.
Preview and deploy
These StackSets belong to the landing-zone phase, so preview and deploy them from the landing zone account. Preview the diff first:
pnpm run landingzone:diff:all
Then deploy:
pnpm run landingzone:deploy:all
CloudFormation handles adding and removing StackSet instances as the target changes. Removing an OU from a target removes stack instances from all accounts currently in that OU; adding one deploys instances to all accounts already there.