From eb0ed0c2a3e4d16ef8f25cbd90c30a4cddfad26a Mon Sep 17 00:00:00 2001 From: Simone Ruffilli Date: Sun, 10 Mar 2024 14:06:49 +0100 Subject: [PATCH] Adds bfd and md5 auth support to google_compute_router_peer (#2142) * Adds support for md5 auth to net-vlan-attachment * Adds support for md5 auth to net-ipsec-over-interconnect * Adds support for md5 auth to net-vpn-ha * Adds support for BFD to net-vpn-ha --- modules/net-ipsec-over-interconnect/README.md | 7 +- modules/net-ipsec-over-interconnect/main.tf | 9 +++ .../net-ipsec-over-interconnect/variables.tf | 10 ++- modules/net-vlan-attachment/README.md | 68 ++++++++++++++++--- modules/net-vlan-attachment/main.tf | 16 +++-- modules/net-vlan-attachment/variables.tf | 22 +++--- modules/net-vpn-ha/README.md | 32 +++++++-- modules/net-vpn-ha/main.tf | 16 +++++ modules/net-vpn-ha/variables.tf | 18 +++-- 9 files changed, 164 insertions(+), 34 deletions(-) diff --git a/modules/net-ipsec-over-interconnect/README.md b/modules/net-ipsec-over-interconnect/README.md index 5cadae3222..8dd0a64713 100644 --- a/modules/net-ipsec-over-interconnect/README.md +++ b/modules/net-ipsec-over-interconnect/README.md @@ -64,6 +64,11 @@ module "vpngw-a" { bgp_peer = { address = "169.254.1.2" asn = 64514 + # MD5 Authentication is optional + md5_authentication_key = { + name = "foo" + key = "bar" + } } bgp_session_range = "169.254.1.1/30" shared_secret = "foobar" @@ -112,7 +117,7 @@ module "vpngw-a" { | [project_id](variables.tf#L54) | The project id. | string | ✓ | | | [region](variables.tf#L59) | GCP Region. | string | ✓ | | | [router_config](variables.tf#L64) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | -| [tunnels](variables.tf#L79) | VPN tunnel configurations. | map(object({…})) | | {} | +| [tunnels](variables.tf#L79) | VPN tunnel configurations. | map(object({…})) | | {} | ## Outputs diff --git a/modules/net-ipsec-over-interconnect/main.tf b/modules/net-ipsec-over-interconnect/main.tf index 06294add99..9fe30d15db 100644 --- a/modules/net-ipsec-over-interconnect/main.tf +++ b/modules/net-ipsec-over-interconnect/main.tf @@ -116,6 +116,15 @@ resource "google_compute_router_peer" "default" { description = range.value } } + + dynamic "md5_authentication_key" { + for_each = each.value.bgp_peer.md5_authentication_key != null ? [each.value.bgp_peer.md5_authentication_key] : [] + content { + name = md5_authentication_key.value.name + key = md5_authentication_key.value.key + } + } + interface = google_compute_router_interface.default[each.key].name } diff --git a/modules/net-ipsec-over-interconnect/variables.tf b/modules/net-ipsec-over-interconnect/variables.tf index 25cf0cf240..780d40b962 100644 --- a/modules/net-ipsec-over-interconnect/variables.tf +++ b/modules/net-ipsec-over-interconnect/variables.tf @@ -80,15 +80,19 @@ variable "tunnels" { description = "VPN tunnel configurations." type = map(object({ bgp_peer = object({ - address = string - asn = number - route_priority = optional(number, 1000) + address = string + asn = number custom_advertise = optional(object({ all_subnets = bool all_vpc_subnets = bool all_peer_vpc_subnets = bool ip_ranges = map(string) })) + md5_authentication_key = optional(object({ + name = string + key = string + })) + route_priority = optional(number, 1000) }) # each BGP session on the same Cloud Router must use a unique /30 CIDR # from the 169.254.0.0/16 block. diff --git a/modules/net-vlan-attachment/README.md b/modules/net-vlan-attachment/README.md index a17117096f..6520ebc2c7 100644 --- a/modules/net-vlan-attachment/README.md +++ b/modules/net-vlan-attachment/README.md @@ -47,6 +47,60 @@ module "example-va" { # tftest modules=1 resources=4 ``` +### Dedicated Interconnect - Single VLAN Attachment (No SLA) - BFD and MD5 Auth + +```hcl +resource "google_compute_router" "interconnect-router" { + name = "interconnect-router" + network = "mynet" + project = "myproject" + region = "europe-west8" + bgp { + advertise_mode = "CUSTOM" + asn = 64514 + advertised_groups = ["ALL_SUBNETS"] + advertised_ip_ranges { + range = "10.255.255.0/24" + } + advertised_ip_ranges { + range = "192.168.255.0/24" + } + } +} + +module "example-va" { + source = "./fabric/modules/net-vlan-attachment" + network = "mynet" + project_id = "myproject" + region = "europe-west8" + name = "vlan-attachment" + description = "Example vlan attachment" + peer_asn = "65000" + router_config = { + create = false + name = google_compute_router.interconnect-router.name + bfd = { + min_receive_interval = 1000 + min_transmit_interval = 1000 + multiplier = 5 + session_initialization_mode = "ACTIVE" + } + md5_authentication_key = { + name = "foo" + key = "bar" + } + } + dedicated_interconnect_config = { + bandwidth = "BPS_10G" + bgp_range = "169.254.0.0/30" + interconnect = "interconnect-a" + vlan_tag = 12345 + } +} + +# tftest modules=1 resources=4 +``` + ### Partner Interconnect - Single VLAN Attachment (No SLA) ```hcl @@ -434,7 +488,7 @@ module "example-va-b-ew12" { # tftest modules=4 resources=6 ``` -### IPSec for Dedicated Interconnect +### IPSec for Dedicated Interconnect Refer to the [HA VPN over Interconnect Blueprint](../../blueprints/networking/ha-vpn-over-interconnect/) for an all-encompassing example. @@ -495,7 +549,7 @@ module "example-va-b" { # tftest modules=2 resources=9 ``` -### IPSec for Partner Interconnect +### IPSec for Partner Interconnect ```hcl module "example-va-a" { @@ -533,10 +587,7 @@ module "example-va-b" { } # tftest modules=2 resources=6 ``` - - - ## Variables | name | description | type | required | default | @@ -547,14 +598,14 @@ module "example-va-b" { | [peer_asn](variables.tf#L74) | The on-premises underlay router ASN. | string | ✓ | | | [project_id](variables.tf#L79) | The project id where resources are created. | string | ✓ | | | [region](variables.tf#L84) | The region where resources are created. | string | ✓ | | -| [router_config](variables.tf#L89) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | +| [router_config](variables.tf#L89) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | | [admin_enabled](variables.tf#L17) | Whether the VLAN attachment is enabled. | bool | | true | | [dedicated_interconnect_config](variables.tf#L23) | Partner interconnect configuration. | object({…}) | | null | | [ipsec_gateway_ip_ranges](variables.tf#L40) | IPSec Gateway IP Ranges. | map(string) | | {} | | [mtu](variables.tf#L46) | The MTU associated to the VLAN attachment (1440 / 1500). | number | | 1500 | | [partner_interconnect_config](variables.tf#L62) | Partner interconnect configuration. | object({…}) | | null | -| [vlan_tag](variables.tf#L110) | The VLAN id to be used for this VLAN attachment. | number | | null | -| [vpn_gateways_ip_range](variables.tf#L116) | The IP range (cidr notation) to be used for the GCP VPN gateways. If null IPSec over Interconnect is not enabled. | string | | null | +| [vlan_tag](variables.tf#L114) | The VLAN id to be used for this VLAN attachment. | number | | null | +| [vpn_gateways_ip_range](variables.tf#L120) | The IP range (cidr notation) to be used for the GCP VPN gateways. If null IPSec over Interconnect is not enabled. | string | | null | ## Outputs @@ -567,5 +618,4 @@ module "example-va-b" { | [router](outputs.tf#L37) | Router resource (only if auto-created). | | | [router_interface](outputs.tf#L42) | Router interface created for the VLAN attachment. | | | [router_name](outputs.tf#L47) | Router name. | | - diff --git a/modules/net-vlan-attachment/main.tf b/modules/net-vlan-attachment/main.tf index 5cf5c328e4..5b59933f7f 100644 --- a/modules/net-vlan-attachment/main.tf +++ b/modules/net-vlan-attachment/main.tf @@ -136,10 +136,18 @@ resource "google_compute_router_peer" "default" { dynamic "bfd" { for_each = var.router_config.bfd != null ? toset([var.router_config.bfd]) : [] content { - session_initialization_mode = bfd.session_initialization_mode - min_receive_interval = bfd.min_receive_interval - min_transmit_interval = bfd.min_transmit_interval - multiplier = bfd.multiplier + session_initialization_mode = bfd.value.session_initialization_mode + min_receive_interval = bfd.value.min_receive_interval + min_transmit_interval = bfd.value.min_transmit_interval + multiplier = bfd.value.multiplier + } + } + + dynamic "md5_authentication_key" { + for_each = var.router_config.md5_authentication_key != null ? [var.router_config.md5_authentication_key] : [] + content { + name = md5_authentication_key.value.name + key = md5_authentication_key.value.key } } diff --git a/modules/net-vlan-attachment/variables.tf b/modules/net-vlan-attachment/variables.tf index 941003f923..fd2b47530f 100644 --- a/modules/net-vlan-attachment/variables.tf +++ b/modules/net-vlan-attachment/variables.tf @@ -89,20 +89,24 @@ variable "region" { variable "router_config" { description = "Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router." type = object({ - create = optional(bool, true) - asn = optional(number, 65001) - name = optional(string, "router") - keepalive = optional(number) - custom_advertise = optional(object({ - all_subnets = bool - ip_ranges = map(string) - })) + create = optional(bool, true) + asn = optional(number, 65001) bfd = optional(object({ - session_initialization_mode = optional(string, "ACTIVE") min_receive_interval = optional(number) min_transmit_interval = optional(number) multiplier = optional(number) + session_initialization_mode = optional(string, "ACTIVE") })) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) + md5_authentication_key = optional(object({ + name = string + key = string + })) + keepalive = optional(number) + name = optional(string, "router") }) nullable = false } diff --git a/modules/net-vpn-ha/README.md b/modules/net-vpn-ha/README.md index 46e39b3fe8..2de72f54ea 100644 --- a/modules/net-vpn-ha/README.md +++ b/modules/net-vpn-ha/README.md @@ -104,6 +104,18 @@ module "vpn_ha" { bgp_peer = { address = "169.254.1.1" asn = 64513 + # BFD is optional + bfd = { + min_receive_interval = 1000 + min_transmit_interval = 1000 + multiplier = 5 + session_initialization_mode = "ACTIVE" + } + # MD5 Authentication is optional + md5_authentication_key = { + name = "foo" + key = "bar" + } } bgp_session_range = "169.254.1.2/30" peer_external_gateway_interface = 0 @@ -114,6 +126,18 @@ module "vpn_ha" { bgp_peer = { address = "169.254.2.1" asn = 64513 + # BFD is optional + bfd = { + min_receive_interval = 1000 + min_transmit_interval = 1000 + multiplier = 5 + session_initialization_mode = "ACTIVE" + } + # MD5 Authentication is optional + md5_authentication_key = { + name = "foo" + key = "bar" + } } bgp_session_range = "169.254.2.2/30" peer_external_gateway_interface = 0 @@ -187,11 +211,11 @@ module "vpn_ha" { | [network](variables.tf#L22) | VPC used for the gateway and routes. | string | ✓ | | | [project_id](variables.tf#L47) | Project where resources will be created. | string | ✓ | | | [region](variables.tf#L52) | Region used for resources. | string | ✓ | | -| [router_config](variables.tf#L57) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | +| [router_config](variables.tf#L57) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | | [peer_gateways](variables.tf#L27) | Configuration of the (external or GCP) peer gateway. | map(object({…})) | | {} | -| [tunnels](variables.tf#L72) | VPN tunnel configurations. | map(object({…})) | | {} | -| [vpn_gateway](variables.tf#L104) | HA VPN Gateway Self Link for using an existing HA VPN Gateway. Ignored if `vpn_gateway_create` is set to `true`. | string | | null | -| [vpn_gateway_create](variables.tf#L110) | Create HA VPN Gateway. Set to null to avoid creation. | object({…}) | | {} | +| [tunnels](variables.tf#L72) | VPN tunnel configurations. | map(object({…})) | | {} | +| [vpn_gateway](variables.tf#L114) | HA VPN Gateway Self Link for using an existing HA VPN Gateway. Ignored if `vpn_gateway_create` is set to `true`. | string | | null | +| [vpn_gateway_create](variables.tf#L120) | Create HA VPN Gateway. Set to null to avoid creation. | object({…}) | | {} | ## Outputs diff --git a/modules/net-vpn-ha/main.tf b/modules/net-vpn-ha/main.tf index cc7bc5840f..20af29015a 100644 --- a/modules/net-vpn-ha/main.tf +++ b/modules/net-vpn-ha/main.tf @@ -117,6 +117,22 @@ resource "google_compute_router_peer" "bgp_peer" { description = range.value } } + dynamic "bfd" { + for_each = each.value.bgp_peer.bfd != null ? [each.value.bgp_peer.bfd] : [] + content { + session_initialization_mode = bfd.value.session_initialization_mode + min_receive_interval = bfd.value.min_receive_interval + min_transmit_interval = bfd.value.min_transmit_interval + multiplier = bfd.value.multiplier + } + } + dynamic "md5_authentication_key" { + for_each = each.value.bgp_peer.md5_authentication_key != null ? toset([each.value.bgp_peer.md5_authentication_key]) : [] + content { + name = md5_authentication_key.value.name + key = md5_authentication_key.value.key + } + } enable_ipv6 = try(each.value.bgp_peer.ipv6, null) == null ? false : true interface = google_compute_router_interface.router_interface[each.key].name ipv6_nexthop_address = try(each.value.bgp_peer.ipv6.nexthop_address, null) diff --git a/modules/net-vpn-ha/variables.tf b/modules/net-vpn-ha/variables.tf index d0f8710fd3..d507c89881 100644 --- a/modules/net-vpn-ha/variables.tf +++ b/modules/net-vpn-ha/variables.tf @@ -57,14 +57,14 @@ variable "region" { variable "router_config" { description = "Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router." type = object({ - create = optional(bool, true) - asn = number - name = optional(string) - keepalive = optional(number) + asn = number + create = optional(bool, true) custom_advertise = optional(object({ all_subnets = bool ip_ranges = map(string) })) + keepalive = optional(number) + name = optional(string) }) nullable = false } @@ -76,12 +76,22 @@ variable "tunnels" { address = string asn = number route_priority = optional(number, 1000) + bfd = optional(object({ + min_receive_interval = optional(number) + min_transmit_interval = optional(number) + multiplier = optional(number) + session_initialization_mode = optional(string, "ACTIVE") + })) custom_advertise = optional(object({ all_subnets = bool all_vpc_subnets = bool all_peer_vpc_subnets = bool ip_ranges = map(string) })) + md5_authentication_key = optional(object({ + name = string + key = string + })) ipv6 = optional(object({ nexthop_address = optional(string) peer_nexthop_address = optional(string)