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 | ObservabilityStackSet, ProvisionManagementStackSet, OrganizationSecurityStackSet, FinOpsStackSet |
src/stacks/landing-zone-member-accounts-stack.ts | AccountSecurityStackSet, ResourceExplorerStackSet, CdkBootstrapStackSet, ServiceQuotasStackSet |
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.
Changing security services and quotas
Configure CSPM, GuardDuty, Inspector, and Macie in security-services.ts. Set a service’s enabled option to false to disable that capability while keeping OrganizationSecurityStackSet deployed. Its unified Security Hub V2 hub remains enabled. Removing the entire StackSet is a separate operation with different retention behavior.
Configure workload quota increase requests in service-quotas.ts. Keep an entry’s key when changing its requested value. Removing an entry does not lower a quota already granted.
Disabling a StackSet
To disable a StackSet, comment out or remove its createStackSet block from the relevant stack file and redeploy. CloudFormation removes the StackSet and its stack instances; resources with retention policies can remain. Review the resource retention behavior before deploying the removal.
// Disable ResourceExplorerStackSet by commenting out the block:
// landingZone.createStackSet(this, {
// name: 'ResourceExplorerStackSet',
// description: 'Prepare every member account for AWS Resource Explorer search',
// stackSetStack: new ResourceExplorerStackSetStack(this, 'ResourceExplorerStackSetStack', {
// primaryRegion: this.region,
// enabledRegions: landingZone.regions,
// }),
// deploymentOptions: fastRolloutDeploymentOptions,
// target: LandingZoneStackSetTarget.fromOrganizationalUnits({
// regions: [this.region],
// organizationalUnits: [orgVars.RootOUId],
// excludeAccounts: [orgVars.FinOpsAccountId],
// }),
// });
To re-enable it, uncomment the block and redeploy.
Dependencies to respect:
ObservabilityStackSetruns the organization trail from the observability account, so keep theObservabilityAccountentry in organization-structure.ts and its CloudTrail entry in delegated-admins.ts while it is enabled. Check what the audit logs keep when it is removed in Observability StackSet first.OrganizationSecurityStackSetrequires the IAM, IAM Access Analyzer, and security-service delegated administrators configured in the organization phase. Keep the corresponding entries in delegated-admins.ts while those services are enabled. New workload accounts do not need published IDs for security-service enrollment.FinOpsStackSettargets the FinOps account, so keep theFinOpsAccountentry in organization-structure.ts and its Compute Optimizer, Cost Optimization Hub, and Resource Explorer entries in delegated-admins.ts while it is enabled. Organization enrollment comes fromProvisionManagementStackSet, so keep that StackSet enabled too.ResourceExplorerStackSetskips the FinOps account and the management account, whichFinOpsStackSetandProvisionManagementStackSetcover. Keep those enabled so every account has an index for the FinOps organization view.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: LandingZoneStackSetTarget.fromOrganizationalUnits({
regions: [this.region],
organizationalUnits: [orgVars.RootOUId],
excludeAccounts: [orgVars.FinOpsAccountId],
}),
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. excludeAccounts skips specific accounts inside the targeted OUs, as ResourceExplorerStackSet does for the FinOps account and CdkBootstrapStackSet does for the landing zone account.
Target explicit accounts (self-managed):
target: LandingZoneStackSetTarget.fromAccounts({
regions: landingZone.regions,
accounts: [orgVars.SecurityAccountId],
}),
Use fromAccounts to deploy to specific accounts by ID. Targeting accounts directly makes the StackSet self-managed. The target alone picks the permission model: fromOrganizationalUnits is always service-managed and fromAccounts always self-managed. The built-in ObservabilityStackSet, ProvisionManagementStackSet, OrganizationSecurityStackSet, and FinOpsStackSet 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. A StackSet that targets an account directly needs that account's ID output, so set publishAccountIdOutput: true on every account you target this way.
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. landingZone.regions is the primary Region followed by each entry of secondaryRegions from your settings. AccountSecurityStackSet, CdkBootstrapStackSet, ServiceQuotasStackSet, ProvisionManagementStackSet, and OrganizationSecurityStackSet deploy to all of them. ObservabilityStackSet, FinOpsStackSet, and ResourceExplorerStackSet deploy to the primary Region only ([this.region]).
To add a region to a specific StackSet:
target: LandingZoneStackSetTarget.fromOrganizationalUnits({
regions: [...landingZone.regions, '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, ResourceExplorerStackSet, CdkBootstrapStackSet, and ServiceQuotasStackSet instead pass a shared fastRolloutDeploymentOptions constant (maxConcurrentAccountsPercentage: 100, failureToleranceAccountsPercentage: 10, concurrencyMode: StackSetConcurrencyMode.SOFT_FAILURE_TOLERANCE), so the rollout reaches every account at once and fails only when more than 10% of a Region's accounts fail. 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.