Skip to content

microsoftexpert/tf-mod-aws-network-manager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🟧 AWS Network Manager / Cloud WAN Terraform Module

A single global network + Cloud WAN core network backbone, with every AWS connectivity primitive — VPC, Transit Gateway, Direct Connect, Site-to-Site VPN, and on-prem SD-WAN Connect peers — wired in as first-class, centrally-governed attachments. Built for the AWS provider v6.x.

Terraform aws module type resources


🧩 Overview

  • 🌐 Two keystones, one module: aws_networkmanager_global_network (the account-wide container) and aws_networkmanager_core_network (the actual Cloud WAN backbone), created and wired together in one call
  • 📜 Policy-as-JSON, plumbing-as-Terraform: you build the Cloud WAN segments/routing policy however you like (the aws_networkmanager_core_network_policy_document data source is the recommended pattern) and pass it in as a string — this module owns the attachment and topology resources, not policy authoring
  • 🔌 Every connectivity path is a first-class child collection: VPC, Connect (SD-WAN GRE/no-encap), Site-to-Site VPN, Direct Connect gateway, and Transit Gateway registration/peering/route-table attachments — all for_each over stable, caller-chosen keys
  • 🗺️ Physical topology modeling: sites, devices, links, and link associations for organizations that track their on-prem network inventory inside Network Manager
  • 🔐 Cross-account safe by construction: attachment acceptance (aws_networkmanager_attachment_accepter) is always an explicit, separate step — no auto-accept flag anywhere in this module
  • 🧵 Migration-friendly: register an existing Transit Gateway hub into Cloud WAN and peer it in without touching the TGW itself, letting you move spoke-by-spoke rather than a big-bang cutover

💡 Why it matters: once a network has outgrown a flat mesh of VPC peerings or a single-Region Transit Gateway, Cloud WAN gives one place to define segmentation policy (which workloads may talk to which) across every Region and every connectivity type — instead of re-deriving that policy independently in route tables, security groups, and VPN configs.


❤️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


🗺️ Where this fits in the family

flowchart LR
 VPC["tf-mod-aws-vpc"] --> NM["tf-mod-aws-network-manager"]
 TGW["tf-mod-aws-transit-gateway"] --> NM
 VPN["tf-mod-aws-vpn"] --> NM
 DX["tf-mod-aws-dx"] --> NM
 PL["aws_ec2_managed_prefix_list (caller-managed)"] --> NM
 NM --> RAM["Cross-account RAM shares"]
 NM --> R53R["tf-mod-aws-route53-resolver (on-prem DNS)"]

 style NM fill:#FF9900,color:#fff
Loading

🧬 What this module builds

flowchart TD
 GN["aws_networkmanager_global_network.this (keystone)"]
 CN["aws_networkmanager_core_network.this (singleton)"]
 PA["aws_networkmanager_core_network_policy_attachment.this (conditional)"]

 GN --> CN
 CN --> PA

 GN --> Site["aws_networkmanager_site (for_each)"]
 GN --> Dev["aws_networkmanager_device (for_each)"]
 Site --> Link["aws_networkmanager_link (for_each)"]
 Dev --> LinkAssoc["aws_networkmanager_link_association (for_each)"]
 Link --> LinkAssoc

 CN --> VpcAtt["aws_networkmanager_vpc_attachment (for_each)"]
 CN --> ConnAtt["aws_networkmanager_connect_attachment (for_each)"]
 VpcAtt --> ConnAtt
 ConnAtt --> ConnPeer["aws_networkmanager_connect_peer (for_each)"]
 CN --> VpnAtt["aws_networkmanager_site_to_site_vpn_attachment (for_each)"]
 CN --> DxAtt["aws_networkmanager_dx_gateway_attachment (for_each)"]
 GN --> TgwReg["aws_networkmanager_transit_gateway_registration (for_each)"]
 CN --> TgwPeer["aws_networkmanager_transit_gateway_peering (for_each)"]
 TgwPeer --> TgwRtAtt["aws_networkmanager_transit_gateway_route_table_attachment (for_each)"]

 GN --> CgwAssoc["aws_networkmanager_customer_gateway_association (for_each)"]
 CN --> PlAssoc["aws_networkmanager_prefix_list_association (for_each)"]
 CN --> RoutingLabel["aws_networkmanager_attachment_routing_policy_label (for_each)"]
 VpcAtt --> Accepter["aws_networkmanager_attachment_accepter (for_each)"]

 style GN fill:#FF9900,color:#fff
 style CN fill:#FF9900,color:#fff
