This module can be used to deploy an AWS Cloud WAN network - with the Core Network as main resource. A Global Network (the high-level container for the Core Network), can also be created if required.
In addition, the module abstracts Central VPCs' creation and Core Network attachment - with the Global Network and Core Network created either within or outside the same module definition. Central VPC types supported are Inspection, Egress (with or without inspection), Ingress (with or without inspection), and Shared Services. Below you can find more information about the format and definition of each VPC type.
Two variables - var.global_network
and var.core_network
- are used to define the Global Network and Core Network. Starting with the Global Network, the following attributes can be configured:
description
= (string) Global Network's description.tags
= (Optional|map(string)) Tags to apply to the Global Network resource.
If a Global Network is already created and it is desired to pass only the resource ID to create a Core Network, use the var.global_network_id
variable.
Following with the Core Network, the following attributes can be configured:
description
= (string) Core Network's description.policy_document
= (any) Core Network's policy in JSON format. It is recommended the use of the Core Network Document data source.base_policy_document
= (Optional|any) Conflicts withbase_policy_regions
. Sets the base policy document for the Core Network. For more information about the need of the base policy, check the When do I need to create the base_policy? section below.base_policy_regions
= (Optional|list(string)) Conflicts withbase_policy_document
. List of AWS Regions to create the base policy document in the Core Network. For more information about the need of the base policy, check the When do I need to create the base_policy? section below.resource_share_name
= (Optional|string) AWS Resource Access Manager (RAM) Resource Share name. Providing this value, RAM resources will be created to share the Core Network with the principals indicated invar.core_network.ram_share_principals
.resource_share_allow_external_principals
= (Optional|bool) Indicates whether principals outside your AWS Organization can be associated with a Resource Share.ram_share_principals
= (Optional|list(string)) List of principals (AWS Account or AWS Organization) to share the Core Network with.tags
= (Optional|map(string)) Tags to apply to the Core Network and RAM Resource Share (if created) resources.
If a Core Network is already created and it is desired to pass only the resource ARN to attach Central VPCs, use the var.core_network_arn
variable.
The example below builds an AWS Network Manager Global Network and Core Network from scratch. The Core Network needs the ID of the Global Network created, and also a policy document (to define the global infrastructure). You can find more information about the policy document in the documentation
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
global_network = {
description = "Global Network - AWS Cloud WAN Module"
tags = {
Name "global-network"
}
}
core_network = {
description = "Core Network - AWS Cloud WAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
tags = {
Name = "core-network"
}
}
tags = {
Module = "aws-ia/cloudwan/aws"
}
}
If you already have a Network Manager Global Network created, you can pass the ID as variable and only create the Core Network.
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
global_network_id "global-network-021aedd98c7487b93"
core_network = {
description = "Global Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
tags = {
Name = "core-network"
}
}
tags = {
Module = "aws-ia/cloudwan/aws"
}
}
In addition, when creating a new Core Network, you can also share it using AWS Resource Access Manager (RAM). You can share a core network across accounts or across your organization. Important to note that you must share your global resource from the N. Virginia (us-east-1) Region so that all other Regions can see the global resource.
module "cloud_wan" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
global_network = {
description = "Global Network - ${var.identifier}"
tags = {
Name = "global-network"
}
}
core_network = {
description = "Core Network - ${var.identifier}"
policy_document = data.aws_networkmanager_core_network_policy_document.policy.json
resource_share_name = "core-network-share"
resource_share_allow_external_principals = false
ram_share_principals = [org-XXX]
tags = {
Name = "core-network"
}
}
tags = {
Project = var.identifier
}
}
Policy documents can be passed as a string of JSON or using the policy_document data source (recommended option).
data "aws_networkmanager_core_network_policy_document" "policy" {
core_network_configuration {
vpn_ecmp_support = false
asn_ranges = ["64512-64520"]
edge_locations {
location = "us-east-1"
asn = 64512
}
}
segments {
name = "shared"
description = "SegmentForSharedServices"
require_attachment_acceptance = true
}
segment_actions {
action = "share"
mode = "attachment-route"
segment = "shared"
share_with = ["*"]
}
attachment_policies {
rule_number = 1
condition_logic = "or"
conditions {
type = "tag-value"
operator = "equals"
key = "segment"
value = "shared"
}
action {
association_method = "constant"
segment = "shared"
}
}
}
The variable var.ipv4_network_definition
is an attribute to configure a supernet (IPv4 CIDR block) or managed prefix list of your network/VPCs in AWS. This variable is used when configuring VPC routing in some central VPCs. When checking the different VPC types below, you can check whether this variable is required or not.
Aside the creation of the Global Network and Core Network, this module also abstracts the creation of Central VPCs - and the attachment to the Core Network. The variable var.central_vpcs
can be configured with a map of VPC definitions, with the following attributes:
type
= (string) VPC type (inspection
,egress
,egress_with_inspection
,ingress
,ingress_with_inspection
,shared_services
) - each one of them with a specific VPC routing. For more information about the configuration of each VPC type, check each Central VPC type section below.name
= (Optional|string) Name of the VPC. If not defined, the key of the map will be used.cidr_block
= (Optional|string) IPv4 CIDR range. Cannot set if vpc_ipv4_ipam_pool_id is set.vpc_ipv4_ipam_pool_id
= (Optional|string) Set to use IPAM to get an IPv4 CIDR block. Cannot set if cidr_block is set.vpc_ipv4_netmask_length
= (Optional|number) Set to use IPAM to get an IPv4 CIDR block using a specified netmask. Must be set withvar.vpc_ipv4_ipam_pool_id
.az_count
= (number) Searches the number of AZs in the region and takes a slice based on this number - the slice is sorted a-z.vpc_enable_dns_hostnames
= (Optional|bool) Indicates whether the instances launched in the VPC get DNS hostnames. Enabled by default.vpc_enable_dns_support
= (Optional|bool) Indicates whether the DNS resolution is supported for the VPC. If enabled, queries to the Amazon provided DNS server at the 169.254.169.253 IP address, or the reserved IP address at the base of the VPC network range "plus two" succeed. If disabled, the Amazon provided DNS service in the VPC that resolves public DNS hostnames to IP addresses is not enabled. Enabled by default.vpc_instance_tenancy
= (Optional|string) The allowed tenancy of instances launched into the VPC.vpc_flow_logs
= (Optional|object(any)) Configuration of the VPC Flow Logs of the VPC configured. Options: "cloudwatch", "s3", "none".subnets
= (any) Configuration of the subnets to create in the VPC - a map of subnets' definition is expected. Depending the VPC type, the format (subnets to configure and resources created by the module) will be different. Check each Central VPC type section below. for more information.tags
= (Optional|map(string)) Tags to apply to all the Central VPC resources.
To simplify the definition of this module, the following VPC module is used to create the VPC resources. We recommend to review its README to have more information about its inputs and outputs.
Defining the type inspection will create specific VPC subnets and routing to create a central Inspection VPC - specific for East/West traffic inspection. When defining the VPC subnets (attribute subnets
) two keys are mandatory: endpoints - to place the AWS Network Firewall or Gateway Load Balancer endpoints - and core_network - to place the Core Network attachment ENIs -. You are free to create additional subnets, but default configuration and VPC routing won't be created on them.
When defining the subnets, the following attributes can be configured:
cidrs
= (Optional|list(string)) Cannot set ifnetmask
is set. List of IPv4 CIDRs to set to subnets. Count of CIDRs defined must match quantity of VPC Availability Zones inaz_count
.netmask
= (Optional|number) Cannot set ifcidrs
is set.. Netmask of VPC CIDR block to calculate for each subnet.name_prefix
= (Optional|string) A string prefix to use for the name of your subnet and associated resources. Subnet type key name is used if omitted.tags
= (Optional|map(string)) Tags to set on the subnet and associated resources. For example, for the core_network subnet type, these tags will be applied to the Core Network attachment.
In addition, additional attributes can be configured for the core_network subnet type:
appliance_mode_support
= (Optional|bool) Indicates whether appliance mode is supported. If enabled, traffic flow between a source and destination use the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults totrue
.require_acceptance
= (Optional|bool) Whether the core network VPC attachment requires acceptance or not. Defaults tofalse
.accept_attachment
= (Optional|bool) Whether the core network VPC attachment is accepted or not in the segment. Only valid ifrequire_acceptance
is set totrue
. Defaults totrue
.
Regarding the VPC routing, a default route (0.0.0.0/0) is created in the endpoints route tables pointing to the Core Network attachment.
module "inspection_vpc" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
core_network_arn = module.cloud_wan.core_network.arn
central_vpcs = {
inspection-east-west = {
type = "inspection"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
endpoints = { cidrs = ["10.10.0.0/28", "10.10.0.16/28"] }
core_network = {
cidrs = ["10.10.0.32/28", "10.10.0.48/28"]
tags = { domain = "inspection" }
}
}
}
}
}
Defining the type egress will create specific VPC subnets and routing to create a central Egress VPC. When defining the VPC subnets (attribute subnets
) two keys are mandatory: public - to place the NAT gateways or NAT instances - and core_network - to place the Core Network attachment ENIs -. You are free to create additional subnets, but default configuration and VPC routing won't be created on them.
When defining the subnets, the following attributes can be configured:
cidrs
= (Optional|list(string)) Cannot set ifnetmask
is set. List of IPv4 CIDRs to set to subnets. Count of CIDRs defined must match quantity of VPC Availability Zones inaz_count
.netmask
= (Optional|number) Cannot set ifcidrs
is set.. Netmask of VPC CIDR block to calculate for each subnet.name_prefix
= (Optional|string) A string prefix to use for the name of your subnet and associated resources. Subnet type key name is used if omitted.tags
= (Optional|map(string)) Tags to set on the subnet and associated resources. For example, for the core_network subnet type, these tags will be applied to the Core Network attachment.
In addition, additional attributes can be configured for both the public and core_network subnet types:
- Public subnets (public)
nat_gateway_configuration
= (Optional|string) Determines if NAT Gateways should be created and in how many AZs. Valid values ="none"
,"single_az"
,"all_azs"
(default).map_public_ip_on_launch
= (Optional|bool) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default tofalse
.
- Core Network subnets (core_network)
connect_to_public_natgw
= (Optional|bool) Determines if a default route to NAT Gateways should be created. Defaults totrue
.appliance_mode_support
= (Optional|bool) Indicates whether appliance mode is supported. If enabled, traffic flow between a source and destination use the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults tofalse
.require_acceptance
= (Optional|bool) Whether the core network VPC attachment requires acceptance or not. Defaults tofalse
.accept_attachment
= (Optional|bool) Whether the core network VPC attachment is accepted or not in the segment. Only valid ifrequire_acceptance
is set totrue
. Defaults totrue
.
Regarding the VPC routing, the default configuration of the connect_to_public_natgw
attribute in the core_network subnet type creates a default route (0.0.0.0/0) in the route tables to the NAT gateways. The CIDR block or Prefix List defined in var.ipv4_network_definition
(required in this VPC type) will be used to create a VPC route to the Core Network in the public route tables.
module "egress_vpc" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
core_network_arn = module.cloud_wan.core_network.arn
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
central-egress = {
type = "egress"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
public = { cidrs = ["10.10.0.0/28", "10.10.0.16/28"] }
core_network = {
cidrs = ["10.10.0.32/28", "10.10.0.48/28"]
tags = { domain = "egress" }
}
}
}
}
}
Defining the type egress_with_inspection will create specific VPC subnets and routing to create a central Egress VPC with subnets to add an inspection layer between the Core Network attachment and the public subnets - to inspect egress traffic. When defining the VPC subnets (attribute subnets
) three keys are mandatory:
- public to place the NAT gateways or NAT instances
- endpoints to place the AWS Network Firewall or Gateway Load Balancer endpoints.
- core_network to place the Core Network attachment ENIs.
You are free to create additional subnets, but default configuration and VPC routing won't be created on them. When defining the subnets, the following attributes can be configured:
cidrs
= (Optional|list(string)) Cannot set ifnetmask
is set. List of IPv4 CIDRs to set to subnets. Count of CIDRs defined must match quantity of VPC Availability Zones inaz_count
.netmask
= (Optional|number) Cannot set ifcidrs
is set.. Netmask of VPC CIDR block to calculate for each subnet.name_prefix
= (Optional|string) A string prefix to use for the name of your subnet and associated resources. Subnet type key name is used if omitted.tags
= (Optional|map(string)) Tags to set on the subnet and associated resources. For example, for the core_network subnet type, these tags will be applied to the Core Network attachment.
In addition, additional attributes can be configured for the public, endpoints, and core_network subnet types:
- Public subnets (public)
nat_gateway_configuration
= (Optional|string) Determines if NAT Gateways should be created and in how many AZs. Valid values ="none"
,"single_az"
,"all_azs"
(default).map_public_ip_on_launch
= (Optional|bool) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default tofalse
.
- Endpoint subnets (endpoints)
connect_to_public_natgw
= (Optional|bool) Determines if routes to NAT Gateways should be created. Defaults totrue
.
- Core Network subnets (core_network)
appliance_mode_support
= (Optional|bool) Indicates whether appliance mode is supported. If enabled, traffic flow between a source and destination use the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults totrue
.require_acceptance
= (Optional|bool) Whether the core network VPC attachment requires acceptance or not. Defaults tofalse
.accept_attachment
= (Optional|bool) Whether the core network VPC attachment is accepted or not in the segment. Only valid ifrequire_acceptance
is set totrue
. Defaults totrue
.
Regarding the VPC routing, the default configuration of the connect_to_public_natgw
attribute in the endpoints subnet type creates a default route (0.0.0.0/0) in the route tables to the NAT gateways. The CIDR block or Prefix List defined in var.ipv4_network_definition
(required in this VPC type) will be used to create a VPC route to the Core Network from the endpoints route tables.
module "egress_with_inspection_vpc" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
core_network_arn = module.cloud_wan.core_network.arn
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
central-egress-inspection = {
type = "egress_with_inspection"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
public = { netmask = 28 }
endpoints = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "egress" }
}
}
}
}
}
Defining the type ingress will create specific VPC subnets and routing to create a central Ingress VPC. When defining the VPC subnets (attribute subnets
) two keys are mandatory: public - to place the Elastic Load Balancers or your own ingress solution - and core_network - to place the Core Network attachment ENIs -. You are free to create additional subnets, but default configuration and VPC routing won't be created on them.
When defining the subnets, the following attributes can be configured:
cidrs
= (Optional|list(string)) Cannot set ifnetmask
is set. List of IPv4 CIDRs to set to subnets. Count of CIDRs defined must match quantity of VPC Availability Zones inaz_count
.netmask
= (Optional|number) Cannot set ifcidrs
is set.. Netmask of VPC CIDR block to calculate for each subnet.name_prefix
= (Optional|string) A string prefix to use for the name of your subnet and associated resources. Subnet type key name is used if omitted.tags
= (Optional|map(string)) Tags to set on the subnet and associated resources. For example, for the core_network subnet type, these tags will be applied to the Core Network attachment.
In addition, additional attributes can be configured for both the public and core_network subnet types:
- Public subnets (public)
connect_to_igw
= (Optional|bool) Determines if the default route (0.0.0.0/0) is created in the public subnets with destination the Internet gateway. Defaults totrue
.map_public_ip_on_launch
= (Optional|bool) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default tofalse
.
- Core Network subnets (core_network)
appliance_mode_support
= (Optional|bool) Indicates whether appliance mode is supported. If enabled, traffic flow between a source and destination use the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults tofalse
.require_acceptance
= (Optional|bool) Whether the core network VPC attachment requires acceptance or not. Defaults tofalse
.accept_attachment
= (Optional|bool) Whether the core network VPC attachment is accepted or not in the segment. Only valid ifrequire_acceptance
is set totrue
. Defaults totrue
.
Regarding the VPC routing, the CIDR block or Prefix List defined in var.ipv4_network_definition
(required in this VPC type) will be used to create a VPC route to the Core Network in the public route tables.
module "egress_with_inspection_vpc" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
core_network_arn = module.cloud_wan.core_network.arn
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
ingress = {
type = "ingress"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
public = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "ingress" }
}
}
}
}
}
Defining the type ingress_with_inspection will create specific VPC subnets and routing to create a central Ingress VPC with subnets to add an inspection layer between the Internet gateway and the public subnets - to inspect ingress traffic. When defining the VPC subnets (attribute subnets
) three keys are mandatory:
- endpoints to place the AWS Network Firewall or Gateway Load Balancer endpoints.
- public to place the Elastic Load Balancers or your own ingress solution.
- core_network to place the Core Network attachment ENIs.
You are free to create additional subnets, but default configuration and VPC routing won't be created on them. When defining the subnets, the following attributes can be configured:
cidrs
= (Optional|list(string)) Cannot set ifnetmask
is set. List of IPv4 CIDRs to set to subnets. Count of CIDRs defined must match quantity of VPC Availability Zones inaz_count
.netmask
= (Optional|number) Cannot set ifcidrs
is set.. Netmask of VPC CIDR block to calculate for each subnet.name_prefix
= (Optional|string) A string prefix to use for the name of your subnet and associated resources. Subnet type key name is used if omitted.tags
= (Optional|map(string)) Tags to set on the subnet and associated resources. For example, for the core_network subnet type, these tags will be applied to the Core Network attachment.
In addition, additional attributes can be configured for both the public and core_network subnet types:
- Public subnets (public)
connect_to_igw
= (Optional|bool) Determines if the default route (0.0.0.0/0) is created in the public subnets with destination the Internet gateway. Defaults tofalse
.map_public_ip_on_launch
= (Optional|bool) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default tofalse
.
- Core Network subnets (core_network)
appliance_mode_support
= (Optional|bool) Indicates whether appliance mode is supported. If enabled, traffic flow between a source and destination use the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults tofalse
.require_acceptance
= (Optional|bool) Whether the core network VPC attachment requires acceptance or not. Defaults tofalse
.accept_attachment
= (Optional|bool) Whether the core network VPC attachment is accepted or not in the segment. Only valid ifrequire_acceptance
is set totrue
. Defaults totrue
.
Regarding the VPC routing, the CIDR block or Prefix List defined in var.ipv4_network_definition
(required in this VPC type) will be used to create a VPC route to the Core Network in the public route tables.
module "egress_with_inspection_vpc" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
core_network_arn = module.cloud_wan.core_network.arn
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
ingress-with-inspection = {
type = "ingress_with_inspection"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
endpoints = { netmask = 28 }
public = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "ingress" }
}
}
}
}
}
Defining the type shared_services will create specific VPC subnets and routing to create a central Shared Services VPC. When defining the VPC subnets (attribute subnets
) the only mandatory key is core_network - to place the Core Network attachment ENIs. When defining the subnets, the following attributes can be configured:
cidrs
= (Optional|list(string)) Cannot set ifnetmask
is set. List of IPv4 CIDRs to set to subnets. Count of CIDRs defined must match quantity of VPC Availability Zones inaz_count
.netmask
= (Optional|number) Cannot set ifcidrs
is set.. Netmask of VPC CIDR block to calculate for each subnet.name_prefix
= (Optional|string) A string prefix to use for the name of your subnet and associated resources. Subnet type key name is used if omitted.tags
= (Optional|map(string)) Tags to set on the subnet and associated resources. For example, for the core_network subnet type, these tags will be applied to the Core Network attachment.
In addition, additional attributes can be configured for both the core_network subnet type:
appliance_mode_support
= (Optional|bool) Indicates whether appliance mode is supported. If enabled, traffic flow between a source and destination use the same Availability Zone for the VPC attachment for the lifetime of that flow. Defaults tofalse
.require_acceptance
= (Optional|bool) Whether the core network VPC attachment requires acceptance or not. Defaults tofalse
.accept_attachment
= (Optional|bool) Whether the core network VPC attachment is accepted or not in the segment. Only valid ifrequire_acceptance
is set totrue
. Defaults totrue
.
Regarding the VPC routing, a default route (0.0.0.0/0) poiting to the Core Network attachment will be created in any private route table you create.
module "egress_with_inspection_vpc" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
core_network_arn = module.cloud_wan.core_network.arn
central_vpcs = {
shared-services = {
type = "shared_services"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
vpc_endpoints = { netmask = 28 }
hybrid_dns = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "shared" }
}
}
}
}
}
The variable var.aws_network_firewall
allows the configuration of AWS Network Firewall resources in those central VPCs where inspection can be added - VPC types inspection
, egress_with_inspection
and ingress_with_inspection
. As we use the following AWS Network Firewall module, the VPC routing pointing to the firewall endpoints is also abstracted.
The variable expects a map containing the Network Firewall configuration to apply in each VPC. How do you make sure the Network Firewall resource (and VPC routing) is created in the corresponding central VPC? By using the same key value you used in var.central_vpcs
. Each map definition expects the following attributes:
name
= (string) Name of the AWS Network Firewall resource.description
= (string) Description of the AWS Network Firewall resource.policy_arn
= (string) ARN of the Network Firewall Policy.delete_protection
= (Optional|bool) Indicates whether it is possible to delete the firewall. Defaults tofalse
.policy_change_protection
= (Optional|bool) Indicates whether it is possible to change the firewall policy. Defaults tofalse
.subnet_change_protection
= (Optional|bool) Indicates whether it is possible to change the associated subnet(s) after creation. Defaults tofalse
.tags
= (Optional|map(string)) Tags to apply to the AWS Network Firewall resource.
If you configure the creation of an AWS Network Firewall resource in an Inspection VPC (type inspection
), the VPC routes created are the default ones (0.0.0.0/0) pointing to the firewall endpoints in the core_network route tables.
module "cloudwan_central_vpcs" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
global_network = {
description = "Global Network"
tags = {
Name = "global-network"
}
}
core_network = {
description = "Core Network"
base_policy_regions = [var.aws_region]
policy_document = data.aws_networkmanager_core_network_policy_document.policy.json
tags = {
Name = "core-network"
}
}
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
inspection = {
type = "inspection"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
endpoints = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "inspection" }
}
}
}
}
aws_network_firewall = {
inspection = {
name = "anfw-inspection"
description = "AWS Network Firewall - East/West"
policy_arn = aws_networkfirewall_firewall_policy.policy.arn
}
}
}
### Egress VPC
If you configure the creation of an AWS Network Firewall resource in an Egress VPC (type egress_with_inspection
), the VPC routes created are:
- Default route (0.0.0.0/0) pointing to the firewall endpoints in the core_network route tables.
- CIDR blocks provided in
var.ipv4_network_definition
pointing to the firewall endpoints in the public route tables.
module "cloudwan_central_vpcs" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
global_network = {
description = "Global Network"
tags = {
Name = "global-network"
}
}
core_network = {
description = "Core Network"
base_policy_regions = [var.aws_region]
policy_document = data.aws_networkmanager_core_network_policy_document.policy.json
tags = {
Name = "core-network"
}
}
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
egress-inspection = {
type = "egress_with_inspection"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
public = { netmask = 28 }
endpoints = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "egress" }
}
}
}
}
aws_network_firewall = {
egress-inspection = {
name = "anfw-egress-inspection"
description = "AWS Network Firewall - Egress"
policy_arn = aws_networkfirewall_firewall_policy.policy.arn
}
}
}
### Ingress VPC
If you configure the creation of an AWS Network Firewall resource in an Ingress VPC (type ingress_with_inspection
), the following resources are created:
- VPC route table associated to the Internet gateway.
- Public subnet CIDR blocks pointing to the firewall endpoints in the IGW route table.
- Default route (0.0.0.0/0) pointing to the firewall endpoints in the public route tables.
module "cloudwan_central_vpcs" {
source = "aws-ia/cloudwan/aws"
version = "3.x.x"
global_network = {
description = "Global Network"
tags = {
Name = "global-network"
}
}
core_network = {
description = "Core Network"
base_policy_regions = [var.aws_region]
policy_document = data.aws_networkmanager_core_network_policy_document.policy.json
tags = {
Name = "core-network"
}
}
ipv4_network_definition = "10.0.0.0/8"
central_vpcs = {
ingress-inspection = {
type = "ingress_with_inspection"
cidr_block = "10.10.0.0/24"
az_count = 2
subnets = {
endpoints = { netmask = 28 }
public = { netmask = 28 }
core_network = {
netmask = 28
tags = { domain = "ingress" }
}
}
}
}
aws_network_firewall = {
ingress-inspection = {
name = "anfw-ingress-inspection"
description = "AWS Network Firewall - Ingress"
policy_arn = aws_networkfirewall_firewall_policy.policy.arn
}
}
}
AWS Cloud WAN automates the association of an attachment to a specific segment, reducing the operational overhead specially in multi-Account environments. If you check how to define a core network policy, you will see that the parameter attachment-policies is where you can define how to automate the associations. What can you use to define the attachment's association policy? You can use the Resource ID, Account ID, AWS Region, Attachment Type, and Tags - which is the common item to use.
Now that we have explained the importance of tags when creating Core Network attachments, how can I create these tags using the module? As we use the following VPC module to create the central VPCs, the tags defined under the core_network subnet type will be applied to the Core Network attachment.
core_network = {
netmask = 28
tags = { domain = "segment" }
}
This module has been created to be used once per AWS Region you are creating resources - only 1 provider can be configured. This means that, if you want to create Central VPCs in several AWS Regions, you should have 1 module definition per Region. What about the Global Network and Core Network? These resources are global, and they can be created using a provider definition from any Region - of course, where Cloud WAN is available. Important to note that whatever Region you configure for the provider that creates the Cloud WAN resources, the home region will be US West (Oregon).
Coming back to the question, our recommendation is to create the Global Network and Core Network in a different module definition than the Central VPCs - even if the provider you use to create the global resource is also used to create Central VPCs in that same Region. The main reason of the recommendation is to decouple the definition of global and regional resources. That said, if you want to use the same module definition to create global resources and central VPCs in the Region the provider has configured, the module will allow you to do it (and it's not an anti-pattern).
You will see two attributes when defining the var.core_network
variable are base_policy_document and base_policy_regions, used in the module to define the base_policy, base_policy_document, and base_policy_regions attributes in the aws_networkmanager_core_network
resource. But... why do we need the base_policy?
First of all, let's start explaining why we use the aws_networkmanager_core_network_policy_attachment
resource. When adding an inspection layer to AWS Cloud WAN, a static route is needed - from any of the segments pointing to an Inspection VPC. As you need to reference the attachmend ID of the Inspection VPC(s), a circular dependency is created. To avoid this circular dependency, the aws_networkmanager_core_network_policy_attachment
was created to decouple the creation of the Core Network to the policy document attachment, so when you deploy from scratch your architecture it proceeds as follows:
- Creation of Global Network (if not done already) and Core Network.
- Creation of Core Network attachments.
- Attachment of the policy document - generation of the network.
Important to note that to get this behaviour you need to use the aws_networkmanager_core_network_policy_document
data source.
However, there's still one challenge to overcome: you cannot attach resources to the Core Network without an active policy. And it makes sense, as in the policy you indicate the AWS Regions in which you want to create CNEs (Core Network Edges). Without policy, there are no CNEs and it's impossible to attach anything. Here is where base_policy is going to help us: a temporal policy document is generated so the attachments can be created before applying the policy document where you reference some of those attachment IDs.
You have two ways to define the base_policy:
- Use the base_policy_document argument if you are providing specific configuration on the CNE ASNs in the final policy document you want to deploy.
- Use the base_policy_regions argument to simply indicate the AWS Regions where you want to create attachments prior to the deployment of the final policy document.
What happens when adding new attachments to a current Core Network with a live policy? If any of these attachmens are referenced in the policy document, those are going to be created first and then the policy is going to be updated. The base_policy attribute won't do anything, as there's a current live policy - we don't need this temporal policy.
What happens when adding new AWS Regions to a current Core Network with a live policy? The base_policy won't help us here, as creating a temporal policy with the new AWS Region will create a network disruption - as we already have a network configuration applied. That's why, when adding new AWS Regions, we need a two-step deployment:
- Step 1: Update and apply the policy document with the new AWS Region(s).
- Step 2: Create the new attachment(s) and update the policy document if any static route is needed.
If you are creating for the first time the Core Network and the Central VPCs using the module, you will get the following error:
Error: creating Network Manager VPC (arn:aws:ec2:XXXXXXX-X:XXXXXXX:vpc/vpc-XXXXXXX) Attachment (core-network-XXXXXXX): ValidationException: A live policy was not found
This error is thrown because when creating the Core Network two resources are created: aws_networkmanager_core_network
(main resource) and aws_networkmanager_core_network_policy_attachment
(policy attachment). When creating the VPC attachments, the first resource is the one reference so when it finishes to be created, Terraform will try to create the attachment without waiting for the policy to be LIVE - hence the error.
How to avoid the error? You can do two things:
- If you create the Core Network using this module, you can use the target option to create first the Core Network policy attachment resource.
- If you create the Core Network using directly the provider resources, you can use a depends_on argument in the module definition to wait for the policy attachment to be created (LIVE) before start creating the central VPCs.
Creating Central VPCs with IPAM configuration - The "for_each" map includes keys derived from resource attributes that cannot be determined until apply
When creating Central VPCs referencing an IPAM pool ID, you get the following error:
The "for_each" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.
When working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.
Alternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge.
As described in the error itself, you first need to create the IPAM pool to then later create the VPCs. You can use the target option if the IPAM resources are created in the same document (and state file) as the VPCs.
Name | Version |
---|---|
terraform | >= 1.3.0 |
aws | >= 5.21.0 |
Name | Version |
---|---|
aws | >= 5.21.0 |
Name | Source | Version |
---|---|---|
central_vpcs | aws-ia/vpc/aws | 4.4.1 |
core_network_tags | aws-ia/label/aws | 0.0.5 |
global_network_tags | aws-ia/label/aws | 0.0.5 |
network_firewall | aws-ia/networkfirewall/aws | 1.0.0 |
public_subnet_cidrs | ./modules/subnet_cidrs | n/a |
tags | aws-ia/label/aws | 0.0.5 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
aws_network_firewall | AWS Network Firewall configuration. This variable expect a map of Network Firewall definitions to create a firewall resource (and corresponding VPC routing to firewall endpoints) in the corresponding VPC. The central VPC to create the resources is specified by using the same map key as in var.central_vpcs. Resources will be created only in VPC types inspection , egress_with_inspection , and ingress_with_inspection .Each map item expects the following attributes: - name = (string) Name of the AWS Network Firewall resource.- description = (string) Description of the AWS Network Firewall resource.- policy_arn = (string) ARN of the Network Firewall Policy.- delete_protection = (Optional|bool) Indicates whether it is possible to delete the firewall. Defaults to false .- policy_change_protection = (Optional|bool) Indicates whether it is possible to change the firewall policy. Defaults to false .- subnet_change_protection = (Optional|bool) Indicates whether it is possible to change the associated subnet(s) after creation. Defaults to false .- tags = (Optional|map(string)) Tags to apply to the AWS Network Firewall resource. |
any |
{} |
no |
central_vpcs | Central VPCs definition. This variable expects a map of VPCs. You can specify the following attributes: - type = (string) VPC type (inspection , egress , egress_with_inspection , ingress , ingress_with_inspection , shared_services ) - each one of them with a specific VPC routing. For more information about the configuration of each VPC type, check the README.- name = (Optional|string) Name of the VPC. If not defined, the key of the map will be used.- cidr_block = (Optional|string) IPv4 CIDR range. Cannot set if vpc_ipv4_ipam_pool_id is set.- vpc_ipv4_ipam_pool_id = (Optional|string) Set to use IPAM to get an IPv4 CIDR block. Cannot set if cidr_block is set.- vpc_ipv4_netmask_length = (Optional|number) Set to use IPAM to get an IPv4 CIDR block using a specified netmask. Must be set with var.vpc_ipv4_ipam_pool_id .- az_count = (number) Searches the number of AZs in the region and takes a slice based on this number - the slice is sorted a-z.- vpc_enable_dns_hostnames = (Optional|bool) Indicates whether the instances launched in the VPC get DNS hostnames. Enabled by default.- vpc_enable_dns_support = (Optional|bool) Indicates whether the DNS resolution is supported for the VPC. If enabled, queries to the Amazon provided DNS server at the 169.254.169.253 IP address, or the reserved IP address at the base of the VPC network range "plus two" succeed. If disabled, the Amazon provided DNS service in the VPC that resolves public DNS hostnames to IP addresses is not enabled. Enabled by default.- vpc_instance_tenancy = (Optional|string) The allowed tenancy of instances launched into the VPC.- vpc_flow_logs = (Optional|object(any)) Configuration of the VPC Flow Logs of the VPC configured. Options: "cloudwatch", "s3", "none".- subnets = (any) Configuration of the subnets to create in the VPC. Depending the VPC type, the format (subnets to configure and resources created by the module) will be different. Check the README for more information. - tags = (Optional|map(string)) Tags to apply to all the Central VPC resources. |
any |
{} |
no |
core_network | Core Network definition - providing information to this variable will create a new Core Network. Conflicts with var.core_network_arn .This variable expects the following attributes: - description = (string) Core Network's description.- policy_document = (any) Core Network's policy in JSON format.- base_policy_document = (Optional|any) Conflicts with base_policy_regions . Sets the base policy document for the Core Network. For more information about the need of the base policy, check the README document.- base_policy_regions = (Optional|list(string)) Conflicts with base_policy_document . List of AWS Regions to create the base policy document in the Core Network. For more information about the need of the base policy, check the README document.- resource_share_name = (Optional|string) AWS Resource Access Manager (RAM) Resource Share name. Providing this value, RAM resources will be created to share the Core Network with the principals indicated in var.core_network.ram_share_principals .- resource_share_allow_external_principals = (Optional|bool) Indicates whether principals outside your AWS Organization can be associated with a Resource Share.- ram_share_principals = (Optional|list(string)) List of principals (AWS Account or AWS Organization) to share the Core Network with.- tags = (Optional|map(string)) Tags to apply to the Core Network and RAM Resource Share (if created). |
any |
{} |
no |
core_network_arn | (Optional) Core Network ARN. Conflicts with var.core_network . |
string |
null |
no |
global_network | Global Network definition - providing information to this variable will create a new Global Network. Conflicts with var.global_network_id .This variable expects the following attributes: - description = (string) Global Network's description.- tags = (Optional|map(string)) Tags to apply to the Global Network. |
any |
{} |
no |
global_network_id | (Optional) Global Network ID. Conflicts with var.global_network . |
string |
null |
no |
ipv4_network_definition | Definition of the IPv4 CIDR blocks of the AWS network - needed for the VPC routes in Ingress and Egress VPC types. You can specific either a CIDR range or a Prefix List ID. | string |
null |
no |
tags | (Optional) Tags to apply to all resources. | map(string) |
{} |
no |
Name | Description |
---|---|
aws_network_firewall | AWS Network Firewall. Full output of aws_networkfirewall_firewall. |
central_vpcs | Central VPC information. Full output of VPC module - https://registry.terraform.io/modules/aws-ia/vpc/aws/latest. |
core_network | Core Network. Full output of aws_networkmanager_core_network. |
global_network | Global Network. Full output of aws_networkmanager_global_network. |
ram_resource_share | Resource Access Manager (RAM) Resource Share. Full output of aws_ram_resource_share. |