Infrastructure by Vitale Mazo

Supercharging Terraform with AWS Cloud WAN Modules — Reference Implementation (Part 1 of 2)

Part 1 of 2: A concise, production‑ready README for evolving from a single‑Region deployment to a segmented, multi‑Region AWS Cloud WAN using Terraform modules and Terraform Cloud workspaces.

#Terraform #AWS #Cloud WAN #DevOps #Infrastructure as Code

Supercharging Terraform with AWS Cloud WAN Modules — Reference Implementation

This is Part 1 of 2. Continue with Part 2 — Advanced AWS Cloud WAN with Service Insertion.

A concise, production‑ready README for evolving from a single‑Region deployment to a segmented, multi‑Region AWS Cloud WAN using Terraform modules and Terraform Cloud workspaces. Adapted from “Beyond the Basics: My Playbook for Supercharging Terraform with AWS Cloud WAN Modules” by Vitale Mazo.


Table of Contents


Overview

This reference distills a proven approach to managing AWS Cloud WAN at enterprise scale with Terraform. It focuses on segment‑based routing, environment isolation, and a multi‑workspace strategy that limits blast radius while enabling application teams to self‑serve VPCs via a logical VPC module.

AWS Cloud WAN Architecture Figure 1: AWS Cloud WAN Global Network Architecture - Source: AWS Architecture Blog


Architecture

High‑level design (segments govern reachability; policies evolve by version):

flowchart LR
  subgraph Global_Network
    subgraph Core_Network
      direction TB
      SEG_PROD[Segment: prod]
      SEG_DEV[Segment: dev]
      SEG_SHARED[Segment: shared]
      SEG_SB[Segment: sandbox (isolated)]
    end
  end

  VPCp1[VPC: prod (us-east-1)] --> SEG_PROD
  VPCt1[VPC: test (us-east-1)] --> SEG_PROD
  VPCd1[VPC: dev (us-east-1)]  --> SEG_DEV
  VPCs1[VPC: shared (us-east-1)] --> SEG_SHARED

  VPCp2[VPC: prod (us-west-2)] --> SEG_PROD
  VPCd2[VPC: dev (us-west-2)]  --> SEG_DEV
  VPCs2[VPC: shared (us-west-2)] --> SEG_SHARED
  VPCsb[VPC: sandbox (us-west-2)] --> SEG_SB

  SEG_SHARED <--> SEG_PROD
  SEG_SHARED <--> SEG_DEV

Key tenets:

  • prod and test live in the prod segment; dev is isolated from prod/test.
  • All environments can reach shared; sandbox is fully isolated (no shares).
  • Policy (JSON) is versioned and applied to the Core Network; attachments are mapped via tags on the attachment (not just the VPC).

Prerequisites

  • Terraform CLI and access to Terraform Cloud (Business recommended for governance).
  • AWS account(s) with permissions for Network Manager / Cloud WAN.
  • Basic familiarity with HCL and Terraform workspaces.

Terraform Provider & Backend (Quick Scaffold)

Use Terraform Cloud workspaces as recommended. Minimal boilerplate:

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.0"
    }
  }
  cloud {
    organization = "YOUR_ORG"
    workspaces { name = "net-global-foundation" }
  }
}

provider "aws" {
  region = "us-east-1"
}

Quick Start

  1. Foundation workspace: create the Global Network and Core Network.
  2. Policy v1: apply a single‑Region policy with prod, dev, shared.
  3. Policy v2: add us-west-2 and an isolated sandbox segment.
  4. VPCs via module: app teams consume a logical VPC module that:
    • creates the VPC + subnets + routes,
    • creates the Cloud WAN VPC attachment,
    • tags the attachment with Environment so the policy maps it to the right segment.

Repository Layout

.
├── foundation/
│   ├── 01-global-network.tf
│   ├── 02-core-network.tf
│   ├── 03-policy-v1.tf
│   └── 04-policy-v2.tf
├── modules/
│   └── logical-vpc/
│       └── main.tf
└── apps/
    ├── app-payments-prod-us-east-1/
    ├── app-analytics-dev-us-west-2/
    └── app-research-sandbox-us-west-2/

Core Components

Global Network

The Global Network is the top‑level container spanning cloud + on‑prem.

# foundation/01-global-network.tf
resource "aws_networkmanager_global_network" "main" {
  description = "Vitale Mazo's Global Enterprise Network"
  tags = {
    Owner      = "Platform.Engineering"
    CostCenter = "12345"
  }
}

Core Network

The Core Network hosts segments, edges, and route policy versions.