Loading

✅ Provider / Versions

  • Terraform >= 1.12.0
  • hashicorp/aws >= 6.0, < 7.0 (validated against v6.54.0)
  • No provider {} block inside this module — credentials, default_tags, and Region all come from the caller's provider configuration

🔑 Required IAM Permissions

Action Required for Notes
networkmanager:CreateGlobalNetwork, DescribeGlobalNetworks, UpdateGlobalNetwork, DeleteGlobalNetwork, TagResource, UntagResource Global network lifecycle
networkmanager:CreateCoreNetwork, GetCoreNetwork, UpdateCoreNetwork, DeleteCoreNetwork Core network lifecycle
networkmanager:PutCoreNetworkPolicy, GetCoreNetworkPolicy, GetCoreNetworkChangeSet, ExecuteCoreNetworkChangeSet Policy attachment / propagation Change-set execution is asynchronous
networkmanager:CreateSite/CreateDevice/CreateLink, matching Get*/Update*/Delete* Sites, devices, links
networkmanager:AssociateLink, DisassociateLink Link associations
networkmanager:CreateVpcAttachment, CreateConnectAttachment, CreateConnectPeer, CreateSiteToSiteVpnAttachment, CreateDirectConnectGatewayAttachment, CreateTransitGatewayRouteTableAttachment, matching Get*/DeleteAttachment The six attachment types Least-privilege: scope Delete* to arn:aws:networkmanager::<account>:attachment/*
networkmanager:RegisterTransitGateway, DeregisterTransitGateway, CreateTransitGatewayPeering TGW registration/peering
networkmanager:AssociateCustomerGateway, DisassociateCustomerGateway Customer gateway associations
networkmanager:PutAttachmentRoutingPolicyLabel, DeleteAttachmentRoutingPolicyLabel Routing policy labels
networkmanager:AcceptAttachment Attachment accepters Run in the core-network-owning account
ec2:DescribeVpcs, ec2:DescribeSubnets Read-back validation for VPC attachments

No iam:PassRole is required anywhere in this module's scope. A service-linked role (AWSServiceRoleForNetworkManager) is auto-created by AWS on first global-network creation — see AWS Prerequisites.


📋 AWS Prerequisites

  • Service-linked role AWSServiceRoleForNetworkManager auto-creates on first use; grant iam:CreateServiceLinkedRole once.
  • Core network requires a LIVE policy before most attachments can be created. Supply a complete core_network_policy_document from the start, or use the two-pass create_base_policy = true pattern (see Architecture Notes).
  • Prefix lists referenced by prefix_list_associations must be defined in us-west-2 (the documented Cloud WAN home Region), even though the association applies globally across every core network edge.
  • Quotas: 5 global networks/account, 1 core network/global network, 10,000 attachments/core network (soft) — verify current values via Service Quotas (networkmanager) before large migrations.
  • A global network is account-wide, not per-Region — do not create one per Region the way you would for a VPC.

📁 Module Structure

tf-mod-aws-network-manager/
├── providers.tf
├── variables.tf
├── main.tf
├── outputs.tf
├── README.md
└── SCOPE.md

⚙️ Quick Start

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name                       = "corp-cloud-wan"
  global_network_description = "global network backbone"
  core_network_description   = "Primary Cloud WAN core network"

  # Build with the aws_networkmanager_core_network_policy_document data
  # source in the caller; passed here as an opaque JSON string.
  core_network_policy_document = data.aws_networkmanager_core_network_policy_document.this.json

  vpc_attachments = {
    app = {
      vpc_arn     = module.app_vpc.arn
      subnet_arns = values(module.app_vpc.private_subnet_arns)
    }
  }

  tags = {
    environment = "shared-services"
    owner       = "network-engineering"
  }
}

🔌 Cross-Module Contract

Consumes

Input Type Source module
vpc_attachments[*].vpc_arn / subnet_arns string / list(string) tf-mod-aws-vpc
site_to_site_vpn_attachments[*].vpn_connection_arn string tf-mod-aws-vpn
customer_gateway_associations[*].customer_gateway_arn string tf-mod-aws-vpn
dx_gateway_attachments[*].direct_connect_gateway_arn string tf-mod-aws-dx
transit_gateway_registrations / transit_gateway_peerings[*].transit_gateway_arn string tf-mod-aws-transit-gateway
transit_gateway_route_table_attachments[*].transit_gateway_route_table_arn string tf-mod-aws-transit-gateway
prefix_list_associations[*].prefix_list_arn string caller-managed aws_ec2_managed_prefix_list

Emits

Output Description Consumed by
id / arn Global network id/ARN Account-wide references
core_network_id / core_network_arn Core network id/ARN Every externally-created attachment; RAM shares
site_ids / device_ids / link_ids Maps by key Sibling collections within this module
vpc_attachment_ids / _arns Map by key connect_attachments (transport), attachment_accepters
transit_gateway_peering_ids Map by key transit_gateway_route_table_attachments
tags_all Merged tags Governance / audit

See SCOPE.md for the complete Consumes/Emits tables (all 19 resource types).


📚 Example Library

1 · Minimal — global network + core network, no policy yet
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "sandbox-cloud-wan"
}
2 · Global network + core network + policy (single Region)
data "aws_networkmanager_core_network_policy_document" "this" {
  core_network_configuration {
    asn_ranges = ["64512-65534"]
    edge_locations { location = "us-east-1" }
  }

  segments {
    name                          = "prod"
    isolate_attachments           = true
    require_attachment_acceptance = true
  }

  segments {
    name                = "shared-services"
    isolate_attachments = false
  }
}

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name                         = "corp-cloud-wan"
  core_network_policy_document = data.aws_networkmanager_core_network_policy_document.this.json
}
3 · Two-pass bootstrap with create_base_policy (VPC attachments before the real policy)
# Pass 1
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name               = "corp-cloud-wan"
  create_base_policy = true

  vpc_attachments = {
    app = { vpc_arn = module.app_vpc.arn, subnet_arns = values(module.app_vpc.private_subnet_arns) }
  }
}

# Pass 2 (after the VPC attachment id is known) — add core_network_policy_document
# referencing module.network_manager.vpc_attachment_ids["app"] in your segment-actions.
4 · VPC attachment with appliance mode + IPv6 support
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  vpc_attachments = {
    inspection = {
      vpc_arn     = module.inspection_vpc.arn
      subnet_arns = values(module.inspection_vpc.private_subnet_arns)
      options = {
        appliance_mode_support = true
        ipv6_support           = true
      }
    }
  }
}
5 · Physical topology — site, device, link, link association
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  sites = {
    hq = { description = "Headquarters", location = { address = "123 Main St", latitude = "47.6062", longitude = "-122.3321" } }
  }

  devices = {
    edge-01 = { site_key = "hq", vendor = "Cisco", model = "ISR4451", type = "router" }
  }

  links = {
    isp-a = { site_key = "hq", bandwidth = { upload_speed = 100, download_speed = 500 }, provider_name = "MegaCorp" }
  }

  link_associations = {
    edge01-isp-a = { device_key = "edge-01", link_key = "isp-a" }
  }
}
6 · Connect attachment (SD-WAN overlay) + Connect peer
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  vpc_attachments = {
    transport = { vpc_arn = module.transport_vpc.arn, subnet_arns = values(module.transport_vpc.private_subnet_arns) }
  }

  connect_attachments = {
    sdwan = {
      edge_location            = "us-east-1"
      transport_attachment_key = "transport"
      options                  = { protocol = "GRE" }
    }
  }

  connect_peers = {
    dc1 = {
      connect_attachment_key = "sdwan"
      peer_address           = "203.0.113.10"
      bgp_options            = { peer_asn = 65000 }
    }
  }
}
7 · Site-to-Site VPN attachment (wiring from tf-mod-aws-vpn)
module "vpn_branch1" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-vpn?ref=v1.0.0"
  #... transit_gateway_id or vpc_id path...
}

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  site_to_site_vpn_attachments = {
    branch1 = { vpn_connection_arn = module.vpn_branch1.arn }
  }

  customer_gateway_associations = {
    branch1 = { customer_gateway_arn = module.vpn_branch1.customer_gateway_arn, device_key = "edge-01" }
  }
}
8 · Direct Connect gateway attachment
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  dx_gateway_attachments = {
    corp = {
      direct_connect_gateway_arn = module.dx.gateway_arn
      edge_locations             = ["us-east-1"]
    }
  }
}
9 · Migrating an existing Transit Gateway hub into Cloud WAN
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  # Step 1: register the existing TGW into the global network (topology only)
  transit_gateway_registrations = {
    legacy_hub = { transit_gateway_arn = module.tgw.arn }
  }

  # Step 2: peer Cloud WAN to the TGW (the actual data-plane link)
  transit_gateway_peerings = {
    legacy_hub = { transit_gateway_arn = module.tgw.arn }
  }

  # Step 3: attach individual TGW route tables (spokes) one at a time
  transit_gateway_route_table_attachments = {
    spoke_a = {
      peering_key                     = "legacy_hub"
      transit_gateway_route_table_arn = module.tgw.route_table_arns["spoke"]
    }
  }
}
10 · Prefix list association referenced by alias in the policy
resource "aws_ec2_managed_prefix_list" "corp_cidrs" {
  provider       = aws.us_west_2 # Cloud WAN home Region
  name           = "corp-cidrs"
  address_family = "IPv4"
  max_entries    = 10
}

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  prefix_list_associations = {
    corp = { alias = "corpCidrs", prefix_list_arn = aws_ec2_managed_prefix_list.corp_cidrs.arn }
  }
}
11 · Cross-account attachment acceptance
# In the core-network-owning account's provider:
module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  attachment_accepters = {
    spoke_a_vpc = {
      attachment_id   = "attachment-0123456789abcdef0"
      attachment_type = "VPC"
    }
  }
}
12 · `tags` merging with provider `default_tags`
# Caller's provider block:
provider "aws" {
  default_tags {
    tags = { managed-by = "terraform", cost-center = "network" }
  }
}

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"
  tags = { environment = "shared-services" } # merges with default_tags; resource tags win on key conflict
}
13 · Secure-by-default opt-out — flattening segment isolation (NOT recommended)
# This module does not template the policy JSON, so "opting out" of segment
# isolation is done entirely in the CALLER's policy document — simply omit
# isolate_attachments/require_attachment_acceptance from a segment block to
# fall back to AWS's own defaults (isolate_attachments = false). Document any
# such exception; our baseline recommendation is explicit isolation with
# narrow share actions, not a flat segment.
data "aws_networkmanager_core_network_policy_document" "flat" {
  core_network_configuration {
    asn_ranges = ["64512-65534"]
    edge_locations { location = "us-east-1" }
  }
  segments { name = "everything" } # isolate_attachments defaults to false — NOT the baseline
}
14 · `for_each` pattern — multiple VPC attachments from a map of VPC modules
locals {
  spoke_vpcs = { app = module.app_vpc, data = module.data_vpc, shared = module.shared_vpc }
}

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name = "corp-cloud-wan"

  vpc_attachments = {
    for k, v in local.spoke_vpcs : k => {
      vpc_arn     = v.arn
      subnet_arns = values(v.private_subnet_arns)
    }
  }
}
15 · `import` block — bringing an existing global network under management
import {
  to = module.network_manager.aws_networkmanager_global_network.this
  id = "global-network-0d47f6t230mz46dy4"
}
16 · End-to-end composition — VPC + Transit Gateway + VPN + Cloud WAN
module "app_vpc" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-vpc?ref=v1.0.0"
  #...
}

module "tgw" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-transit-gateway?ref=v1.0.0"
  #...
}

module "vpn_branch1" {
  source             = "git::https://github.com/microsoftexpert/tf-mod-aws-vpn?ref=v1.0.0"
  transit_gateway_id = module.tgw.id
  #...
}

data "aws_networkmanager_core_network_policy_document" "this" {
  core_network_configuration {
    asn_ranges = ["64512-65534"]
    edge_locations { location = "us-east-1" }
  }
  segments {
    name                          = "prod"
    isolate_attachments           = true
    require_attachment_acceptance = false
  }
}

module "network_manager" {
  source = "git::https://github.com/microsoftexpert/tf-mod-aws-network-manager?ref=v1.0.0"

  name                         = "corp-cloud-wan"
  core_network_policy_document = data.aws_networkmanager_core_network_policy_document.this.json

  vpc_attachments = {
    app = { vpc_arn = module.app_vpc.arn, subnet_arns = values(module.app_vpc.private_subnet_arns) }
  }

  transit_gateway_registrations = { legacy_hub = { transit_gateway_arn = module.tgw.arn } }
  transit_gateway_peerings      = { legacy_hub = { transit_gateway_arn = module.tgw.arn } }

  site_to_site_vpn_attachments = { branch1 = { vpn_connection_arn = module.vpn_branch1.arn } }

  tags = { environment = "prod", owner = "network-engineering" }
}

📥 Inputs (high-level)

Core: name, global_network_description, core_network_description

Policy: core_network_policy_document, create_base_policy, base_policy_document, base_policy_regions

Topology: sites, devices, links, link_associations

Attachments: vpc_attachments, connect_attachments, connect_peers, site_to_site_vpn_attachments, dx_gateway_attachments, transit_gateway_registrations, transit_gateway_peerings, transit_gateway_route_table_attachments

Governance: customer_gateway_associations, prefix_list_associations, attachment_routing_policy_labels, attachment_accepters

Universal: tags, timeouts


🧾 Outputs

  • id / arn — global network primary outputs
  • global_network_id — alias of id
  • core_network_id / core_network_arn / core_network_state / core_network_edges / core_network_segments / core_network_policy_attachment_state
  • site_ids / site_arns, device_ids / device_arns, link_ids / link_arns, link_association_ids — topology maps by key
  • vpc_attachment_ids / _arns, connect_attachment_ids / _arns, connect_peer_ids / _arns — attachment maps by key
  • connect_peer_configurationssensitive; may include tunnel addressing detail
  • site_to_site_vpn_attachment_ids / _arns, dx_gateway_attachment_ids / _arns
  • transit_gateway_registration_keys, transit_gateway_peering_ids / _arns / edge_locations, transit_gateway_route_table_attachment_ids / _arns
  • customer_gateway_association_keys, prefix_list_association_keys, attachment_routing_policy_label_keys, attachment_accepter_states — metadata-only resources with no AWS-exposed id/arn
  • tags_all

🧠 Architecture Notes

  • ARN formats: global network — arn:aws:networkmanager::<account>:global-network/<id>; core network — arn:aws:networkmanager::<account>:core-network/<id>; attachments — arn:aws:networkmanager:<edge-region>:<account>:attachment/<id>.
  • Immutable / FORCE-NEW fields: vpc_attachments[*].vpc_arn, connect_attachments[*].options.protocol, connect_peers[*].peer_address, every routing_policy_label, and every field on prefix_list_associations / attachment_routing_policy_labels.
  • tagstags_all ↔ provider default_tags: resource tags merge with the caller's provider default_tags; resource tags win on key conflict. Six resources in this module are NOT taggable in AWS: link_association, transit_gateway_registration, customer_gateway_association, attachment_accepter, prefix_list_association, attachment_routing_policy_label.
  • Eventual consistency: applying aws_networkmanager_core_network_policy_attachment triggers an asynchronous change-set across every core network edge. terraform apply returns once the change-set is EXECUTED, not once every edge has converged — verify core_network_edges / attachment state before cutting production traffic over.
  • Destroy ordering: deleting the core network policy attachment does NOT revert the policy (AWS behavior). Deleting the core network itself requires every attachment to be deleted first (AWS-enforced); deleting the global network requires the core network to be gone first.
  • No us-east-1 global-resource requirement — unlike CloudFront/WAFv2/ACM, Cloud WAN's edge Regions are defined INSIDE the policy document, not by the provider's Region; this module can be authored from any provider Region.
  • aws_networkmanager_transit_gateway_peering has no edge-location input — AWS computes it automatically; see transit_gateway_peering_edge_locations.

🧱 Design Principles

  • Segment isolation is a policy-authoring discipline, not a module flag. This module does not template the Cloud WAN policy JSON, so there is no single "secure default" boolean to flip. Build core_network_policy_document with isolate_attachments = true and require_attachment_acceptance = true on sensitive segments, and use narrow share/deny-filter actions to open only the inter-segment paths you intend — opt-out is simply omitting these fields from a segment block, which is why the recommendation is documented here rather than enforced in code.
  • Cross-account attachments never auto-accept. There is no flag in this module that accepts an attachment automatically; attachment_accepters is always a deliberate, separate map the core-network-owning account populates.
  • VPC attachment options default to the safer posture where AWS defines one (dns_support = true; appliance_mode_support / ipv6_support / security_group_referencing_support all default false, requiring explicit opt-in per attachment).
  • Attachments are blocked from creation until a LIVE policy exists — the module enforces this with an explicit depends_on from every attachment resource to the policy attachment, so terraform apply fails fast with a clear dependency rather than a confusing AWS API error mid-apply.

🚀 Runbook

cd tf-mod-aws-network-manager
terraform init -backend=false
terraform validate
terraform fmt -check

⚠️ terraform plan/apply require valid AWS credentials (profile / SSO / OIDC) and a Region. Pin the module source with ?ref=v1.0.0 — never a branch — so a later commit to main cannot silently change what an existing root module applies.

terraform plan
terraform apply
terraform output core_network_id

🧪 Testing

  • terraform validate + terraform fmt -check — the offline gate this module was authored against (no AWS credentials required).
  • For live testing, apply into a non-production account/Region with a least-privilege role scoped to the IAM actions listed above; start with create_base_policy = true and a single vpc_attachments entry before layering in Connect/VPN/TGW attachments.
  • Verify policy propagation with core_network_edges / attachment state outputs before treating a new segment as production-ready.

💬 Example Output

$ terraform apply
...
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

core_network_id = "core-network-0d47f6t230mz46dy4"
core_network_arn = "arn:aws:networkmanager::123456789012:core-network/core-network-0d47f6t230mz46dy4"
id = "global-network-0d47f6t230mz46dy4"
vpc_attachment_ids = {
 "app" = "attachment-0a1b2c3d4e5f6g7h8"
}

🔍 Troubleshooting

  • ValidationException: policy is not LIVE on a VPC/Connect/VPN/DX attachment — the core network has no LIVE policy yet. Set create_base_policy = true for a two-pass bootstrap, or supply a complete core_network_policy_document up front.
  • Routes not showing up after terraform apply — the policy change-set is asynchronous; check core_network_edges and the relevant attachment's state before assuming the apply "didn't work."
  • Tag drift from default_tags overlap — a key set in both the provider's default_tags and this module's tags will show the resource value winning; remove the duplicate from one side to stop the diff noise.
  • Credential-chain failures — this module has no credential variables; confirm AWS_PROFILE/SSO session/OIDC role is valid in the shell/pipeline before plan/apply.
  • prefix_list_association fails with a Region error — the referenced managed prefix list must be defined in us-west-2 regardless of where your core network's edges are.
  • Cross-account attachment stuck PENDING_ATTACHMENT_ACCEPTANCE — run attachment_accepters in the core-network-owning account's provider, not the spoke account's.
  • Destroy fails: "core network has attachments" — delete every attachment collection (set the relevant maps to {}) before removing the core network or global network.
  • IAM permission denials — cross-check the failing action against ## Required IAM permissions above; do not broaden to networkmanager:*.

🔗 Related Docs

  • Terraform Registry: hashicorp/aws — Network Manager resource family (aws_networkmanager_*)
  • AWS documentation: Network Manager / Cloud WAN core concepts, policy document reference, Connect attachments, and cross-account sharing
  • AWS documentation: Direct Connect + Cloud WAN integration, Transit Gateway peering with Cloud WAN

🧡 "Infrastructure as Code should be standardized, consistent, and secure."

Packages

 
 
 

Contributors

Languages