Add support for ipv6 to net-vpc module (#1568)

* add support for ipv6

* fix test
This commit is contained in:
Ludovico Magnocavallo 2023-08-05 13:07:26 +02:00 committed by GitHub
parent a6c90f2ba7
commit aecba0bbd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 185 additions and 29 deletions

View File

@ -19,6 +19,7 @@ This module allows creation and management of VPC networks including subnetworks
- [Custom Routes](#custom-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)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->
@ -475,13 +476,47 @@ module "vpc" {
}
# tftest modules=1 resources=5 inventory=firewall_policy_enforcement_order.yaml
```
### IPv6
A non-overlapping private IPv6 address space can be configured for the VPC via the `ipv6_config` variable. If an internal range is not specified, a unique /48 ULA prefix from the `fd20::/20` range is assigned.
```hcl
module "vpc" {
source = "./fabric/modules/net-vpc"
project_id = "my-project"
name = "my-network"
ipv6_config = {
# internal_range is optional
enable_ula_internal = true
internal_range = "fd20:6b2:27e5:0:0:0:0:0/48"
}
subnets = [
{
ip_cidr_range = "10.0.0.0/24"
name = "test"
region = "europe-west1"
ipv6 = {}
},
{
ip_cidr_range = "10.0.1.0/24"
name = "test"
region = "europe-west3"
ipv6 = {
access_type = "EXTERNAL"
}
}
]
}
# tftest modules=1 resources=5 inventory=ipv6.yaml
```
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L83) | The name of the network being created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L99) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
| [name](variables.tf#L93) | The name of the network being created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L109) | 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&#40;&#123;&#10; private &#61; optional&#40;bool, true&#41;&#10; private-6 &#61; optional&#40;bool, false&#41;&#10; restricted &#61; optional&#40;bool, true&#41;&#10; restricted-6 &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [data_folder](variables.tf#L34) | An optional folder containing the subnet configurations in YaML format. | <code>string</code> | | <code>null</code> |
@ -489,19 +524,20 @@ module "vpc" {
| [description](variables.tf#L46) | An optional description of this resource (triggers recreation on change). | <code>string</code> | | <code>&#34;Terraform-managed.&#34;</code> |
| [dns_policy](variables.tf#L52) | DNS policy setup for the VPC. | <code title="object&#40;&#123;&#10; inbound &#61; optional&#40;bool&#41;&#10; logging &#61; optional&#40;bool&#41;&#10; outbound &#61; optional&#40;object&#40;&#123;&#10; private_ns &#61; list&#40;string&#41;&#10; public_ns &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [firewall_policy_enforcement_order](variables.tf#L65) | Order that Firewall Rules and Firewall Policies are evaluated. Can be either 'BEFORE_CLASSIC_FIREWALL' or 'AFTER_CLASSIC_FIREWALL'. | <code>string</code> | | <code>&#34;AFTER_CLASSIC_FIREWALL&#34;</code> |
| [mtu](variables.tf#L77) | 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#L88) | VPC peering configuration. | <code title="object&#40;&#123;&#10; peer_vpc_self_link &#61; string&#10; create_remote_peer &#61; optional&#40;bool, true&#41;&#10; export_routes &#61; optional&#40;bool&#41;&#10; import_routes &#61; optional&#40;bool&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [psa_config](variables.tf#L104) | The Private Service Access configuration for Service Networking. | <code title="object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; export_routes &#61; optional&#40;bool, false&#41;&#10; import_routes &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [routes](variables.tf#L114) | Network routes, keyed by name. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; dest_range &#61; string&#10; next_hop_type &#61; string &#35; gateway, instance, ip, vpn_tunnel, ilb&#10; next_hop &#61; string&#10; priority &#61; optional&#40;number&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [routing_mode](variables.tf#L135) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>&#34;GLOBAL&#34;</code> |
| [shared_vpc_host](variables.tf#L145) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L151) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnet_iam](variables.tf#L157) | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [subnet_iam_additive](variables.tf#L163) | Subnet IAM additive bindings in {REGION/NAME => {ROLE => [MEMBERS]}} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [subnets](variables.tf#L170) | Subnet configuration. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; flow_logs_config &#61; optional&#40;object&#40;&#123;&#10; aggregation_interval &#61; optional&#40;string&#41;&#10; filter_expression &#61; optional&#40;string&#41;&#10; flow_sampling &#61; optional&#40;number&#41;&#10; metadata &#61; optional&#40;string&#41;&#10; metadata_fields &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; ipv6 &#61; optional&#40;object&#40;&#123;&#10; access_type &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; &#125;&#41;&#41;&#10; secondary_ip_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L195) | 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&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; active &#61; bool&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L207) | List of subnets for Private Service Connect service producers. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_create](variables.tf#L218) | Create VPC. When set to false, uses a data source to reference existing VPC. | <code>bool</code> | | <code>true</code> |
| [ipv6_config](variables.tf#L77) | Optional IPv6 configuration for this network. | <code title="object&#40;&#123;&#10; enable_ula_internal &#61; optional&#40;bool&#41;&#10; internal_range &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [mtu](variables.tf#L87) | 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#L98) | VPC peering configuration. | <code title="object&#40;&#123;&#10; peer_vpc_self_link &#61; string&#10; create_remote_peer &#61; optional&#40;bool, true&#41;&#10; export_routes &#61; optional&#40;bool&#41;&#10; import_routes &#61; optional&#40;bool&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [psa_config](variables.tf#L114) | The Private Service Access configuration for Service Networking. | <code title="object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; export_routes &#61; optional&#40;bool, false&#41;&#10; import_routes &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [routes](variables.tf#L124) | Network routes, keyed by name. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; dest_range &#61; string&#10; next_hop_type &#61; string &#35; gateway, instance, ip, vpn_tunnel, ilb&#10; next_hop &#61; string&#10; priority &#61; optional&#40;number&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [routing_mode](variables.tf#L145) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>&#34;GLOBAL&#34;</code> |
| [shared_vpc_host](variables.tf#L155) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L161) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnet_iam](variables.tf#L167) | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [subnet_iam_additive](variables.tf#L173) | Subnet IAM additive bindings in {REGION/NAME => {ROLE => [MEMBERS]}} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [subnets](variables.tf#L180) | Subnet configuration. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; flow_logs_config &#61; optional&#40;object&#40;&#123;&#10; aggregation_interval &#61; optional&#40;string&#41;&#10; filter_expression &#61; optional&#40;string&#41;&#10; flow_sampling &#61; optional&#40;number&#41;&#10; metadata &#61; optional&#40;string&#41;&#10; metadata_fields &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; ipv6 &#61; optional&#40;object&#40;&#123;&#10; access_type &#61; optional&#40;string, &#34;INTERNAL&#34;&#41;&#10; &#125;&#41;&#41;&#10; secondary_ip_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L206) | 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&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; active &#61; bool&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L218) | List of subnets for Private Service Connect service producers. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_create](variables.tf#L229) | Create VPC. When set to false, uses a data source to reference existing VPC. | <code>bool</code> | | <code>true</code> |
## Outputs
@ -509,16 +545,18 @@ module "vpc" {
|---|---|:---:|
| [bindings](outputs.tf#L17) | Subnet IAM bindings. | |
| [id](outputs.tf#L22) | Fully qualified network id. | |
| [name](outputs.tf#L34) | Network name. | |
| [network](outputs.tf#L46) | Network resource. | |
| [project_id](outputs.tf#L58) | Project ID containing the network. Use this when you need to create resources *after* the VPC is fully set up (e.g. subnets created, shared VPC service projects attached, Private Service Networking configured). | |
| [self_link](outputs.tf#L71) | Network self link. | |
| [subnet_ids](outputs.tf#L83) | Map of subnet IDs keyed by name. | |
| [subnet_ips](outputs.tf#L88) | Map of subnet address ranges keyed by name. | |
| [subnet_regions](outputs.tf#L95) | Map of subnet regions keyed by name. | |
| [subnet_secondary_ranges](outputs.tf#L102) | Map of subnet secondary ranges keyed by name. | |
| [subnet_self_links](outputs.tf#L113) | Map of subnet self links keyed by name. | |
| [subnets](outputs.tf#L118) | Subnet resources. | |
| [subnets_proxy_only](outputs.tf#L123) | L7 ILB or L7 Regional LB subnet resources. | |
| [subnets_psc](outputs.tf#L128) | Private Service Connect subnet resources. | |
| [internal_ipv6_range](outputs.tf#L34) | ULA range. | |
| [name](outputs.tf#L39) | Network name. | |
| [network](outputs.tf#L51) | Network resource. | |
| [project_id](outputs.tf#L63) | Project ID containing the network. Use this when you need to create resources *after* the VPC is fully set up (e.g. subnets created, shared VPC service projects attached, Private Service Networking configured). | |
| [self_link](outputs.tf#L76) | Network self link. | |
| [subnet_ids](outputs.tf#L88) | Map of subnet IDs keyed by name. | |
| [subnet_ips](outputs.tf#L93) | Map of subnet address ranges keyed by name. | |
| [subnet_ipv6_external_prefixes](outputs.tf#L100) | Map of subnet external IPv6 prefixes keyed by name. | |
| [subnet_regions](outputs.tf#L108) | Map of subnet regions keyed by name. | |
| [subnet_secondary_ranges](outputs.tf#L115) | Map of subnet secondary ranges keyed by name. | |
| [subnet_self_links](outputs.tf#L126) | Map of subnet self links keyed by name. | |
| [subnets](outputs.tf#L131) | Subnet resources. | |
| [subnets_proxy_only](outputs.tf#L136) | L7 ILB or L7 Regional LB subnet resources. | |
| [subnets_psc](outputs.tf#L141) | Private Service Connect subnet resources. | |
<!-- END TFDOC -->

View File

@ -43,6 +43,8 @@ resource "google_compute_network" "network" {
mtu = var.mtu
routing_mode = var.routing_mode
network_firewall_policy_enforcement_order = var.firewall_policy_enforcement_order
enable_ula_internal_ipv6 = var.ipv6_config.enable_ula_internal
internal_ipv6_range = var.ipv6_config.internal_range
}
resource "google_compute_network_peering" "local" {

View File

@ -31,6 +31,11 @@ output "id" {
]
}
output "internal_ipv6_range" {
description = "ULA range."
value = try(local.network.internal_ipv6_range, null)
}
output "name" {
description = "Network name."
value = local.network.name
@ -92,6 +97,14 @@ output "subnet_ips" {
}
}
output "subnet_ipv6_external_prefixes" {
description = "Map of subnet external IPv6 prefixes keyed by name."
value = {
for k, v in google_compute_subnetwork.subnetwork :
k => try(v.external_ipv6_prefix, null)
}
}
output "subnet_regions" {
description = "Map of subnet regions keyed by name."
value = {

View File

@ -112,6 +112,13 @@ resource "google_compute_subnetwork" "subnetwork" {
for name, range in each.value.secondary_ip_ranges :
{ range_name = name, ip_cidr_range = range }
]
stack_type = (
try(each.value.ipv6, null) != null ? "IPV4_IPV6" : null
)
ipv6_access_type = (
try(each.value.ipv6, null) != null ? each.value.ipv6.access_type : null
)
# private_ipv6_google_access = try(each.value.ipv6.enable_private_access, null)
dynamic "log_config" {
for_each = each.value.flow_logs_config != null ? [""] : []
content {

View File

@ -74,6 +74,16 @@ variable "firewall_policy_enforcement_order" {
}
}
variable "ipv6_config" {
description = "Optional IPv6 configuration for this network."
type = object({
enable_ula_internal = optional(bool)
internal_range = optional(string)
})
nullable = false
default = {}
}
variable "mtu" {
description = "Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes."
type = number
@ -184,8 +194,9 @@ variable "subnets" {
metadata_fields = optional(list(string))
}))
ipv6 = optional(object({
access_type = optional(string)
enable_private_access = optional(bool, true)
access_type = optional(string, "INTERNAL")
# this field is marked for internal use in the API documentation
# enable_private_access = optional(string)
}))
secondary_ip_ranges = optional(map(string))
}))

View File

@ -0,0 +1,85 @@
# 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: true
internal_ipv6_range: fd20:6b2:27e5:0:0:0:0:0/48
name: my-network
network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL
project: my-project
routing_mode: GLOBAL
timeouts: null
module.vpc.google_compute_route.gateway["private-googleapis"]:
description: Terraform-managed.
dest_range: 199.36.153.8/30
name: my-network-private-googleapis
next_hop_gateway: default-internet-gateway
next_hop_ilb: null
next_hop_instance: null
next_hop_vpn_tunnel: null
priority: 1000
project: my-project
tags: null
timeouts: null
module.vpc.google_compute_route.gateway["restricted-googleapis"]:
description: Terraform-managed.
dest_range: 199.36.153.4/30
name: my-network-restricted-googleapis
next_hop_gateway: default-internet-gateway
next_hop_ilb: null
next_hop_instance: null
next_hop_vpn_tunnel: null
priority: 1000
project: my-project
tags: null
timeouts: null
module.vpc.google_compute_subnetwork.subnetwork["europe-west1/test"]:
description: Terraform-managed.
ip_cidr_range: 10.0.0.0/24
ipv6_access_type: INTERNAL
log_config: []
name: test
private_ip_google_access: true
project: my-project
region: europe-west1
role: null
secondary_ip_range: []
stack_type: IPV4_IPV6
timeouts: null
module.vpc.google_compute_subnetwork.subnetwork["europe-west3/test"]:
description: Terraform-managed.
ip_cidr_range: 10.0.1.0/24
ipv6_access_type: EXTERNAL
log_config: []
name: test
private_ip_google_access: true
project: my-project
region: europe-west3
role: null
secondary_ip_range: []
stack_type: IPV4_IPV6
timeouts: null
counts:
google_compute_network: 1
google_compute_route: 2
google_compute_subnetwork: 2
modules: 1
resources: 5
outputs: {}