# foundation/02-core-network.tf
resource "aws_networkmanager_core_network" "main" {
  description       = "Enterprise Core Network"
  global_network_id = aws_networkmanager_global_network.main.id
}

Core Network Policy

Tip: Use the official aws_networkmanager_core_network_policy_document data source to generate valid JSON (hyphen‑case keys) and apply with the policy attachment resource. Avoid hand‑crafting JSON.

AWS Cloud WAN Policy and Tagging Figure 2: AWS Cloud WAN Policy Enforcement and Tagging - Shows how VPCs are attached to network segments based on tags and attachment policies

Iteration 1 — Multi‑Environment, Single Region

Goals:

  • Isolate dev from prod/test.
  • Allow prod and test to interoperate.
  • Grant shared reachability to all.
# foundation/03-policy-v1.tf
data "aws_networkmanager_core_network_policy_document" "v1" {
  version = "2021.12"

  core_network_configuration {
    asn_ranges = ["64512-65534"]
    edge_locations { location = "us-east-1" }
  }

  # Segments
  segments { name = "prod"   description = "Production and Test environments" }
  segments { name = "dev"    description = "Development environment" }
  segments { name = "shared" description = "Shared infrastructure services" }

  # shared <-> prod/dev (bidirectional advertisements)
  segment_actions {
    action     = "share"
    mode       = "attachment-route"
    segment    = "shared"
    share_with = ["prod", "dev"]
  }

  # Attachment mapping by TAGS ON THE ATTACHMENT
  attachment_policies {
    rule_number     = 100
    condition_logic = "or"
    conditions { type = "tag-value", key = "Environment", operator = "equals", value = "production" }
    conditions { type = "tag-value", key = "Environment", operator = "equals", value = "test" }
    action { association_method = "constant", segment = "prod" }
  }

  attachment_policies {
    rule_number = 200
    conditions  { type = "tag-value", key = "Environment", operator = "equals", value = "development" }
    action      { association_method = "constant", segment = "dev" }
  }

  attachment_policies {
    rule_number = 300
    conditions  { type = "tag-value", key = "Environment", operator = "equals", value = "shared" }
    action      { association_method = "constant", segment = "shared" }
  }
}

resource "aws_networkmanager_core_network_policy_attachment" "v1" {
  core_network_id = aws_networkmanager_core_network.main.id
  policy_document = data.aws_networkmanager_core_network_policy_document.v1.json
  description     = "Cloud WAN policy – Iteration 1"
}

Iteration 2 — Add Region + Isolated Sandbox

Add us‑west‑2 and a sandbox that is isolated (no shares, requires acceptance).

# foundation/04-policy-v2.tf
data "aws_networkmanager_core_network_policy_document" "v2" {
  version = "2021.12"

  core_network_configuration {
    asn_ranges = ["64512-65534"]
    edge_locations { location = "us-east-1" }
    edge_locations { location = "us-west-2" } # new region
  }

  segments { name = "prod" }
  segments { name = "dev" }
  segments { name = "shared" }

  # Isolated sandbox
  segments {
    name                          = "sandbox"
    description                   = "Isolated sandbox for security testing"
    require_attachment_acceptance = true
    isolate_attachments           = true
  }

  # Preserve v1 shares
  segment_actions {
    action     = "share"
    mode       = "attachment-route"
    segment    = "shared"
    share_with = ["prod", "dev"]
  }

  # Map sandbox attachments
  attachment_policies {
    rule_number = 50
    conditions  { type = "tag-value", key = "Environment", operator = "equals", value = "sandbox" }
    action      { association_method = "constant", segment = "sandbox" }
  }

  # (Reuse v1 mapping rules for prod/dev/shared)
}

resource "aws_networkmanager_core_network_policy_attachment" "v2" {
  core_network_id = aws_networkmanager_core_network.main.id
  policy_document = data.aws_networkmanager_core_network_policy_document.v2.json
  description     = "Cloud WAN policy – Iteration 2 (add us-west-2 + sandbox)"
}

Logical VPC Module

Application teams consume a logical VPC module that builds the VPC + subnets, creates a VPC attachment, tags the attachment (critical), and programs VPC routes to the Core Network ARN.

# modules/logical-vpc/main.tf (essentials)
variable "core_network_id"  { type = string }
variable "core_network_arn" { type = string }
variable "environment"      { type = string } # production | test | development | shared | sandbox
variable "cost_center"      { type = string }

# ... aws_vpc, subnets, route tables, etc. ...

