Add support for policy based routes to net-vpc (#1926)
* Add support for PBR to net-vpc
This commit is contained in:
parent
5f323a767a
commit
ca3c86cb5c
|
@ -17,6 +17,7 @@ This module allows creation and management of VPC networks including subnetworks
|
|||
- [DNS Policies](#dns-policies)
|
||||
- [Subnet Factory](#subnet-factory)
|
||||
- [Custom Routes](#custom-routes)
|
||||
- [Policy Based Routes](#policy-based-routes)
|
||||
- [Private Google Access routes](#private-google-access-routes)
|
||||
- [Allow Firewall Policy to be evaluated before Firewall Rules](#allow-firewall-policy-to-be-evaluated-before-firewall-rules)
|
||||
- [IPv6](#ipv6)
|
||||
|
@ -455,6 +456,40 @@ module "vpc" {
|
|||
# tftest modules=5 resources=15 inventory=routes.yaml
|
||||
```
|
||||
|
||||
### Policy Based Routes
|
||||
|
||||
Policy based routes can be configured through the `policy_based_routes` variable.
|
||||
|
||||
```hcl
|
||||
module "vpc" {
|
||||
source = "./fabric/modules/net-vpc"
|
||||
project_id = var.project_id
|
||||
name = "my-vpc"
|
||||
policy_based_routes = {
|
||||
skip-pbr-for-nva = {
|
||||
use_default_routing = true
|
||||
priority = 100
|
||||
target = {
|
||||
tags = ["nva"]
|
||||
}
|
||||
}
|
||||
send-all-to-nva = {
|
||||
next_hop_ilb_ip = "10.0.0.253"
|
||||
priority = 101
|
||||
filter = {
|
||||
src_range = "10.0.0.0/8"
|
||||
dest_range = "0.0.0.0/0"
|
||||
}
|
||||
target = {
|
||||
interconnect_attachment = "europe-west8"
|
||||
}
|
||||
}
|
||||
}
|
||||
create_googleapis_routes = null
|
||||
}
|
||||
# tftest modules=1 resources=3 inventory=pbr.yaml
|
||||
```
|
||||
|
||||
### Private Google Access routes
|
||||
|
||||
By default the VPC module creates IPv4 routes for the [Private Google Access ranges](https://cloud.google.com/vpc/docs/configure-private-google-access#config-routing). This behavior can be controlled through the `create_googleapis_routes` variable:
|
||||
|
@ -541,7 +576,7 @@ module "vpc" {
|
|||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [name](variables.tf#L95) | The name of the network being created. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L111) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L159) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
|
||||
| [auto_create_subnetworks](variables.tf#L17) | Set to true to create an auto mode subnet, defaults to custom mode. | <code>bool</code> | | <code>false</code> |
|
||||
| [create_googleapis_routes](variables.tf#L23) | Toggle creation of googleapis private/restricted routes. Disabled when vpc creation is turned off, or when set to null. | <code title="object({ private = optional(bool, true) private-6 = optional(bool, false) restricted = optional(bool, true) restricted-6 = optional(bool, false) })">object({…})</code> | | <code>{}</code> |
|
||||
| [delete_default_routes_on_create](variables.tf#L34) | Set to true to delete the default routes at creation time. | <code>bool</code> | | <code>false</code> |
|
||||
|
@ -552,15 +587,16 @@ module "vpc" {
|
|||
| [ipv6_config](variables.tf#L79) | Optional IPv6 configuration for this network. | <code title="object({ enable_ula_internal = optional(bool) internal_range = optional(string) })">object({…})</code> | | <code>{}</code> |
|
||||
| [mtu](variables.tf#L89) | Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes. | <code>number</code> | | <code>null</code> |
|
||||
| [peering_config](variables.tf#L100) | VPC peering configuration. | <code title="object({ peer_vpc_self_link = string create_remote_peer = optional(bool, true) export_routes = optional(bool) import_routes = optional(bool) })">object({…})</code> | | <code>null</code> |
|
||||
| [psa_config](variables.tf#L116) | The Private Service Access configuration for Service Networking. | <code title="object({ ranges = map(string) export_routes = optional(bool, false) import_routes = optional(bool, false) peered_domains = optional(list(string), []) })">object({…})</code> | | <code>null</code> |
|
||||
| [routes](variables.tf#L127) | Network routes, keyed by name. | <code title="map(object({ description = optional(string, "Terraform-managed.") dest_range = string next_hop_type = string # gateway, instance, ip, vpn_tunnel, ilb next_hop = string priority = optional(number) tags = optional(list(string)) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [routing_mode](variables.tf#L148) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>"GLOBAL"</code> |
|
||||
| [shared_vpc_host](variables.tf#L158) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
|
||||
| [shared_vpc_service_projects](variables.tf#L164) | Shared VPC service projects to register with this host. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [subnets](variables.tf#L170) | Subnet configuration. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) enable_private_access = optional(bool, true) flow_logs_config = optional(object({ aggregation_interval = optional(string) filter_expression = optional(string) flow_sampling = optional(number) metadata = optional(string) metadata_fields = optional(list(string)) })) ipv6 = optional(object({ access_type = optional(string, "INTERNAL") })) secondary_ip_ranges = optional(map(string)) iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ role = string members = list(string) condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) iam_bindings_additive = optional(map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [subnets_proxy_only](variables.tf#L217) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) active = optional(bool, true) global = optional(bool, false) iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ role = string members = list(string) condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) iam_bindings_additive = optional(map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [subnets_psc](variables.tf#L251) | List of subnets for Private Service Connect service producers. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ role = string members = list(string) condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) iam_bindings_additive = optional(map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [vpc_create](variables.tf#L283) | Create VPC. When set to false, uses a data source to reference existing VPC. | <code>bool</code> | | <code>true</code> |
|
||||
| [policy_based_routes](variables.tf#L111) | Policy based routes, keyed by name. | <code title="map(object({ description = optional(string, "Terraform-managed.") labels = optional(map(string)) priority = optional(number) next_hop_ilb_ip = optional(string) use_default_routing = optional(bool, false) filter = optional(object({ ip_protocol = optional(string) dest_range = optional(string) src_range = optional(string) }), {}) target = optional(object({ interconnect_attachment = optional(string) tags = optional(list(string)) }), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [psa_config](variables.tf#L164) | The Private Service Access configuration for Service Networking. | <code title="object({ ranges = map(string) export_routes = optional(bool, false) import_routes = optional(bool, false) peered_domains = optional(list(string), []) })">object({…})</code> | | <code>null</code> |
|
||||
| [routes](variables.tf#L175) | Network routes, keyed by name. | <code title="map(object({ description = optional(string, "Terraform-managed.") dest_range = string next_hop_type = string # gateway, instance, ip, vpn_tunnel, ilb next_hop = string priority = optional(number) tags = optional(list(string)) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [routing_mode](variables.tf#L196) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>"GLOBAL"</code> |
|
||||
| [shared_vpc_host](variables.tf#L206) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
|
||||
| [shared_vpc_service_projects](variables.tf#L212) | Shared VPC service projects to register with this host. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [subnets](variables.tf#L218) | Subnet configuration. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) enable_private_access = optional(bool, true) flow_logs_config = optional(object({ aggregation_interval = optional(string) filter_expression = optional(string) flow_sampling = optional(number) metadata = optional(string) metadata_fields = optional(list(string)) })) ipv6 = optional(object({ access_type = optional(string, "INTERNAL") })) secondary_ip_ranges = optional(map(string)) iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ role = string members = list(string) condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) iam_bindings_additive = optional(map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [subnets_proxy_only](variables.tf#L265) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) active = optional(bool, true) global = optional(bool, false) iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ role = string members = list(string) condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) iam_bindings_additive = optional(map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [subnets_psc](variables.tf#L299) | List of subnets for Private Service Connect service producers. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ role = string members = list(string) condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) iam_bindings_additive = optional(map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) })), {}) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [vpc_create](variables.tf#L331) | Create VPC. When set to false, uses a data source to reference existing VPC. | <code>bool</code> | | <code>true</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
|
|
@ -108,3 +108,32 @@ resource "google_compute_route" "vpn_tunnel" {
|
|||
tags = each.value.tags
|
||||
next_hop_vpn_tunnel = each.value.next_hop
|
||||
}
|
||||
|
||||
resource "google_network_connectivity_policy_based_route" "default" {
|
||||
for_each = var.policy_based_routes
|
||||
project = var.project_id
|
||||
network = local.network.id
|
||||
name = "${var.name}-${each.key}"
|
||||
description = each.value.description
|
||||
priority = each.value.priority
|
||||
next_hop_other_routes = each.value.use_default_routing ? "DEFAULT_ROUTING" : null
|
||||
next_hop_ilb_ip = each.value.use_default_routing ? null : each.value.next_hop_ilb_ip
|
||||
filter {
|
||||
protocol_version = "IPV4"
|
||||
ip_protocol = each.value.filter.ip_protocol
|
||||
dest_range = each.value.filter.dest_range
|
||||
src_range = each.value.filter.src_range
|
||||
}
|
||||
dynamic "virtual_machine" {
|
||||
for_each = each.value.target.tags != null ? [""] : []
|
||||
content {
|
||||
tags = each.value.target.tags
|
||||
}
|
||||
}
|
||||
dynamic "interconnect_attachment" {
|
||||
for_each = each.value.target.interconnect_attachment != null ? [""] : []
|
||||
content {
|
||||
region = each.value.target.interconnect_attachment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,54 @@ variable "peering_config" {
|
|||
default = null
|
||||
}
|
||||
|
||||
variable "policy_based_routes" {
|
||||
description = "Policy based routes, keyed by name."
|
||||
type = map(object({
|
||||
description = optional(string, "Terraform-managed.")
|
||||
labels = optional(map(string))
|
||||
priority = optional(number)
|
||||
next_hop_ilb_ip = optional(string)
|
||||
use_default_routing = optional(bool, false)
|
||||
filter = optional(object({
|
||||
ip_protocol = optional(string)
|
||||
dest_range = optional(string)
|
||||
src_range = optional(string)
|
||||
}), {})
|
||||
target = optional(object({
|
||||
interconnect_attachment = optional(string)
|
||||
tags = optional(list(string))
|
||||
}), {})
|
||||
}))
|
||||
default = {}
|
||||
nullable = false
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for r in var.policy_based_routes :
|
||||
contains(["TCP", "UDP", "ALL", null], r.filter.ip_protocol)
|
||||
if r.filter.ip_protocol != null
|
||||
])
|
||||
error_message = "Unsupported protocol for route."
|
||||
}
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for r in var.policy_based_routes :
|
||||
(
|
||||
(r.use_default_routing == true ? 1 : 0)
|
||||
+
|
||||
(r.next_hop_ilb_ip != null ? 1 : 0)
|
||||
) == 1
|
||||
])
|
||||
error_message = "Either set `use_default_routing = true` or specify an internal passthrough LB IP."
|
||||
}
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for r in var.policy_based_routes :
|
||||
r.target.tags == null || r.target.interconnect_attachment == null
|
||||
])
|
||||
error_message = "Either use virtual machine tags or a vlan attachment region as a target."
|
||||
}
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
description = "The ID of the project where this VPC will be created."
|
||||
type = string
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
# Copyright 2023 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
values:
|
||||
module.vpc.google_compute_network.network[0]:
|
||||
auto_create_subnetworks: false
|
||||
delete_default_routes_on_create: false
|
||||
description: Terraform-managed.
|
||||
enable_ula_internal_ipv6: null
|
||||
name: my-vpc
|
||||
network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL
|
||||
project: project-id
|
||||
routing_mode: GLOBAL
|
||||
timeouts: null
|
||||
? module.vpc.google_network_connectivity_policy_based_route.default["send-all-to-nva"]
|
||||
: description: Terraform-managed.
|
||||
filter:
|
||||
- dest_range: 0.0.0.0/0
|
||||
ip_protocol: ALL
|
||||
protocol_version: IPV4
|
||||
src_range: 10.0.0.0/8
|
||||
interconnect_attachment:
|
||||
- region: europe-west8
|
||||
labels: null
|
||||
name: my-vpc-send-all-to-nva
|
||||
next_hop_ilb_ip: 10.0.0.253
|
||||
next_hop_other_routes: null
|
||||
priority: 101
|
||||
project: project-id
|
||||
timeouts: null
|
||||
virtual_machine: []
|
||||
? module.vpc.google_network_connectivity_policy_based_route.default["skip-pbr-for-nva"]
|
||||
: description: Terraform-managed.
|
||||
filter:
|
||||
- dest_range: 0.0.0.0/0
|
||||
ip_protocol: ALL
|
||||
protocol_version: IPV4
|
||||
src_range: 0.0.0.0/0
|
||||
interconnect_attachment: []
|
||||
labels: null
|
||||
name: my-vpc-skip-pbr-for-nva
|
||||
next_hop_ilb_ip: null
|
||||
next_hop_other_routes: DEFAULT_ROUTING
|
||||
priority: 100
|
||||
project: project-id
|
||||
timeouts: null
|
||||
virtual_machine:
|
||||
- tags:
|
||||
- nva
|
||||
|
||||
counts:
|
||||
google_compute_network: 1
|
||||
google_network_connectivity_policy_based_route: 2
|
||||
modules: 1
|
||||
resources: 3
|
||||
|
||||
outputs: {}
|
Loading…
Reference in New Issue