Skip to main content

AWS Landing Zone

A single-account AWS landing zone - a two-AZ VPC, KMS key, VPC flow logs, deployer and read-only IAM roles, and an encrypted CloudTrail audit trail that downstream Pulumi projects build on.

This example lives in the pulumi/examples repository. Check out just this directory to use it:

Get started with this example
git clone --filter=blob:none --sparse https://github.com/pulumi/examples pulumi-examples
git -C pulumi-examples sparse-checkout set aws-ts-landing-zone
cd pulumi-examples/aws-ts-landing-zone

The foundational, shared resources a single AWS account needs before any workload lands on top of it. Deploy this once per account, then have every downstream Pulumi project consume its outputs (via a StackReference) instead of re-creating the same plumbing.

Note: This is an illustrative example of how you might model a landing zone in Pulumi, not a production-ready one. A real landing zone would typically add guardrails this example leaves out for brevity — Service Control Policies, AWS Config rules, GuardDuty/Security Hub, cross-account centralized logging, and IAM roles scoped to specific tasks rather than the broad PowerUserAccess/ReadOnlyAccess used here.

The LandingZone component provisions:

  • A VPC across three availability zones, with public and private subnets, an internet gateway, and per-AZ NAT gateways (built with the awsx.ec2.Vpc component).
  • A KMS customer-managed key (with rotation) and a key policy that lets CloudWatch Logs and CloudTrail use it.
  • VPC flow logs delivered to an encrypted CloudWatch log group.
  • Deployer (PowerUserAccess) and read-only (ReadOnlyAccess) IAM roles that a trusted principal can assume.
  • An encrypted, multi-region CloudTrail audit trail writing to a lifecycle-managed S3 bucket.

The companion example aws-ts-serverless-react-postgres consumes this stack’s networkId, privateSubnetIds, and secretsStore outputs.

Prerequisites#

  1. Install Pulumi
  2. Configure your AWS credentials
  3. Install Node.js

Deploying and running the program#

  1. Create a new stack:

    Terminal window
    pulumi stack init dev
  2. Set the AWS region:

    Terminal window
    pulumi config set aws:region us-west-2

    Optionally override the VPC CIDR block or the principal trusted to assume the roles:

    Terminal window
    pulumi config set cidrBlock 10.10.0.0/16
    pulumi config set trustedPrincipalArn arn:aws:iam::123456789012:root
  3. Install dependencies:

    Terminal window
    npm install
  4. Run pulumi up to preview and deploy:

    Terminal window
    pulumi up
  5. Inspect the outputs downstream stacks will reference:

    Terminal window
    pulumi stack output
    Current stack outputs (9):
    OUTPUT VALUE
    auditBucket platform-audit-***
    dataEncryptionKeyAlias alias/platform-landing-zone
    dataEncryptionKeyArn arn:aws:kms:us-west-2:***
    deployerRoleArn arn:aws:iam::***:role/platform-deployer
    networkId vpc-***
    privateSubnetIds ["subnet-***","subnet-***","subnet-***"]
    publicSubnetIds ["subnet-***","subnet-***","subnet-***"]
    readOnlyRoleArn arn:aws:iam::***:role/platform-readonly
    secretsStore platform/

Clean up#

To tear down the resources, run:

Terminal window
pulumi destroy
pulumi stack rm

Summary#

In this example you deployed a reusable AWS landing zone: network, encryption, audit logging, and workload identities that every project in the account can share. Reference its outputs from your application stacks with a StackReference to keep foundational infrastructure in one place.

Related

The infrastructure as code platform for any cloud.