resource "aws_networkmanager_vpc_attachment" "this" {
  core_network_id = var.core_network_id
  vpc_arn         = aws_vpc.this.arn
  subnet_arns     = [aws_subnet.private_a.arn, aws_subnet.private_b.arn]

  # Tags evaluated by the ATTACHMENT policy:
  tags = {
    Environment = var.environment
    CostCenter  = var.cost_center
  }
}

# Example route: send traffic to Cloud WAN
resource "aws_route" "to_core_network" {
  route_table_id         = aws_route_table.private.id
  destination_cidr_block = "0.0.0.0/0"   # or a specific CIDR
  core_network_arn       = var.core_network_arn
}

Important: Cloud WAN does not modify your VPC route tables. Your module must add routes targeting the core network attachment ARN.


Terraform Cloud Workspace Strategy

  • Workspace 1 — Foundation (net-global-foundation):
    Manages Global/Core Network + policy attachments; outputs core_network_id, core_network_arn, segment names.
  • Workspace 2 — Shared Services (per Region) (svc-shared-us-east-1, svc-shared-us-west-2):
    Consumes foundation outputs; deploys the logical VPC module.
  • Workspace 3+ — App Workspaces (app-payments-prod-us-east-1, app-analytics-dev-us-west-2, app-research-sandbox-us-west-2):
    Owned by app teams; blast radius is limited to their stack.
  • Run Triggers: propagate foundation changes to dependent workspaces.

Governance & Guardrails

Use Sentinel/OPA to enforce:

  • Every aws_networkmanager_vpc_attachment must have Environment and CostCenter tags.
  • Block attempts to disable sandbox isolation or add shares to sandbox.
  • Fail plans that create attachments without a valid Environment value.

Advanced Design Considerations

Attachment types — include Connect (SD‑WAN):

resource "aws_networkmanager_connect_attachment" "sdwan" {
  core_network_id         = var.core_network_id
  transport_attachment_id = aws_networkmanager_vpc_attachment.transport.id
  edge_location           = "us-east-1"
  tags = { Environment = "branch-edge" }
}

Cross‑Account model via AWS RAM: share the Core Network from us-east-1; recipient accounts must accept before creating attachments.

Policy lifecycle: each edit creates a new version; generate a change set, review impact, and keep prior versions for rollback. Expect propagation per Core Network Edge.

Attachment acceptance control: set require_attachment_acceptance at segment level for sensitive segments (e.g., prod).

ASN planning: define asn_ranges; optionally allocate non‑overlapping, narrow ranges per Region.

Observability & events: use Network Manager for a global view and emit signals to EventBridge (policy applied, attachment state changes).

Inter‑segment inspection: insert an inspection VPC (firewall/IPS/GWLB); advertise only inspection prefixes and steer via segment shares + route tables.

Direct Connect fit: use DX/SiteLink for deterministic underlay into AWS; then attach into Cloud WAN for global policy and distribution.


Rollout & Operations Checklist

  • Foundation workspace applied; Core Network ID/ARN exported.
  • Policy v1 applied; verify shared <-> prod/dev reachability.
  • Policy v2 applied; us-west-2 edge online; sandbox isolated.
  • VPC module applied; attachment tags set (Environment, CostCenter).
  • VPC route tables contain routes to Core Network ARN where needed.
  • Run Triggers wired; downstream workspaces re‑planned.
  • Guardrails active (Sentinel/OPA).
  • EventBridge alerts configured (policy version changes, attachment state).

Troubleshooting

  • Attachment isn’t in the expected segment → Confirm tags on the attachment, not just the VPC.
  • No cross‑env reachability → Check segment shares (e.g., shared <-> prod/dev) are present in the active policy version.
  • Sandbox leaking → Ensure sandbox has no share actions, and isolate_attachments = true.
  • Blackhole routes → Verify VPC routes target core_network_arn; Cloud WAN won’t change VPC route tables.
  • Cross‑account failures → Confirm RAM share initiated in us-east-1 and recipients accepted.
  • Policy change didn’t apply everywhere → Check change set and allow for per‑edge propagation; consider rollback to the prior version if needed.

FAQ

Why map environments with attachment tags instead of per‑workspace variables?
Because the policy engine evaluates tags on the attachment, giving centralized, declarative control over segment placement and safety rails across accounts.

Can test live with prod?
Yes—place test in the prod segment if you need pre‑production validation, while keeping dev in its own segment.


Credits

Primary source and examples by Vitale Mazo — “Beyond the Basics: My Playbook for Supercharging Terraform with AWS Cloud WAN Modules.”


Save this file as README.md in the root of your repo.

About the Author

Vitale Mazo is a Senior Cloud Engineer with 19+ years of experience in enterprise IT, specializing in cloud native technologies and multi-cloud infrastructure design.