Skip to content

Latest commit

 

History

History
163 lines (123 loc) · 6.97 KB

File metadata and controls

163 lines (123 loc) · 6.97 KB

Generated by Merlin Studio (https://app.merlin-studio.cloud). Licensed under the Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0).

Deployment Guide

This guide walks through deploying the landing zone for AcmeCorp using each of the four output formats. Pick the section that matches your tooling — you don't need to use all four.

Prerequisites (all formats)

  1. AWS Organizations is created and the Management account is identified.
  2. Identity Center (SSO) is enabled in the management account (or you've decided to skip it for now).
  3. The deployer has AdministratorAccess on the management account, plus the OrganizationAccountAccessRole for cross-account changes.
  4. AWS CLI v2 is installed and configured (aws --version ≥ 2.15).
  5. All PLACEHOLDER_* tokens have been replaced — see PLACEHOLDERS.md if present.
  6. Run a search to confirm nothing slipped through:
    grep -rE 'PLACEHOLDER_[A-Z_]+' . | grep -v PLACEHOLDERS.md

Post-deployment: IAM Identity Center access assignments

The landing zone creates Identity Center permission sets (AdministratorAccess, ReadOnlyAccess, BillingAccess, …) but no account assignments — it cannot reference IdP users or groups that do not exist until you connect your identity source and create groups. Until you assign principals, no one can sign in to any account via SSO, even though the permission sets are present.

After deploying and connecting your IdP (or creating groups in Identity Center), create one assignment per group → permission set → account/OU:

  • Console: Identity Center → AWS accounts → select account(s) → Assign users/groups.
  • CLI:
    aws sso-admin create-account-assignment \
      --instance-arn <identity-center-instance-arn> \
      --permission-set-arn <permission-set-arn> \
      --principal-type GROUP --principal-id <group-id> \
      --target-type AWS_ACCOUNT --target-id <account-id>
  • LZA: populate the (scaffolded-empty) identityCenterAssignments block in aws-lza/iam-config.yaml and re-run the pipeline.

A sensible baseline: AWSAdministrators → AdministratorAccess (Root, break-glass), Engineers → PowerUserAccess (Workloads), Auditors → ReadOnlyAccess + SecurityAuditAccess (all), Finance → BillingAccess (Management).


Format 1: AWS Control Tower + Landing Zone Accelerator (LZA)

LZA orchestrates Control Tower + a custom CDK app. The 6–8 YAML files in aws-lza/ drive it.

Prereqs

Steps

  1. Commit the contents of aws-lza/ to the configured aws-accelerator-config repository.
  2. Trigger the AWSAccelerator-Pipeline in CodePipeline (or wait for the next scheduled run).
  3. Each stage runs in sequence: Prepare → Accounts → Organization → Networking → Security → SecurityResources → Operations → Network-Prep → SecurityAudit → Network-VPC → Finalize.
  4. Monitor in CloudWatch Logs (group aws-accelerator-installer) and Step Functions.

Verification

  • All accounts in accounts-config.yaml appear in AWS Organizations.
  • The org-level CloudTrail in LogArchive shows events from every member account.
  • GuardDuty delegated admin = Audit; Security Hub aggregator linked to us-east-2.

Common gotchas

  • Stuck on Prepare: check that the management account's email address in accounts-config.yaml matches the actual payer account email.
  • Networking stage fails: confirm OU IDs in organization-config.yaml exist before the pipeline runs (LZA creates the OU tree itself, but a partial earlier run can leave stale state).
  • CMK-encrypted CloudTrail won't decrypt: KMS key policy must include the SCP service principal for cross-account decrypt. LZA wires this; double-check after manual key edits.




Troubleshooting

Symptom Likely cause Fix
PLACEHOLDER_* literal in deployed resource Token wasn't replaced before apply tofu/cdk destroy, replace tokens, re-apply
AccessDenied for CloudTrail/Config writes Bucket policy missing service principal Re-run with the bundled bucket policy in s3_log_archive.tf / LoggingStack
LZA pipeline stuck on Network-Prep OU referenced by VPC doesn't exist Confirm organization-config.yaml runs before network-config.yaml
cdk deploy fails on LogGroup already exists Re-deploying without removing the previous CDK app Delete the CFN stack manually, then re-deploy

Format-specific behavior you should know about

Two aspects of the landing zone are expressed differently in each format because the underlying tools differ. The deployed shape is equivalent; the operational mechanics are not.

Default VPC deletion

AWS Control Tower / LZA can delete the default VPC in every region of every account in one declarative line (defaultVpc.delete: true). Terraform and CDK have no equivalent primitive — aws_default_vpc manages an existing default VPC rather than purging defaults org-wide. As a result:

  • LZA: handles automatically. No action needed.
  • OpenTofu: emits a marker null_resource pointing at scripts/delete-default-vpcs.sh. Run the script once after first apply, in every account, in every enabled region.
  • CDK: not handled. Run the same out-of-band script.
  • tfvars: not handled. Run the same out-of-band script.

The deployed result is identical: zero default VPCs in any account.

VPC flow log destinations and retention

LZA's flow-log block supports dual destinations natively:

destinations: [cloud-watch-logs, s3]

with separate retention (CloudWatch 365 days, S3 lifecycle 7 years).

The Terraform community VPC module and CDK Vpc construct accept one primary flow-log destination per VPC. Reproducing LZA's dual-destination pattern in those formats requires emitting a second aws_flow_log / ec2.FlowLog resource outside the module — a more verbose but equivalent pattern.

For this bundle, OpenTofu / CDK / tfvars emit CloudWatch-only flow logs (365-day retention). If you require the 7-year S3 archive that LZA provides, either deploy via LZA, or add a second flow-log resource targeting S3 in the format you're using. The generator does not auto-emit the second resource because most CIS-only deployments don't need it; add it explicitly when compliance demands it.


Where to ask for help