AWS Control Tower: Landing Zone Runbook
AWS Control Tower: Landing Zone Runbook and Generator
Control Tower is the managed multi-account landing zone on top of Organizations. This sheet explains what it builds and why, how the legacy setup (guardrails, Core/Custom OUs, per-account trails, Service Catalog only) differs from the current one (landing zone API and manifest, baselines, controls catalog, AFT), then gives a tickable configuration runbook, operational playbooks, and a generator that turns your parameters into the manifest, the CLI sequence and Terraform.
What a landing zone is
One management account, two shared accounts, an OU tree, a set of StackSets that bake a baseline into every enrolled account, and a policy layer that keeps it that way.
fig 1 · the three accounts Control Tower owns and the baseline it pushes into the ones you enroll
| Component | Lives in | Name you will see | Notes |
|---|---|---|---|
| Organization trail | Management, delivers to Log Archive | aws-controltower-BaselineCloudTrail | since LZ 3.0; member-account trails were removed, add your own if you need per-account trails |
| Log buckets | Log Archive | aws-controltower-logs-{acct}-{region} aws-controltower-s3-access-logs-{acct}-{region} | retention 1 to 15 years set in the manifest; bucket policy denies non-TLS and non-trail writers |
| KMS key for logs | Management (your key) | your alias | optional, recommended; key policy must allow CloudTrail and Config principals before you create the landing zone |
| Config aggregator | Audit | aws-controltower-GuardrailsComplianceAggregator | organization aggregator; the compliance dashboard reads from it |
| Config recorders | every enrolled account, every governed region | aws-controltower-BaselineConfigRecorder | global resources recorded in the home region only since LZ 3.1 |
| StackSets | Management | AWSControlTowerBP-BASELINE-CONFIG, -CLOUDTRAIL, -ROLES, -SERVICE-ROLES, -CLOUDWATCH, AWSControlTowerGuardrailAWS-GR_* | never edit by hand; drift is detected and repaired by baseline reset |
| SCPs | Management, attached to OUs | aws-guardrails-{id} | one SCP per OU for preventive controls, plus the region deny SCP at root |
| IAM roles | every account | AWSControlTowerExecution, AWSControlTowerCloudTrailRole, AWSControlTowerConfigRecorderRole, aws-controltower-ForwardSnsNotificationRole | AWSControlTowerExecution is the admin break-glass path from the management account |
| SNS | Audit, plus per-account forwarders | aws-controltower-AggregateSecurityNotifications, -AllConfigNotifications, -SecurityNotifications | subscribe your SIEM or ticketing here |
| Identity Center | Management (or delegated admin) | AWSAdministratorAccess, AWSPowerUserAccess, AWSReadOnlyAccess, AWSOrganizationsFullAccess, AWSServiceCatalogAdminFullAccess, AWSServiceCatalogEndUserAccess | CT-managed permission sets and groups; optional since LZ 3.x (self-managed identity) |
| Account Factory | Management (Service Catalog) | AWS Control Tower Account Factory | provisioned product per account; AFT wraps it with a pipeline |
Legacy landing zone vs current practice
If you inherit a landing zone created in 2019 to 2022 you will meet the left column. Everything on the right is additive: upgrade the landing zone version, then adopt the API surface piece by piece.
| Area | Legacy (LZ 2.x, console-only era) | Current (LZ 3.3+, API era) |
|---|---|---|
| How it is created | Console wizard only; settings not reproducible; no way to express the landing zone as code | CreateLandingZone with a JSON manifest; Terraform aws_controltower_landing_zone; CloudFormation AWS::ControlTower::LandingZone |
| OU names | Core (shared accounts) and Custom (your accounts); mandatory Sandbox-like second OU | Security (mandatory) and an optional additional OU (default Sandbox); names chosen in the manifest; nested OUs supported (registered to five levels) |
| Vocabulary | Guardrails: mandatory, strongly recommended, elective | Controls, in the Control Catalog, with behavior (preventive, detective, proactive) and implementation (SCP, Config rule, CloudFormation hook, RCP); same three enforcement tiers |
| CloudTrail | One trail per account (StackSet BASELINE-CLOUDTRAIL in every account) | One organization trail in the management account (LZ 3.0+); member trails removed on upgrade; add org-level data events yourself |
| Config recording | Global resources recorded in every region (cost and noise) | Global resources only in the home region (LZ 3.1+); recorder settings can be customised per account through the ConfigRecorder APIs since 2024 |
| Identity | AWS SSO mandatory, directory created by Control Tower | IAM Identity Center optional: CT-managed, bring your own instance, or self-managed (none); external IdP with SCIM is the norm; delegated administrator for Identity Center supported |
| Enrolling OUs and accounts | “Register OU” and “Enroll account” buttons; Account Factory Service Catalog product; no API | EnableBaseline on an OU (AWSControlTowerBaseline 4.0) and per-OU parameters; Account Factory still vends accounts, AFT and AFC automate it; ResetEnabledBaseline repairs drift |
| Applying controls | Console toggles per OU; no API; no parameters | EnableControl with control ARN and parameters (for example the region list of the OU-level region deny control); Terraform aws_controltower_control |
| Region governance | No region deny; you wrote your own SCP | Landing-zone region deny (manifest) plus OU-level region deny control CT.MULTISERVICE.PV.1 with allowed exceptions |
| Account Factory VPC | Creates a VPC in every new account by default, overlapping CIDRs | VPC creation off by default in current Account Factory settings; networking comes from IPAM plus your own IaC |
| Customisation | Customizations for Control Tower (CfCT): CodePipeline that deploys StackSets and SCPs from a manifest on lifecycle events | CfCT still supported; Account Factory for Terraform (AFT) for Terraform shops; Account Factory Customization (AFC) uses Service Catalog blueprints inside Account Factory |
| Security services | Enabled by hand per account | Security Hub central configuration with the “AWS Control Tower” service-managed standard; delegated admin set once in Audit, auto-enable for new accounts |
| Policy types | SCPs only | SCPs, Resource Control Policies (data perimeter), Declarative policies (EC2 settings), tag, backup and AI opt-out policies; Control Tower controls can emit RCPs |
| Drift and upgrades | Console “repair” per OU; manual upgrade clicks | UpdateLandingZone, ResetLandingZone, ResetEnabledBaseline, ResetEnabledControl; drift events on EventBridge |
| Backup | Not part of the landing zone | Optional AWS Backup integration in the manifest (central backup account and backup admin account) and backup plan controls |
Landing zone versions worth knowing
| Version | What changed | What to do on upgrade |
|---|---|---|
| 2.x | Console era: guardrails, Core/Custom, per-account trails, mandatory SSO | Plan the jump to 3.x in one maintenance window; re-register OUs afterwards |
| 3.0 | Organization trail replaces member trails; Security/Sandbox OU names; optional Identity Center | Any tooling that reads per-account trail buckets must switch to the org trail prefix |
| 3.1 | Config records global resources only in the home region | Expect a one-time drop in Config item counts and cost |
| 3.2 | Account Factory VPC optional; baseline updates | Review Account Factory network settings |
| 3.3 | Landing zone API and manifest; baselines API; KMS and retention in the manifest | Export the manifest, commit it, manage the landing zone from code from here on |
| later 3.x | AWS Backup integration, OU-level region deny, RCP-backed controls, Config recorder customisation | Read the release notes before each bump; aws controltower get-landing-zone shows the available version |
Migration from a legacy zone Do not delete and recreate. Upgrade in place (console or UpdateLandingZone), re-register every OU so the 4.0 baseline is applied, then export the manifest with get-landing-zone and start managing it from Terraform by importing the existing resource. Accounts and logs survive; the old member-account trails are removed by the 3.0 step.
Controls: how each kind works
fig 2 · where each control type sits relative to the API call; detective controls only observe
| Behavior | Implemented as | Identifier pattern | Example | Tier |
|---|---|---|---|---|
| Preventive | SCP attached to the OU | AWS-GR_* (legacy ids) CT.{SERVICE}.PV.{n} | AWS-GR_RESTRICT_ROOT_USER AWS-GR_AUDIT_BUCKET_DELETION_PROHIBITED | mandatory, strongly recommended, elective |
| Preventive, region | SCP with NotAction allow-list | landing zone region deny CT.MULTISERVICE.PV.1 (OU level) | parameters: allowed regions, exempted principals and actions | elective at OU level |
| Preventive, data perimeter | Resource Control Policy | CT.{SERVICE}.PV.{n} (RCP-backed) | deny S3 access from outside the organization | elective |
| Detective | Config managed rule deployed via StackSet | AWS-GR_* SH.{STANDARD}.{n} (Security Hub standard) | AWS-GR_ENCRYPTED_VOLUMES AWS-GR_RESTRICTED_SSH AWS-GR_S3_BUCKET_PUBLIC_WRITE_PROHIBITED | strongly recommended, elective |
| Proactive | CloudFormation hook (AWS::ControlTower::…) | CT.{SERVICE}.PR.{n} | CT.S3.PR.1 (block public access on new buckets) CT.EC2.PR.4 (no 0.0.0.0/0 in SG) | elective |
# Browse the catalog (control catalog is the source of truth for ARNs since 2024) aws controlcatalog list-controls --query "Controls[].{arn:Arn,name:Name,behavior:Behavior}" --output table aws controlcatalog get-control --control-arn arn:aws:controlcatalog:::control/vnw7fjwdhkf4alb6jf6ocyzri # Enabled on one OU aws controltower list-enabled-controls --target-identifier arn:aws:organizations::111111111111:ou/o-abc123/ou-abcd-11111111 # Enable a detective control (regional ARN form still accepted) aws controltower enable-control \ --control-identifier arn:aws:controltower:eu-central-1::control/AWS-GR_ENCRYPTED_VOLUMES \ --target-identifier arn:aws:organizations::111111111111:ou/o-abc123/ou-abcd-11111111 # OU-level region deny with parameters aws controltower enable-control \ --control-identifier arn:aws:controltower:eu-central-1::control/CT.MULTISERVICE.PV.1 \ --target-identifier arn:aws:organizations::111111111111:ou/o-abc123/ou-abcd-22222222 \ --parameters '[{"key":"AllowedRegions","value":["eu-central-1","eu-west-1"]}]' # Poll the async operation aws controltower get-control-operation --operation-identifier <id>
OU design that ages well
OUs are for policy, not for org charts. Group by what a control should apply to: environment, data classification, lifecycle state. Keep the tree shallow; five levels is the registration limit, three is plenty.
| OU | Holds | Controls and policies you attach |
|---|---|---|
| Root | nothing directly except the management account | region deny (landing zone), deny leaving the organization, deny disabling CloudTrail and Config, protect AWSControlTower* roles |
| Security | Log Archive, Audit (mandatory, created by CT) | mandatory controls; deny bucket policy changes on log buckets; delegated admin registrations live in Audit |
| Infrastructure | Network (Transit Gateway, IPAM, Route 53), Shared Services (AD, tooling), Backup | strongly recommended set; allow only infra services; RCP restricting resource sharing to the org |
| Workloads/Prod | production application accounts | strongly recommended + elective hardening, proactive controls, deny instance types outside the allow list, backup policy |
| Workloads/NonProd | dev, test, staging | same preventive set as Prod minus the strictest, detective only for cost-related rules |
| Sandbox | personal experimentation, short-lived | region deny to one region, deny IAM users, service allow-list, budget action to stop instances |
| PolicyStaging | one or two canary accounts | every new SCP goes here first for a week |
| Suspended | accounts being decommissioned | deny everything except billing and read; after 90 days close the account |
| Exceptions | acquired or legacy accounts that cannot take the baseline yet | register the OU later; until then only SCPs apply |
| Deployments | CI/CD accounts with cross-account deploy roles | deny console access, require OIDC federation for pipelines |
Account names and emails Pick a pattern before the first account: {org}-{env}-{workload} and plus-addressed emails such as [email protected]. Emails cannot be reused, and Account Factory rejects an email already attached to a closed account for 90 days.
Account Factory, AFT, AFC and CfCT
fig 3 · vending is always Account Factory; the three customisation layers differ in where the code runs and who owns the pipeline
| Choose | When | Watch out for |
|---|---|---|
| Account Factory alone | small estates, few accounts a year, everything else by hand or a separate IaC repo | no customisation on vend; someone has to run the post-steps |
| AFC blueprints | you want a VPC, roles and alarms in every account with the least moving parts | one blueprint per account; updates mean updating the provisioned product; CloudFormation only |
| AFT | Terraform shop, many accounts, per-account customisation, GitOps | its own management account and pipeline to maintain; Terraform version pinning; AFT upgrades are a project |
| CfCT | CloudFormation shop that needs StackSets and SCPs applied by OU from a repo | overlaps with Control Tower controls; keep custom SCPs out of the aws-guardrails-* names |
| Enrolling an existing account | acquisitions, pre-CT accounts | delete any existing Config recorder and delivery channel first; create AWSControlTowerExecution role trusting the management account; then enable baseline on its OU or use Account Factory “enroll” |
Configuration runbook
Greenfield landing zone, API path, Terraform-ready. Each step is one decision or one command; tick as you go. The generator at the bottom fills the values.
Phase 0: decisions (do these on paper first)
Phase 1: management account hygiene
aws iam get-account-summary --query "SummaryMap.AccountMFAEnabled" aws account put-alternate-contact --alternate-contact-type SECURITY --email-address [email protected] --name "Security" --phone-number "+359..." --title "SOC"
aws organizations create-organization --feature-set ALL ROOT=$(aws organizations list-roots --query "Roots[0].Id" --output text) for T in SERVICE_CONTROL_POLICY TAG_POLICY BACKUP_POLICY RESOURCE_CONTROL_POLICY DECLARATIVE_POLICY_EC2; do aws organizations enable-policy-type --root-id $ROOT --policy-type $T; done aws organizations enable-aws-service-access --service-principal controltower.amazonaws.com aws organizations enable-aws-service-access --service-principal sso.amazonaws.com
for R in $(aws ec2 describe-regions --query "Regions[].RegionName" --output text); do aws configservice describe-configuration-recorders --region $R --query "ConfigurationRecorders[].name" --output text; done
aws service-quotas request-service-quota-increase --service-code organizations --quota-code L-29A0C5DF --desired-value 100 aws account enable-region --region-name eu-south-1
AWSControlTowerAdmin trust controltower.amazonaws.com, policy AWSControlTowerServiceRolePolicy + ec2:DescribeAvailabilityZones AWSControlTowerCloudTrailRole trust cloudtrail.amazonaws.com, logs:CreateLogStream/PutLogEvents on aws-controltower/CloudTrailLogs AWSControlTowerStackSetRole trust cloudformation.amazonaws.com, sts:AssumeRole on arn:aws:iam::*:role/AWSControlTowerExecution AWSControlTowerConfigAggregatorRoleForOrganizations trust config.amazonaws.com, policy AWSConfigRoleForOrganizations
Phase 2: shared accounts and key
aws organizations create-account --email [email protected] --account-name "Log Archive" aws organizations create-account --email [email protected] --account-name "Audit" aws organizations list-create-account-status --states SUCCEEDED --query "CreateAccountStatuses[].{name:AccountName,id:AccountId}"
Phase 3: create the landing zone
OP=$(aws controltower create-landing-zone --landing-zone-version 3.3 --manifest file://manifest.json \
--tags Owner=platform --query operationIdentifier --output text)
watch -n 60 aws controltower get-landing-zone-operation --operation-identifier $OP
aws controltower list-landing-zonesaws organizations list-organizational-units-for-parent --parent-id $ROOT aws cloudtrail get-trail-status --name aws-controltower-BaselineCloudTrail aws controltower list-enabled-baselines
Phase 4: identity
Phase 5: OUs, baselines, controls
aws organizations create-organizational-unit --parent-id $ROOT --name Infrastructure aws organizations create-organizational-unit --parent-id $ROOT --name Workloads WL=$(aws organizations list-organizational-units-for-parent --parent-id $ROOT --query "OrganizationalUnits[?Name=='Workloads'].Id" --output text) aws organizations create-organizational-unit --parent-id $WL --name Prod aws organizations create-organizational-unit --parent-id $WL --name NonProd
IC=$(aws controltower list-enabled-baselines --query "enabledBaselines[?contains(baselineIdentifier,'LN25R72TTG6IGPTQ')].arn" --output text)
aws controltower enable-baseline \
--baseline-identifier arn:aws:controltower:eu-central-1::baseline/17BSJV3IGJ2QSGA2 \
--baseline-version 4.0 \
--target-identifier arn:aws:organizations::111111111111:ou/o-abc123/ou-abcd-11111111 \
--parameters "[{\"key\":\"IdentityCenterEnabledBaselineArn\",\"value\":\"$IC\"}]"Phase 6: security services delegated to Audit
AUDIT=222222222222
aws guardduty enable-organization-admin-account --admin-account-id $AUDIT
aws securityhub enable-organization-admin-account --admin-account-id $AUDIT
aws inspector2 enable-delegated-admin-account --delegated-admin-account-id $AUDIT
aws organizations register-delegated-administrator --account-id $AUDIT --service-principal access-analyzer.amazonaws.com
aws organizations register-delegated-administrator --account-id $AUDIT --service-principal config.amazonaws.com
aws organizations register-delegated-administrator --account-id $AUDIT --service-principal macie.amazonaws.com
aws detective enable-organization-admin-account --account-id $AUDIT
aws fms associate-admin-account --admin-account $AUDIT
# then, from the Audit account:
aws guardduty update-organization-configuration --detector-id <id> --auto-enable-organization-members ALL
aws securityhub update-organization-configuration --auto-enable --auto-enable-standards DEFAULTPhase 7: Account Factory and first accounts
# Account Factory via Service Catalog (what the console button does) PID=$(aws servicecatalog search-products-as-admin --query "ProductViewDetails[?ProductViewSummary.Name=='AWS Control Tower Account Factory'].ProductViewSummary.ProductId" --output text) PA=$(aws servicecatalog list-provisioning-artifacts --product-id $PID --query "ProvisioningArtifactDetails[-1].Id" --output text) aws servicecatalog provision-product --product-id $PID --provisioning-artifact-id $PA --provisioned-product-name network-prod \ --provisioning-parameters Key=AccountName,Value=network-prod Key=AccountEmail,[email protected] \ Key=ManagedOrganizationalUnit,Value="Infrastructure (ou-abcd-33333333)" \ Key=SSOUserEmail,[email protected] Key=SSOUserFirstName,Value=Platform Key=SSOUserLastName,Value=Team
Phase 8: operate
aws controltower get-landing-zone --landing-zone-identifier $(aws controltower list-landing-zones --query "landingZones[0].arn" --output text) terraform import aws_controltower_landing_zone.this <landing-zone-id>
{ "source": ["aws.controltower"],
"detail-type": ["AWS Service Event via CloudTrail"],
"detail": { "eventName": ["CreateManagedAccount","UpdateManagedAccount","EnableGuardrail","DisableGuardrail","SetupLandingZone","UpdateLandingZone","RegisterOrganizationalUnit","DeregisterOrganizationalUnit"] } }Operational playbooks
PB-1 Enroll an existing (pre-Control Tower) account
when acquisition, legacy account, account created outside Account Factory
aws configservice delete-configuration-recorder --configuration-recorder-name default --region eu-central-1 aws configservice delete-delivery-channel --delivery-channel-name default --region eu-central-1
aws iam create-role --role-name AWSControlTowerExecution --assume-role-policy-document \
'{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::111111111111:root"},"Action":"sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name AWSControlTowerExecution --policy-arn arn:aws:iam::aws:policy/AdministratorAccessaws organizations move-account --account-id 333333333333 --source-parent-id $ROOT --destination-parent-id ou-abcd-22222222 aws controltower list-enabled-baselines --query "enabledBaselines[?contains(targetIdentifier,'333333333333')]"
PB-2 Add a governed region
when a workload needs a region that is currently denied
aws controltower update-landing-zone --landing-zone-identifier <id> --landing-zone-version 3.3 --manifest file://manifest.json for EB in $(aws controltower list-enabled-baselines --query "enabledBaselines[].arn" --output text); do aws controltower reset-enabled-baseline --enabled-baseline-identifier $EB; done
PB-3 Upgrade the landing zone version
when get-landing-zone shows a newer version; quarterly review
aws controltower update-landing-zone --landing-zone-identifier <id> --landing-zone-version 3.4 --manifest file://manifest.json
PB-4 Repair drift
when dashboard shows drift: SCP modified, role deleted, account moved by hand, StackSet instance deleted
aws controltower get-landing-zone --landing-zone-identifier <id> --query "landingZone.driftStatus" aws controltower get-enabled-baseline --enabled-baseline-identifier <arn> --query "enabledBaselineDetails.driftStatusSummary" aws controltower get-enabled-control --enabled-control-identifier <arn> --query "enabledControlDetails.driftStatusSummary"
aws controltower reset-enabled-control --enabled-control-identifier <arn> aws controltower reset-enabled-baseline --enabled-baseline-identifier <arn> aws controltower reset-landing-zone --landing-zone-identifier <id>
PB-5 Decommission an account
when workload retired, sandbox expired
aws servicecatalog terminate-provisioned-product --provisioned-product-name sandbox-lp aws organizations close-account --account-id 444444444444
PB-6 Roll out a new preventive control safely
when security asks for a new deny, for example “no public AMIs”
aws logs start-query --log-group-name aws-controltower/CloudTrailLogs --start-time $(date -d '-7 days' +%s) --end-time $(date +%s) \ --query-string 'fields eventTime, userIdentity.arn, eventName, errorMessage | filter errorCode = "AccessDenied" and errorMessage like /service control policy/ | sort eventTime desc'
PB-7 Lost access to the management account console
when IdP outage, Identity Center misconfiguration, admin left
aws sts assume-role --role-arn arn:aws:iam::333333333333:role/AWSControlTowerExecution --role-session-name breakglass-$(date +%s)
Generator: manifest, CLI, Terraform
Fill the parameters; the three outputs update as you type. Nothing leaves the page. Account IDs that you do not have yet can stay as the placeholders; the CLI output creates them first.
Terraform notes aws_controltower_landing_zone and aws_controltower_control are in the aws provider; awscc_controltower_enabled_baseline is in the awscc provider because the aws provider has no baseline resource. OU ARNs are needed as targets, so the OUs are created by Terraform and their ARNs passed through. Apply in two stages: roles, accounts and landing zone first (one apply, then wait for the operation), OUs, baselines and controls second, because the Identity Center enabled-baseline ARN only exists after the landing zone is up.
API and CLI reference
| Object | CLI (aws controltower …) | Notes |
|---|---|---|
| Landing zone | create-landing-zone, get-landing-zone, update-landing-zone, reset-landing-zone, delete-landing-zone, list-landing-zones, get-landing-zone-operation, list-landing-zone-operations | one per organization; operations are async, poll with the operation identifier |
| Baselines | list-baselines, get-baseline, enable-baseline, get-enabled-baseline, list-enabled-baselines, update-enabled-baseline, reset-enabled-baseline, disable-baseline, get-baseline-operation | AWSControlTowerBaseline 17BSJV3IGJ2QSGA2, IdentityCenterBaseline LN25R72TTG6IGPTQ; others via list-baselines |
| Controls | enable-control, disable-control, get-enabled-control, list-enabled-controls, update-enabled-control, reset-enabled-control, get-control-operation, list-control-operations | target is an OU ARN; parameters as JSON key/value list |
| Control catalog | aws controlcatalog list-controls, get-control, list-domains, list-objectives, list-common-controls | global ARN form arn:aws:controlcatalog:::control/{id}; maps controls to frameworks |
| Tags | tag-resource, untag-resource, list-tags-for-resource | on landing zone, enabled baselines, enabled controls |
| Events | EventBridge source aws.controltower | CreateManagedAccount, UpdateManagedAccount, EnableGuardrail, DisableGuardrail, SetupLandingZone, UpdateLandingZone, RegisterOrganizationalUnit, DeregisterOrganizationalUnit, PrecheckOrganizationalUnit |
| CloudFormation | AWS::ControlTower::LandingZone, AWS::ControlTower::EnabledBaseline, AWS::ControlTower::EnabledControl | same model as the API; the awscc Terraform provider wraps these |
| Terraform (aws) | aws_controltower_landing_zone, aws_controltower_control, data.aws_controltower_controls | provider 5.20+ for landing zone |
| Terraform (awscc) | awscc_controltower_landing_zone, awscc_controltower_enabled_baseline, awscc_controltower_enabled_control | Cloud Control API based; needed for baselines |
| AFT module | aws-ia/control_tower_account_factory/aws | GitHub aws-ia/terraform-aws-control_tower_account_factory |
| CfCT | customizations-for-aws-control-tower (CloudFormation template) | GitHub aws-solutions/aws-control-tower-customizations |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| CreateLandingZone fails with a role error | one of the four AWSControlTower* roles missing or wrong trust | create them as in Phase 1; names are exact |
| “AWS Config is already enabled” precheck failure | recorder or delivery channel exists in management, Log Archive or Audit | delete in every governed region, retry |
| Account Factory stuck in “Under change” for hours | StackSet instance failed in one region (quota, SCP, opt-in region not enabled) | CloudFormation StackSets, operation details; fix and re-run the provisioned product update |
| Email already in use | a closed account or an existing AWS sign-up uses it | new plus-address; closed accounts block the email for 90 days |
| Drift on every OU after an upgrade | baseline version moved; OUs not re-registered | reset-enabled-baseline on each OU |
| Terraform apply in a member account denied with “explicit deny in a service control policy” | a preventive control or region deny matched | CloudTrail errorMessage names the policy id; read the control, do not edit the SCP |
| Control Tower roles deleted in a member account | someone ran an “clean up IAM” script | recreate AWSControlTowerExecution, then reset the enabled baseline for the OU |
| Identity Center groups missing new members | SCIM not provisioning or group not pushed from the IdP | check SCIM endpoint token expiry (one year), push the group from the IdP |
| Config costs jumped | pre-3.1 recorders record global resources everywhere, or a noisy resource type | upgrade; or customise recorders via the Config recorder customisation to exclude types |
| Cannot delete a log bucket or its objects | mandatory controls and bucket policy deny it, by design | only via lifecycle expiry; the landing zone retention is the knob |
| Member account cannot leave the organization | mandatory control AWS-GR_RESTRICT_ROOT_USER and the leave-org SCP | move to an unregistered OU, remove from Account Factory, then organizations remove-account-from-organization from the management account |
0 comments