From ea4469e19c75e01d1a3802d2f3c545056a7a0634 Mon Sep 17 00:00:00 2001
From: David Ferguson <155442377+davidferguson-telana@users.noreply.github.com>
Date: Tue, 17 Mar 2026 08:39:07 +0000
Subject: [PATCH] Add support for cipher suite configuration on net-vpn-*
modules (#3790)
---
modules/README.md | 2 +-
modules/net-vpn-dynamic/README.md | 81 ++++-
modules/net-vpn-dynamic/main.tf | 26 +-
modules/net-vpn-dynamic/variables.tf | 21 +-
modules/net-vpn-ha/README.md | 105 ++++++-
modules/net-vpn-ha/main.tf | 23 ++
modules/net-vpn-ha/variables.tf | 15 +-
modules/net-vpn-static/README.md | 64 +++-
modules/net-vpn-static/main.tf | 26 +-
modules/net-vpn-static/variables.tf | 13 +
.../vpn-single-tunnel-custom-ciphers.yaml | 297 ++++++++++++++++++
.../examples/vpn-single-tunnel.yaml | 284 +++++++++++++++++
.../net_vpn_ha/examples/gcp-to-gcp.yaml | 2 +
.../gcp-to-onprem-custom-ciphers.yaml | 232 ++++++++++++++
.../net_vpn_ha/examples/gcp-to-onprem.yaml | 2 +
tests/modules/net_vpn_ha/examples/ipv6.yaml | 84 ++++-
.../vpn-single-tunnel-custom-ciphers.yaml | 172 ++++++++++
.../examples/vpn-single-tunnel.yaml | 156 +++++++++
18 files changed, 1568 insertions(+), 37 deletions(-)
create mode 100644 tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel-custom-ciphers.yaml
create mode 100644 tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel.yaml
create mode 100644 tests/modules/net_vpn_ha/examples/gcp-to-onprem-custom-ciphers.yaml
create mode 100644 tests/modules/net_vpn_static/examples/vpn-single-tunnel-custom-ciphers.yaml
create mode 100644 tests/modules/net_vpn_static/examples/vpn-single-tunnel.yaml
diff --git a/modules/README.md b/modules/README.md
index 6eabc99f1..bcb7a2935 100644
--- a/modules/README.md
+++ b/modules/README.md
@@ -61,8 +61,8 @@ These modules are used in the examples included in this repository. If you are u
- [Service Directory](./service-directory)
- [VPC](./net-vpc)
- [VPC firewall](./net-vpc-firewall)
-- [VPN dynamic](./net-vpn-dynamic)
- [VPC peering](./net-vpc-peering)
+- [VPN dynamic](./net-vpn-dynamic)
- [VPN HA](./net-vpn-ha)
- [VPN static](./net-vpn-static)
diff --git a/modules/net-vpn-dynamic/README.md b/modules/net-vpn-dynamic/README.md
index 5f79ffaaa..89e64527a 100644
--- a/modules/net-vpn-dynamic/README.md
+++ b/modules/net-vpn-dynamic/README.md
@@ -1,10 +1,22 @@
# Cloud VPN Dynamic Module
-## Example
+This module makes it easy to deploy a [Classic VPN](https://docs.cloud.google.com/network-connectivity/docs/vpn/concepts/overview#classic-vpn) with dynamic (BGP) routing.
-This example shows how to configure a single VPN tunnel using a couple of extra features
+
+- [Examples](#examples)
+ - [Classic VPN with single tunnel](#classic-vpn-with-single-tunnel)
+ - [Classic VPN with single tunnel and custom ciphers](#classic-vpn-with-single-tunnel-and-custom-ciphers)
+- [Variables](#variables)
+- [Outputs](#outputs)
+
-- custom advertisement on the tunnel's BGP session; if custom advertisement is not needed, simply set the `bgp_peer_options` attribute to `null`
+## Examples
+
+### Classic VPN with single tunnel
+
+This example shows how to configure a single VPN tunnel using a couple of extra features:
+
+- custom advertisement on the tunnel's BGP session; if custom advertisement is not needed, simply set the `custom_advertise` attribute to `null`
- internally generated shared secret, which can be fetched from the module's `random_secret` output for reuse; a predefined secret can be used instead by assigning it to the `shared_secret` attribute
```hcl
@@ -51,10 +63,66 @@ module "vpn-dynamic" {
}
}
}
-# tftest modules=2 resources=12
+# tftest modules=2 resources=12 inventory=vpn-single-tunnel.yaml
+```
+
+### Classic VPN with single tunnel and custom ciphers
+
+This example shows how to configure a single VPN tunnel with custom ciphers.
+
+```hcl
+module "vm" {
+ source = "./fabric/modules/compute-vm"
+ project_id = "my-project"
+ zone = "europe-west1-b"
+ name = "my-vm"
+ network_interfaces = [{
+ nat = true
+ network = var.vpc.self_link
+ subnetwork = var.subnet.self_link
+ }]
+ service_account = {
+ auto_create = true
+ }
+}
+
+module "vpn-dynamic" {
+ source = "./fabric/modules/net-vpn-dynamic"
+ project_id = "my-project"
+ region = "europe-west1"
+ network = var.vpc.name
+ name = "gateway-1"
+ router_config = {
+ asn = 64514
+ }
+ tunnels = {
+ remote-1 = {
+ bgp_peer = {
+ address = "169.254.139.134"
+ asn = 64513
+ custom_advertise = null
+ }
+ bgp_session_range = "169.254.139.133/30"
+ cipher_suite = {
+ phase1 = {
+ dh = ["Group-14"]
+ encryption = ["AES-CBC-256"]
+ integrity = ["HMAC-SHA2-256-128"]
+ prf = ["PRF-HMAC-SHA2-256"]
+ }
+ phase2 = {
+ encryption = ["AES-CBC-128"]
+ integrity = ["HMAC-SHA2-256-128"]
+ pfs = ["Group-14"]
+ }
+ }
+ peer_ip = module.vm.external_ip
+ }
+ }
+}
+# tftest modules=2 resources=12 inventory=vpn-single-tunnel-custom-ciphers.yaml
```
-
## Variables
| name | description | type | required | default |
@@ -66,7 +134,7 @@ module "vpn-dynamic" {
| [router_config](variables.tf#L49) | 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({…}) | ✓ | |
| [gateway_address](variables.tf#L17) | Optional address assigned to the VPN gateway. Ignored unless gateway_address_create is set to false. | string | | null |
| [gateway_address_create](variables.tf#L23) | Create external address assigned to the VPN gateway. Needs to be explicitly set to false to use address in gateway_address variable. | bool | | true |
-| [tunnels](variables.tf#L64) | VPN tunnel configurations. | map(object({…})) | | {} |
+| [tunnels](variables.tf#L64) | VPN tunnel configurations. | map(object({…})) | | {} |
## Outputs
@@ -83,5 +151,4 @@ module "vpn-dynamic" {
| [tunnel_names](outputs.tf#L58) | VPN tunnel names. | |
| [tunnel_self_links](outputs.tf#L66) | VPN tunnel self links. | |
| [tunnels](outputs.tf#L74) | VPN tunnel resources. | |
-
diff --git a/modules/net-vpn-dynamic/main.tf b/modules/net-vpn-dynamic/main.tf
index fcf26934b..14c88b2d5 100644
--- a/modules/net-vpn-dynamic/main.tf
+++ b/modules/net-vpn-dynamic/main.tf
@@ -152,7 +152,31 @@ resource "google_compute_vpn_tunnel" "tunnels" {
ike_version = each.value.ike_version
shared_secret = coalesce(each.value.shared_secret, local.secret)
target_vpn_gateway = google_compute_vpn_gateway.gateway.self_link
- depends_on = [google_compute_forwarding_rule.esp]
+
+ dynamic "cipher_suite" {
+ for_each = each.value.cipher_suite != null ? [each.value.cipher_suite] : []
+ content {
+ dynamic "phase1" {
+ for_each = [cipher_suite.value.phase1]
+ content {
+ dh = try(phase1.value.dh, null)
+ encryption = try(phase1.value.encryption, null)
+ integrity = try(phase1.value.integrity, null)
+ prf = try(phase1.value.prf, null)
+ }
+ }
+ dynamic "phase2" {
+ for_each = [cipher_suite.value.phase2]
+ content {
+ encryption = try(phase2.value.encryption, null)
+ integrity = try(phase2.value.integrity, null)
+ pfs = try(phase2.value.pfs, null)
+ }
+ }
+ }
+ }
+
+ depends_on = [google_compute_forwarding_rule.esp]
}
resource "random_id" "secret" {
diff --git a/modules/net-vpn-dynamic/variables.tf b/modules/net-vpn-dynamic/variables.tf
index 33d23a040..106983ab2 100644
--- a/modules/net-vpn-dynamic/variables.tf
+++ b/modules/net-vpn-dynamic/variables.tf
@@ -78,10 +78,23 @@ variable "tunnels" {
# each BGP session on the same Cloud Router must use a unique /30 CIDR
# from the 169.254.0.0/16 block.
bgp_session_range = string
- ike_version = optional(number, 2)
- peer_ip = string
- router = optional(string)
- shared_secret = optional(string)
+ cipher_suite = optional(object({
+ phase1 = optional(object({
+ dh = optional(list(string))
+ encryption = optional(list(string))
+ integrity = optional(list(string))
+ prf = optional(list(string))
+ }))
+ phase2 = optional(object({
+ encryption = optional(list(string))
+ integrity = optional(list(string))
+ pfs = optional(list(string))
+ }))
+ }))
+ ike_version = optional(number, 2)
+ peer_ip = string
+ router = optional(string)
+ shared_secret = optional(string)
}))
default = {}
nullable = false
diff --git a/modules/net-vpn-ha/README.md b/modules/net-vpn-ha/README.md
index 6bda2b6f3..93b253a23 100644
--- a/modules/net-vpn-ha/README.md
+++ b/modules/net-vpn-ha/README.md
@@ -6,6 +6,7 @@ This module makes it easy to deploy either GCP-to-GCP or GCP-to-On-prem [Cloud H
- [Examples](#examples)
- [GCP to GCP](#gcp-to-gcp)
- [GCP to on-prem](#gcp-to-on-prem)
+ - [GCP to on-prem with custom ciphers](#gcp-to-on-prem-with-custom-ciphers)
- [IPv6 (dual-stack)](#ipv6-dual-stack)
- [Recipes](#recipes)
- [Variables](#variables)
@@ -135,7 +136,7 @@ module "vpn_ha" {
bgp_peer = {
address = "169.254.2.1"
asn = 64513
- # Custom learned routes are optional
+ # Custom learned routes are optional
custom_learned_ip_ranges = {
ip_ranges = {
"onprem-range" = "10.128.0.0/16"
@@ -157,6 +158,98 @@ module "vpn_ha" {
# tftest modules=1 resources=12 inventory=gcp-to-onprem.yaml
```
+### GCP to on-prem with custom ciphers
+
+```hcl
+module "vpn_ha" {
+ source = "./fabric/modules/net-vpn-ha"
+ project_id = var.project_id
+ region = var.region
+ network = var.vpc.self_link
+ name = "mynet-to-onprem"
+ peer_gateways = {
+ default = {
+ external = {
+ redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT"
+ interfaces = ["8.8.8.8"] # on-prem router ip address
+ }
+ }
+ }
+ router_config = { asn = 64514 }
+ tunnels = {
+ remote-0 = {
+ bgp_peer = {
+ address = "169.254.1.1"
+ asn = 64513
+ # Custom learned routes are optional
+ custom_learned_ip_ranges = {
+ ip_ranges = {
+ "onprem-range" = "10.128.0.0/16"
+ }
+ }
+ # MD5 Authentication is optional
+ md5_authentication_key = {
+ name = "foo"
+ key = "bar"
+ }
+ }
+ bgp_session_range = "169.254.1.2/30"
+ cipher_suite = {
+ phase1 = {
+ dh = ["Group-14"]
+ encryption = ["AES-CBC-256"]
+ integrity = ["HMAC-SHA2-256-128"]
+ prf = ["PRF-HMAC-SHA2-256"]
+ }
+ phase2 = {
+ encryption = ["AES-CBC-128"]
+ integrity = ["HMAC-SHA2-256-128"]
+ pfs = ["Group-14"]
+ }
+ }
+ peer_external_gateway_interface = 0
+ shared_secret = "mySecret"
+ vpn_gateway_interface = 0
+ }
+ remote-1 = {
+ bgp_peer = {
+ address = "169.254.2.1"
+ asn = 64513
+ # Custom learned routes are optional
+ custom_learned_ip_ranges = {
+ ip_ranges = {
+ "onprem-range" = "10.128.0.0/16"
+ }
+ }
+ # MD5 Authentication is optional
+ md5_authentication_key = {
+ name = "foo"
+ key = "bar"
+ }
+ }
+ bgp_session_range = "169.254.2.2/30"
+ cipher_suite = {
+ phase1 = {
+ dh = ["Group-14"]
+ encryption = ["AES-CBC-256"]
+ integrity = ["HMAC-SHA2-256-128"]
+ prf = ["PRF-HMAC-SHA2-256"]
+ }
+ phase2 = {
+ encryption = ["AES-CBC-128"]
+ integrity = ["HMAC-SHA2-256-128"]
+ pfs = ["Group-14"]
+ }
+ }
+ peer_external_gateway_interface = 0
+ shared_secret = "mySecret"
+ vpn_gateway_interface = 1
+ }
+ }
+}
+# tftest modules=1 resources=12 inventory=gcp-to-onprem-custom-ciphers.yaml
+```
+
### IPv6 (dual-stack)
You can optionally set your HA VPN gateway (and BGP sessions) to carry both IPv4 and IPv6 traffic. IPv6 only is not supported.
@@ -205,10 +298,10 @@ module "vpn_ha" {
}
}
vpn_gateway_create = {
- stack_type = "IPV4_IPV6"
+ ipv6 = true
}
}
-# tftest modules=1 resources=12 intentory=ipv6.yaml
+# tftest modules=1 resources=12 inventory=ipv6.yaml
```
You can optionally avoid to specify MD5 keys and the module will automatically generate them for you.
@@ -228,9 +321,9 @@ You can optionally avoid to specify MD5 keys and the module will automatically g
| [router_config](variables.tf#L72) | 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({…}) | ✓ | |
| [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} |
| [peer_gateways](variables.tf#L41) | Configuration of the (external or GCP) peer gateway. | map(object({…})) | | {} |
-| [tunnels](variables.tf#L88) | VPN tunnel configurations. | map(object({…})) | | {} |
-| [vpn_gateway](variables.tf#L129) | 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#L135) | Create HA VPN Gateway. Set to null to avoid creation. | object({…}) | | {} |
+| [tunnels](variables.tf#L88) | VPN tunnel configurations. | map(object({…})) | | {} |
+| [vpn_gateway](variables.tf#L142) | 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#L148) | 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 187691d30..a7da6cdd6 100644
--- a/modules/net-vpn-ha/main.tf
+++ b/modules/net-vpn-ha/main.tf
@@ -189,6 +189,29 @@ resource "google_compute_vpn_tunnel" "tunnels" {
ike_version = each.value.ike_version
shared_secret = coalesce(each.value.shared_secret, local.secret)
vpn_gateway = local.vpn_gateway
+
+ dynamic "cipher_suite" {
+ for_each = each.value.cipher_suite != null ? [each.value.cipher_suite] : []
+ content {
+ dynamic "phase1" {
+ for_each = [cipher_suite.value.phase1]
+ content {
+ dh = try(phase1.value.dh, null)
+ encryption = try(phase1.value.encryption, null)
+ integrity = try(phase1.value.integrity, null)
+ prf = try(phase1.value.prf, null)
+ }
+ }
+ dynamic "phase2" {
+ for_each = [cipher_suite.value.phase2]
+ content {
+ encryption = try(phase2.value.encryption, null)
+ integrity = try(phase2.value.integrity, null)
+ pfs = try(phase2.value.pfs, null)
+ }
+ }
+ }
+ }
}
resource "random_id" "secret" {
diff --git a/modules/net-vpn-ha/variables.tf b/modules/net-vpn-ha/variables.tf
index 29e5d1dee..32e5a639f 100644
--- a/modules/net-vpn-ha/variables.tf
+++ b/modules/net-vpn-ha/variables.tf
@@ -112,7 +112,20 @@ variable "tunnels" {
})
# each BGP session on the same Cloud Router must use a unique /30 CIDR
# from the 169.254.0.0/16 block.
- bgp_session_range = string
+ bgp_session_range = string
+ cipher_suite = optional(object({
+ phase1 = optional(object({
+ dh = optional(list(string))
+ encryption = optional(list(string))
+ integrity = optional(list(string))
+ prf = optional(list(string))
+ }))
+ phase2 = optional(object({
+ encryption = optional(list(string))
+ integrity = optional(list(string))
+ pfs = optional(list(string))
+ }))
+ }))
ike_version = optional(number, 2)
name = optional(string)
peer_external_gateway_interface = optional(number)
diff --git a/modules/net-vpn-static/README.md b/modules/net-vpn-static/README.md
index 902fc1e46..961e1b379 100644
--- a/modules/net-vpn-static/README.md
+++ b/modules/net-vpn-static/README.md
@@ -1,6 +1,18 @@
# Cloud VPN Route-based Module
-## Example
+This module makes it easy to deploy a [Classic VPN](https://docs.cloud.google.com/network-connectivity/docs/vpn/concepts/overview#classic-vpn) with static routing.
+
+
+- [Examples](#examples)
+ - [Classic VPN with single tunnel](#classic-vpn-with-single-tunnel)
+ - [Classic VPN with single tunnel and custom ciphers](#classic-vpn-with-single-tunnel-and-custom-ciphers)
+- [Variables](#variables)
+- [Outputs](#outputs)
+
+
+## Examples
+
+### Classic VPN with single tunnel
```hcl
module "addresses" {
@@ -28,10 +40,53 @@ module "vpn" {
}
}
}
-# tftest modules=2 resources=8
+# tftest modules=2 resources=8 inventory=vpn-single-tunnel.yaml
+```
+
+### Classic VPN with single tunnel and custom ciphers
+
+```hcl
+module "addresses" {
+ source = "./fabric/modules/net-address"
+ project_id = var.project_id
+ external_addresses = {
+ vpn = { region = "europe-west1" }
+ }
+}
+
+module "vpn" {
+ source = "./fabric/modules/net-vpn-static"
+ project_id = var.project_id
+ region = var.region
+ network = var.vpc.self_link
+ name = "remote"
+ gateway_address_create = false
+ gateway_address = module.addresses.external_addresses["vpn"].address
+ remote_ranges = ["10.10.0.0/24"]
+ tunnels = {
+ remote-0 = {
+ cipher_suite = {
+ phase1 = {
+ dh = ["Group-14"]
+ encryption = ["AES-CBC-256"]
+ integrity = ["HMAC-SHA2-256-128"]
+ prf = ["PRF-HMAC-SHA2-256"]
+ }
+ phase2 = {
+ encryption = ["AES-CBC-128"]
+ integrity = ["HMAC-SHA2-256-128"]
+ pfs = ["Group-14"]
+ }
+ }
+ peer_ip = "1.1.1.1"
+ shared_secret = "mysecret"
+ traffic_selectors = { local = ["0.0.0.0/0"], remote = ["0.0.0.0/0"] }
+ }
+ }
+}
+# tftest modules=2 resources=8 inventory=vpn-single-tunnel-custom-ciphers.yaml
```
-
## Variables
| name | description | type | required | default |
@@ -44,7 +99,7 @@ module "vpn" {
| [gateway_address_create](variables.tf#L23) | Create external address assigned to the VPN gateway. Needs to be explicitly set to false to use address in gateway_address variable. | bool | | true |
| [remote_ranges](variables.tf#L49) | Remote IP CIDR ranges. | list(string) | | [] |
| [route_priority](variables.tf#L56) | Route priority, defaults to 1000. | number | | 1000 |
-| [tunnels](variables.tf#L62) | VPN tunnel configurations. | map(object({…})) | | {} |
+| [tunnels](variables.tf#L62) | VPN tunnel configurations. | map(object({…})) | | {} |
## Outputs
@@ -59,5 +114,4 @@ module "vpn" {
| [tunnel_names](outputs.tf#L47) | VPN tunnel names. | |
| [tunnel_self_links](outputs.tf#L55) | VPN tunnel self links. | |
| [tunnels](outputs.tf#L63) | VPN tunnel resources. | |
-
diff --git a/modules/net-vpn-static/main.tf b/modules/net-vpn-static/main.tf
index f05771c16..547eea873 100644
--- a/modules/net-vpn-static/main.tf
+++ b/modules/net-vpn-static/main.tf
@@ -93,7 +93,31 @@ resource "google_compute_vpn_tunnel" "tunnels" {
ike_version = each.value.ike_version
shared_secret = coalesce(each.value.shared_secret, local.secret)
target_vpn_gateway = google_compute_vpn_gateway.gateway.self_link
- depends_on = [google_compute_forwarding_rule.esp]
+
+ dynamic "cipher_suite" {
+ for_each = each.value.cipher_suite != null ? [each.value.cipher_suite] : []
+ content {
+ dynamic "phase1" {
+ for_each = [cipher_suite.value.phase1]
+ content {
+ dh = try(phase1.value.dh, null)
+ encryption = try(phase1.value.encryption, null)
+ integrity = try(phase1.value.integrity, null)
+ prf = try(phase1.value.prf, null)
+ }
+ }
+ dynamic "phase2" {
+ for_each = [cipher_suite.value.phase2]
+ content {
+ encryption = try(phase2.value.encryption, null)
+ integrity = try(phase2.value.integrity, null)
+ pfs = try(phase2.value.pfs, null)
+ }
+ }
+ }
+ }
+
+ depends_on = [google_compute_forwarding_rule.esp]
}
resource "random_id" "secret" {
diff --git a/modules/net-vpn-static/variables.tf b/modules/net-vpn-static/variables.tf
index 935c543a4..7b0653a5d 100644
--- a/modules/net-vpn-static/variables.tf
+++ b/modules/net-vpn-static/variables.tf
@@ -62,6 +62,19 @@ variable "route_priority" {
variable "tunnels" {
description = "VPN tunnel configurations."
type = map(object({
+ cipher_suite = optional(object({
+ phase1 = optional(object({
+ dh = optional(list(string))
+ encryption = optional(list(string))
+ integrity = optional(list(string))
+ prf = optional(list(string))
+ }))
+ phase2 = optional(object({
+ encryption = optional(list(string))
+ integrity = optional(list(string))
+ pfs = optional(list(string))
+ }))
+ }))
ike_version = optional(number, 2)
peer_ip = string
shared_secret = optional(string)
diff --git a/tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel-custom-ciphers.yaml b/tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel-custom-ciphers.yaml
new file mode 100644
index 000000000..6b43e66df
--- /dev/null
+++ b/tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel-custom-ciphers.yaml
@@ -0,0 +1,297 @@
+# Copyright 2026 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.vm.google_compute_instance.default[0]:
+ advanced_machine_features: []
+ allow_stopping_for_update: true
+ attached_disk: []
+ boot_disk:
+ - auto_delete: true
+ disk_encryption_key_raw: null
+ disk_encryption_key_rsa: null
+ disk_encryption_service_account: null
+ force_attach: null
+ initialize_params:
+ - enable_confidential_compute: null
+ image: projects/debian-cloud/global/images/family/debian-11
+ resource_manager_tags: null
+ size: 10
+ source_image_encryption_key: []
+ source_snapshot_encryption_key: []
+ storage_pool: null
+ type: pd-balanced
+ interface: null
+ mode: READ_WRITE
+ can_ip_forward: false
+ deletion_protection: false
+ description: Managed by the compute-vm Terraform module.
+ desired_status: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ enable_display: false
+ hostname: null
+ instance_encryption_key: []
+ key_revocation_action_type: NONE
+ labels: null
+ machine_type: f1-micro
+ metadata: null
+ metadata_startup_script: null
+ name: my-vm
+ network_interface:
+ - access_config:
+ - public_ptr_domain_name: null
+ alias_ip_range: []
+ ipv6_access_config: []
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ nic_type: null
+ queue_count: null
+ security_policy: null
+ subnetwork: subnet_self_link
+ network_performance_config: []
+ params: []
+ partner_metadata: null
+ project: my-project
+ resource_policies: null
+ scheduling:
+ - automatic_restart: true
+ availability_domain: null
+ graceful_shutdown: []
+ host_error_timeout_seconds: null
+ instance_termination_action: null
+ local_ssd_recovery_timeout: []
+ maintenance_interval: null
+ max_run_duration: []
+ min_node_cpus: null
+ node_affinities: []
+ on_host_maintenance: MIGRATE
+ on_instance_stop_action: []
+ preemptible: false
+ provisioning_model: STANDARD
+ skip_guest_os_shutdown: false
+ termination_time: null
+ scratch_disk: []
+ service_account:
+ - email: tf-vm-my-vm@my-project.iam.gserviceaccount.com
+ scopes:
+ - https://www.googleapis.com/auth/cloud-platform
+ - https://www.googleapis.com/auth/userinfo.email
+ shielded_instance_config: []
+ tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ zone: europe-west1-b
+ module.vm.google_service_account.service_account[0]:
+ account_id: tf-vm-my-vm
+ create_ignore_already_exists: null
+ description: null
+ disabled: false
+ display_name: Terraform VM my-vm.
+ email: tf-vm-my-vm@my-project.iam.gserviceaccount.com
+ member: serviceAccount:tf-vm-my-vm@my-project.iam.gserviceaccount.com
+ project: my-project
+ timeouts: null
+ module.vpn-dynamic.google_compute_address.gateway[0]:
+ address_type: EXTERNAL
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ip_collection: null
+ ip_version: null
+ ipv6_endpoint_type: null
+ labels: null
+ name: vpn-gateway-1
+ network: null
+ project: my-project
+ region: europe-west1
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.vpn-dynamic.google_compute_forwarding_rule.esp:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: ESP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-gateway-1-esp
+ no_automate_dns_zone: null
+ ports: null
+ project: my-project
+ recreate_closed_psc: false
+ region: europe-west1
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn-dynamic.google_compute_forwarding_rule.udp-4500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-gateway-1-udp-4500
+ no_automate_dns_zone: null
+ port_range: '4500'
+ ports: null
+ project: my-project
+ recreate_closed_psc: false
+ region: europe-west1
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn-dynamic.google_compute_forwarding_rule.udp-500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-gateway-1-udp-500
+ no_automate_dns_zone: null
+ port_range: '500'
+ ports: null
+ project: my-project
+ recreate_closed_psc: false
+ region: europe-west1
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn-dynamic.google_compute_router.router[0]:
+ bgp:
+ - advertise_mode: DEFAULT
+ advertised_groups: []
+ advertised_ip_ranges: []
+ asn: 64514
+ keepalive_interval: 20
+ description: null
+ encrypted_interconnect_router: null
+ md5_authentication_keys: []
+ name: vpn-gateway-1
+ network: vpc-name
+ params: []
+ project: my-project
+ region: europe-west1
+ timeouts: null
+ module.vpn-dynamic.google_compute_router_interface.router_interface["remote-1"]:
+ interconnect_attachment: null
+ ip_range: 169.254.139.133/30
+ name: gateway-1-remote-1
+ private_ip_address: null
+ project: my-project
+ region: europe-west1
+ router: vpn-gateway-1
+ subnetwork: null
+ timeouts: null
+ vpn_tunnel: gateway-1-remote-1
+ module.vpn-dynamic.google_compute_router_peer.bgp_peer["remote-1"]:
+ advertise_mode: DEFAULT
+ advertised_groups: []
+ advertised_ip_ranges: []
+ advertised_route_priority: 1000
+ custom_learned_ip_ranges: []
+ custom_learned_route_priority: null
+ enable: true
+ enable_ipv6: false
+ export_policies: null
+ import_policies: null
+ interface: gateway-1-remote-1
+ md5_authentication_key: []
+ name: gateway-1-remote-1
+ peer_asn: 64513
+ peer_ip_address: 169.254.139.134
+ project: my-project
+ region: europe-west1
+ router: vpn-gateway-1
+ router_appliance_instance: null
+ timeouts: null
+ zero_advertised_route_priority: null
+ zero_custom_learned_route_priority: false
+ module.vpn-dynamic.google_compute_vpn_gateway.gateway:
+ description: null
+ name: gateway-1
+ network: vpc-name
+ project: my-project
+ region: europe-west1
+ timeouts: null
+ module.vpn-dynamic.google_compute_vpn_tunnel.tunnels["remote-1"]:
+ cipher_suite:
+ - phase1:
+ - dh:
+ - Group-14
+ encryption:
+ - AES-CBC-256
+ integrity:
+ - HMAC-SHA2-256-128
+ prf:
+ - PRF-HMAC-SHA2-256
+ phase2:
+ - encryption:
+ - AES-CBC-128
+ integrity:
+ - HMAC-SHA2-256-128
+ pfs:
+ - Group-14
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ike_version: 2
+ labels: null
+ name: gateway-1-remote-1
+ peer_external_gateway: null
+ peer_external_gateway_interface: null
+ peer_gcp_gateway: null
+ project: my-project
+ region: europe-west1
+ router: vpn-gateway-1
+ shared_secret_wo: null
+ shared_secret_wo_version: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ vpn_gateway: null
+ vpn_gateway_interface: null
+ module.vpn-dynamic.random_id.secret:
+ byte_length: 8
+ keepers: null
+ prefix: null
+
+counts:
+ google_compute_address: 1
+ google_compute_forwarding_rule: 3
+ google_compute_instance: 1
+ google_compute_router_interface: 1
+ google_compute_router_peer: 1
+ google_compute_router: 1
+ google_compute_vpn_gateway: 1
+ google_compute_vpn_tunnel: 1
+ google_service_account: 1
+ modules: 2
+ random_id: 1
+ resources: 12
+
+outputs: {}
diff --git a/tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel.yaml b/tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel.yaml
new file mode 100644
index 000000000..0b4502ba4
--- /dev/null
+++ b/tests/modules/net_vpn_dynamic/examples/vpn-single-tunnel.yaml
@@ -0,0 +1,284 @@
+# Copyright 2026 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.vm.google_compute_instance.default[0]:
+ advanced_machine_features: []
+ allow_stopping_for_update: true
+ attached_disk: []
+ boot_disk:
+ - auto_delete: true
+ disk_encryption_key_raw: null
+ disk_encryption_key_rsa: null
+ disk_encryption_service_account: null
+ force_attach: null
+ initialize_params:
+ - enable_confidential_compute: null
+ image: projects/debian-cloud/global/images/family/debian-11
+ resource_manager_tags: null
+ size: 10
+ source_image_encryption_key: []
+ source_snapshot_encryption_key: []
+ storage_pool: null
+ type: pd-balanced
+ interface: null
+ mode: READ_WRITE
+ can_ip_forward: false
+ deletion_protection: false
+ description: Managed by the compute-vm Terraform module.
+ desired_status: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ enable_display: false
+ hostname: null
+ instance_encryption_key: []
+ key_revocation_action_type: NONE
+ labels: null
+ machine_type: f1-micro
+ metadata: null
+ metadata_startup_script: null
+ name: my-vm
+ network_interface:
+ - access_config:
+ - public_ptr_domain_name: null
+ alias_ip_range: []
+ ipv6_access_config: []
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ nic_type: null
+ queue_count: null
+ security_policy: null
+ subnetwork: subnet_self_link
+ network_performance_config: []
+ params: []
+ partner_metadata: null
+ project: my-project
+ resource_policies: null
+ scheduling:
+ - automatic_restart: true
+ availability_domain: null
+ graceful_shutdown: []
+ host_error_timeout_seconds: null
+ instance_termination_action: null
+ local_ssd_recovery_timeout: []
+ maintenance_interval: null
+ max_run_duration: []
+ min_node_cpus: null
+ node_affinities: []
+ on_host_maintenance: MIGRATE
+ on_instance_stop_action: []
+ preemptible: false
+ provisioning_model: STANDARD
+ skip_guest_os_shutdown: false
+ termination_time: null
+ scratch_disk: []
+ service_account:
+ - email: tf-vm-my-vm@my-project.iam.gserviceaccount.com
+ scopes:
+ - https://www.googleapis.com/auth/cloud-platform
+ - https://www.googleapis.com/auth/userinfo.email
+ shielded_instance_config: []
+ tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ zone: europe-west1-b
+ module.vm.google_service_account.service_account[0]:
+ account_id: tf-vm-my-vm
+ create_ignore_already_exists: null
+ description: null
+ disabled: false
+ display_name: Terraform VM my-vm.
+ email: tf-vm-my-vm@my-project.iam.gserviceaccount.com
+ member: serviceAccount:tf-vm-my-vm@my-project.iam.gserviceaccount.com
+ project: my-project
+ timeouts: null
+ module.vpn-dynamic.google_compute_address.gateway[0]:
+ address_type: EXTERNAL
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ip_collection: null
+ ip_version: null
+ ipv6_endpoint_type: null
+ labels: null
+ name: vpn-gateway-1
+ network: null
+ project: my-project
+ region: europe-west1
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.vpn-dynamic.google_compute_forwarding_rule.esp:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: ESP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-gateway-1-esp
+ no_automate_dns_zone: null
+ ports: null
+ project: my-project
+ recreate_closed_psc: false
+ region: europe-west1
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn-dynamic.google_compute_forwarding_rule.udp-4500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-gateway-1-udp-4500
+ no_automate_dns_zone: null
+ port_range: '4500'
+ ports: null
+ project: my-project
+ recreate_closed_psc: false
+ region: europe-west1
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn-dynamic.google_compute_forwarding_rule.udp-500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-gateway-1-udp-500
+ no_automate_dns_zone: null
+ port_range: '500'
+ ports: null
+ project: my-project
+ recreate_closed_psc: false
+ region: europe-west1
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn-dynamic.google_compute_router.router[0]:
+ bgp:
+ - advertise_mode: DEFAULT
+ advertised_groups: []
+ advertised_ip_ranges: []
+ asn: 64514
+ keepalive_interval: 20
+ description: null
+ encrypted_interconnect_router: null
+ md5_authentication_keys: []
+ name: vpn-gateway-1
+ network: vpc-name
+ params: []
+ project: my-project
+ region: europe-west1
+ timeouts: null
+ module.vpn-dynamic.google_compute_router_interface.router_interface["remote-1"]:
+ interconnect_attachment: null
+ ip_range: 169.254.139.133/30
+ name: gateway-1-remote-1
+ private_ip_address: null
+ project: my-project
+ region: europe-west1
+ router: vpn-gateway-1
+ subnetwork: null
+ timeouts: null
+ vpn_tunnel: gateway-1-remote-1
+ module.vpn-dynamic.google_compute_router_peer.bgp_peer["remote-1"]:
+ advertise_mode: CUSTOM
+ advertised_groups:
+ - ALL_SUBNETS
+ advertised_ip_ranges:
+ - description: Advertised range description
+ range: 192.168.0.0/24
+ advertised_route_priority: 1000
+ custom_learned_ip_ranges: []
+ custom_learned_route_priority: null
+ enable: true
+ enable_ipv6: false
+ export_policies: null
+ import_policies: null
+ interface: gateway-1-remote-1
+ md5_authentication_key: []
+ name: gateway-1-remote-1
+ peer_asn: 64513
+ peer_ip_address: 169.254.139.134
+ project: my-project
+ region: europe-west1
+ router: vpn-gateway-1
+ router_appliance_instance: null
+ timeouts: null
+ zero_advertised_route_priority: null
+ zero_custom_learned_route_priority: false
+ module.vpn-dynamic.google_compute_vpn_gateway.gateway:
+ description: null
+ name: gateway-1
+ network: vpc-name
+ project: my-project
+ region: europe-west1
+ timeouts: null
+ module.vpn-dynamic.google_compute_vpn_tunnel.tunnels["remote-1"]:
+ cipher_suite: []
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ike_version: 2
+ labels: null
+ name: gateway-1-remote-1
+ peer_external_gateway: null
+ peer_external_gateway_interface: null
+ peer_gcp_gateway: null
+ project: my-project
+ region: europe-west1
+ router: vpn-gateway-1
+ shared_secret_wo: null
+ shared_secret_wo_version: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ vpn_gateway: null
+ vpn_gateway_interface: null
+ module.vpn-dynamic.random_id.secret:
+ byte_length: 8
+ keepers: null
+ prefix: null
+
+counts:
+ google_compute_address: 1
+ google_compute_forwarding_rule: 3
+ google_compute_instance: 1
+ google_compute_router_interface: 1
+ google_compute_router_peer: 1
+ google_compute_router: 1
+ google_compute_vpn_gateway: 1
+ google_compute_vpn_tunnel: 1
+ google_service_account: 1
+ modules: 2
+ random_id: 1
+ resources: 12
+
+outputs: {}
diff --git a/tests/modules/net_vpn_ha/examples/gcp-to-gcp.yaml b/tests/modules/net_vpn_ha/examples/gcp-to-gcp.yaml
index d7591c4b5..501871f4d 100644
--- a/tests/modules/net_vpn_ha/examples/gcp-to-gcp.yaml
+++ b/tests/modules/net_vpn_ha/examples/gcp-to-gcp.yaml
@@ -214,3 +214,5 @@ counts:
modules: 2
random_id: 6
resources: 22
+
+outputs: {}
diff --git a/tests/modules/net_vpn_ha/examples/gcp-to-onprem-custom-ciphers.yaml b/tests/modules/net_vpn_ha/examples/gcp-to-onprem-custom-ciphers.yaml
new file mode 100644
index 000000000..2e75c10e7
--- /dev/null
+++ b/tests/modules/net_vpn_ha/examples/gcp-to-onprem-custom-ciphers.yaml
@@ -0,0 +1,232 @@
+# Copyright 2026 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.vpn_ha.google_compute_external_vpn_gateway.external_gateway["default"]:
+ description: Terraform managed external VPN gateway
+ effective_labels:
+ goog-terraform-provisioned: "true"
+ interface:
+ - id: 0
+ ip_address: 8.8.8.8
+ ipv6_address: null
+ labels: null
+ name: mynet-to-onprem-default
+ project: project-id
+ redundancy_type: SINGLE_IP_INTERNALLY_REDUNDANT
+ terraform_labels:
+ goog-terraform-provisioned: "true"
+ timeouts: null
+ module.vpn_ha.google_compute_ha_vpn_gateway.ha_gateway[0]:
+ description: Terraform managed external VPN gateway
+ effective_labels:
+ goog-terraform-provisioned: "true"
+ gateway_ip_version: IPV4
+ labels: null
+ name: mynet-to-onprem
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ project: project-id
+ region: europe-west8
+ stack_type: IPV4_ONLY
+ terraform_labels:
+ goog-terraform-provisioned: "true"
+ timeouts: null
+ module.vpn_ha.google_compute_router.router[0]:
+ bgp:
+ - advertise_mode: DEFAULT
+ advertised_groups: []
+ advertised_ip_ranges: []
+ asn: 64514
+ keepalive_interval: 20
+ description: null
+ encrypted_interconnect_router: null
+ md5_authentication_keys: []
+ name: vpn-mynet-to-onprem
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ project: project-id
+ region: europe-west8
+ timeouts: null
+ module.vpn_ha.google_compute_router_interface.router_interface["remote-0"]:
+ interconnect_attachment: null
+ ip_range: 169.254.1.2/30
+ name: mynet-to-onprem-remote-0
+ private_ip_address: null
+ project: project-id
+ region: europe-west8
+ router: vpn-mynet-to-onprem
+ subnetwork: null
+ timeouts: null
+ vpn_tunnel: mynet-to-onprem-remote-0
+ module.vpn_ha.google_compute_router_interface.router_interface["remote-1"]:
+ interconnect_attachment: null
+ ip_range: 169.254.2.2/30
+ name: mynet-to-onprem-remote-1
+ private_ip_address: null
+ project: project-id
+ region: europe-west8
+ router: vpn-mynet-to-onprem
+ subnetwork: null
+ timeouts: null
+ vpn_tunnel: mynet-to-onprem-remote-1
+ module.vpn_ha.google_compute_router_peer.bgp_peer["remote-0"]:
+ advertise_mode: DEFAULT
+ advertised_groups: []
+ advertised_ip_ranges: []
+ advertised_route_priority: 1000
+ custom_learned_ip_ranges:
+ - range: 10.128.0.0/16
+ custom_learned_route_priority: 1000
+ enable: true
+ enable_ipv6: false
+ export_policies: null
+ import_policies: null
+ interface: mynet-to-onprem-remote-0
+ md5_authentication_key:
+ - key: bar
+ name: foo
+ name: mynet-to-onprem-remote-0
+ peer_asn: 64513
+ peer_ip_address: 169.254.1.1
+ project: project-id
+ region: europe-west8
+ router: vpn-mynet-to-onprem
+ router_appliance_instance: null
+ timeouts: null
+ zero_advertised_route_priority: null
+ zero_custom_learned_route_priority: false
+ module.vpn_ha.google_compute_router_peer.bgp_peer["remote-1"]:
+ advertise_mode: DEFAULT
+ advertised_groups: []
+ advertised_ip_ranges: []
+ advertised_route_priority: 1000
+ custom_learned_ip_ranges:
+ - range: 10.128.0.0/16
+ custom_learned_route_priority: 1000
+ enable: true
+ enable_ipv6: false
+ export_policies: null
+ import_policies: null
+ interface: mynet-to-onprem-remote-1
+ md5_authentication_key:
+ - key: bar
+ name: foo
+ name: mynet-to-onprem-remote-1
+ peer_asn: 64513
+ peer_ip_address: 169.254.2.1
+ project: project-id
+ region: europe-west8
+ router: vpn-mynet-to-onprem
+ router_appliance_instance: null
+ timeouts: null
+ zero_advertised_route_priority: null
+ zero_custom_learned_route_priority: false
+ module.vpn_ha.google_compute_vpn_tunnel.tunnels["remote-0"]:
+ cipher_suite:
+ - phase1:
+ - dh:
+ - Group-14
+ encryption:
+ - AES-CBC-256
+ integrity:
+ - HMAC-SHA2-256-128
+ prf:
+ - PRF-HMAC-SHA2-256
+ phase2:
+ - encryption:
+ - AES-CBC-128
+ integrity:
+ - HMAC-SHA2-256-128
+ pfs:
+ - Group-14
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: "true"
+ ike_version: 2
+ labels: null
+ name: mynet-to-onprem-remote-0
+ peer_external_gateway_interface: 0
+ peer_gcp_gateway: null
+ project: project-id
+ region: europe-west8
+ router: vpn-mynet-to-onprem
+ shared_secret: mySecret
+ shared_secret_wo: null
+ shared_secret_wo_version: null
+ target_vpn_gateway: null
+ terraform_labels:
+ goog-terraform-provisioned: "true"
+ timeouts: null
+ vpn_gateway_interface: 0
+ module.vpn_ha.google_compute_vpn_tunnel.tunnels["remote-1"]:
+ cipher_suite:
+ - phase1:
+ - dh:
+ - Group-14
+ encryption:
+ - AES-CBC-256
+ integrity:
+ - HMAC-SHA2-256-128
+ prf:
+ - PRF-HMAC-SHA2-256
+ phase2:
+ - encryption:
+ - AES-CBC-128
+ integrity:
+ - HMAC-SHA2-256-128
+ pfs:
+ - Group-14
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: "true"
+ ike_version: 2
+ labels: null
+ name: mynet-to-onprem-remote-1
+ peer_external_gateway_interface: 0
+ peer_gcp_gateway: null
+ project: project-id
+ region: europe-west8
+ router: vpn-mynet-to-onprem
+ shared_secret: mySecret
+ shared_secret_wo: null
+ shared_secret_wo_version: null
+ target_vpn_gateway: null
+ terraform_labels:
+ goog-terraform-provisioned: "true"
+ timeouts: null
+ vpn_gateway_interface: 1
+ module.vpn_ha.random_id.md5_keys["remote-0"]:
+ byte_length: 12
+ keepers: null
+ prefix: null
+ module.vpn_ha.random_id.md5_keys["remote-1"]:
+ byte_length: 12
+ keepers: null
+ prefix: null
+ module.vpn_ha.random_id.secret:
+ byte_length: 8
+ keepers: null
+ prefix: null
+
+counts:
+ google_compute_external_vpn_gateway: 1
+ google_compute_ha_vpn_gateway: 1
+ google_compute_router: 1
+ google_compute_router_interface: 2
+ google_compute_router_peer: 2
+ google_compute_vpn_tunnel: 2
+ modules: 1
+ random_id: 3
+ resources: 12
+
+outputs: {}
diff --git a/tests/modules/net_vpn_ha/examples/gcp-to-onprem.yaml b/tests/modules/net_vpn_ha/examples/gcp-to-onprem.yaml
index 2727c7e93..d609c70ce 100644
--- a/tests/modules/net_vpn_ha/examples/gcp-to-onprem.yaml
+++ b/tests/modules/net_vpn_ha/examples/gcp-to-onprem.yaml
@@ -196,3 +196,5 @@ counts:
modules: 1
random_id: 3
resources: 12
+
+outputs: {}
diff --git a/tests/modules/net_vpn_ha/examples/ipv6.yaml b/tests/modules/net_vpn_ha/examples/ipv6.yaml
index c0df23a24..830519677 100644
--- a/tests/modules/net_vpn_ha/examples/ipv6.yaml
+++ b/tests/modules/net_vpn_ha/examples/ipv6.yaml
@@ -15,20 +15,33 @@
values:
module.vpn_ha.google_compute_external_vpn_gateway.external_gateway["default"]:
description: Terraform managed external VPN gateway
+ effective_labels:
+ goog-terraform-provisioned: 'true'
interface:
- id: 0
ip_address: 8.8.8.8
+ ipv6_address: null
labels: null
name: mynet-to-onprem-default
project: project-id
redundancy_type: SINGLE_IP_INTERNALLY_REDUNDANT
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
module.vpn_ha.google_compute_ha_vpn_gateway.ha_gateway[0]:
description: Terraform managed external VPN gateway
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ gateway_ip_version: IPV4
+ labels: null
name: mynet-to-onprem
- network: projects/xxx/global/networks/aaa
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
project: project-id
- region: region
+ region: europe-west8
stack_type: IPV4_IPV6
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
module.vpn_ha.google_compute_router.router[0]:
bgp:
- advertise_mode: DEFAULT
@@ -38,19 +51,23 @@ values:
keepalive_interval: 20
description: null
encrypted_interconnect_router: null
+ md5_authentication_keys: []
name: vpn-mynet-to-onprem
- network: projects/xxx/global/networks/aaa
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ params: []
project: project-id
- region: region
+ region: europe-west8
+ timeouts: null
module.vpn_ha.google_compute_router_interface.router_interface["remote-0"]:
interconnect_attachment: null
ip_range: 169.254.1.2/30
name: mynet-to-onprem-remote-0
private_ip_address: null
project: project-id
- region: region
+ region: europe-west8
router: vpn-mynet-to-onprem
subnetwork: null
+ timeouts: null
vpn_tunnel: mynet-to-onprem-remote-0
module.vpn_ha.google_compute_router_interface.router_interface["remote-1"]:
interconnect_attachment: null
@@ -58,66 +75,109 @@ values:
name: mynet-to-onprem-remote-1
private_ip_address: null
project: project-id
- region: region
+ region: europe-west8
router: vpn-mynet-to-onprem
subnetwork: null
+ timeouts: null
vpn_tunnel: mynet-to-onprem-remote-1
module.vpn_ha.google_compute_router_peer.bgp_peer["remote-0"]:
advertise_mode: DEFAULT
advertised_groups: []
advertised_ip_ranges: []
advertised_route_priority: 1000
+ custom_learned_ip_ranges: []
+ custom_learned_route_priority: null
enable: true
enable_ipv6: true
+ export_policies: null
+ import_policies: null
interface: mynet-to-onprem-remote-0
+ md5_authentication_key: []
name: mynet-to-onprem-remote-0
peer_asn: 64513
peer_ip_address: 169.254.1.1
project: project-id
- region: region
+ region: europe-west8
router: vpn-mynet-to-onprem
router_appliance_instance: null
+ timeouts: null
+ zero_advertised_route_priority: null
+ zero_custom_learned_route_priority: false
module.vpn_ha.google_compute_router_peer.bgp_peer["remote-1"]:
advertise_mode: DEFAULT
advertised_groups: []
advertised_ip_ranges: []
advertised_route_priority: 1000
+ custom_learned_ip_ranges: []
+ custom_learned_route_priority: null
enable: true
enable_ipv6: true
+ export_policies: null
+ import_policies: null
interface: mynet-to-onprem-remote-1
ipv6_nexthop_address: 2600:2d00:0:2::1
+ md5_authentication_key: []
name: mynet-to-onprem-remote-1
peer_asn: 64513
peer_ip_address: 169.254.2.1
peer_ipv6_nexthop_address: 2600:2d00:0:3::1
project: project-id
- region: region
+ region: europe-west8
router: vpn-mynet-to-onprem
router_appliance_instance: null
+ timeouts: null
+ zero_advertised_route_priority: null
+ zero_custom_learned_route_priority: false
module.vpn_ha.google_compute_vpn_tunnel.tunnels["remote-0"]:
+ cipher_suite: []
description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
ike_version: 2
+ labels: null
name: mynet-to-onprem-remote-0
peer_external_gateway_interface: 0
peer_gcp_gateway: null
project: project-id
- region: region
+ region: europe-west8
router: vpn-mynet-to-onprem
shared_secret: mySecret
+ shared_secret_wo: null
+ shared_secret_wo_version: null
target_vpn_gateway: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
vpn_gateway_interface: 0
module.vpn_ha.google_compute_vpn_tunnel.tunnels["remote-1"]:
+ cipher_suite: []
description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
ike_version: 2
+ labels: null
name: mynet-to-onprem-remote-1
peer_external_gateway_interface: 0
peer_gcp_gateway: null
project: project-id
- region: region
+ region: europe-west8
router: vpn-mynet-to-onprem
shared_secret: mySecret
+ shared_secret_wo: null
+ shared_secret_wo_version: null
target_vpn_gateway: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
vpn_gateway_interface: 1
+ module.vpn_ha.random_id.md5_keys["remote-0"]:
+ byte_length: 12
+ keepers: null
+ prefix: null
+ module.vpn_ha.random_id.md5_keys["remote-1"]:
+ byte_length: 12
+ keepers: null
+ prefix: null
module.vpn_ha.random_id.secret:
byte_length: 8
keepers: null
@@ -126,10 +186,12 @@ values:
counts:
google_compute_external_vpn_gateway: 1
google_compute_ha_vpn_gateway: 1
- google_compute_router: 1
google_compute_router_interface: 2
google_compute_router_peer: 2
+ google_compute_router: 1
google_compute_vpn_tunnel: 2
modules: 1
random_id: 3
resources: 12
+
+outputs: {}
diff --git a/tests/modules/net_vpn_static/examples/vpn-single-tunnel-custom-ciphers.yaml b/tests/modules/net_vpn_static/examples/vpn-single-tunnel-custom-ciphers.yaml
new file mode 100644
index 000000000..6ecc7f140
--- /dev/null
+++ b/tests/modules/net_vpn_static/examples/vpn-single-tunnel-custom-ciphers.yaml
@@ -0,0 +1,172 @@
+# Copyright 2026 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.addresses.google_compute_address.external["vpn"]:
+ address_type: EXTERNAL
+ description: Terraform managed.
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ip_collection: null
+ ip_version: null
+ ipv6_endpoint_type: null
+ labels: null
+ name: vpn
+ network: null
+ project: project-id
+ region: europe-west1
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.vpn.google_compute_forwarding_rule.esp:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: ESP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-remote-esp
+ no_automate_dns_zone: null
+ ports: null
+ project: project-id
+ recreate_closed_psc: false
+ region: europe-west8
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn.google_compute_forwarding_rule.udp-4500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-remote-udp-4500
+ no_automate_dns_zone: null
+ port_range: '4500'
+ ports: null
+ project: project-id
+ recreate_closed_psc: false
+ region: europe-west8
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn.google_compute_forwarding_rule.udp-500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-remote-udp-500
+ no_automate_dns_zone: null
+ port_range: '500'
+ ports: null
+ project: project-id
+ recreate_closed_psc: false
+ region: europe-west8
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn.google_compute_route.route["remote-0-10-10-0-0-24"]:
+ description: null
+ dest_range: 10.10.0.0/24
+ name: vpn-remote-remote-0-10-10-0-0-24
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ next_hop_gateway: null
+ next_hop_ilb: null
+ next_hop_instance: null
+ params: []
+ priority: 1000
+ project: project-id
+ tags: null
+ timeouts: null
+ module.vpn.google_compute_vpn_gateway.gateway:
+ description: null
+ name: remote
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ project: project-id
+ region: europe-west8
+ timeouts: null
+ module.vpn.google_compute_vpn_tunnel.tunnels["remote-0"]:
+ cipher_suite:
+ - phase1:
+ - dh:
+ - Group-14
+ encryption:
+ - AES-CBC-256
+ integrity:
+ - HMAC-SHA2-256-128
+ prf:
+ - PRF-HMAC-SHA2-256
+ phase2:
+ - encryption:
+ - AES-CBC-128
+ integrity:
+ - HMAC-SHA2-256-128
+ pfs:
+ - Group-14
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ike_version: 2
+ labels: null
+ local_traffic_selector:
+ - 0.0.0.0/0
+ name: remote-remote-0
+ peer_external_gateway: null
+ peer_external_gateway_interface: null
+ peer_gcp_gateway: null
+ peer_ip: 1.1.1.1
+ project: project-id
+ region: europe-west8
+ remote_traffic_selector:
+ - 0.0.0.0/0
+ router: null
+ shared_secret: mysecret
+ shared_secret_wo: null
+ shared_secret_wo_version: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ vpn_gateway: null
+ vpn_gateway_interface: null
+ module.vpn.random_id.secret:
+ byte_length: 8
+ keepers: null
+ prefix: null
+
+counts:
+ google_compute_address: 1
+ google_compute_forwarding_rule: 3
+ google_compute_route: 1
+ google_compute_vpn_gateway: 1
+ google_compute_vpn_tunnel: 1
+ modules: 2
+ random_id: 1
+ resources: 8
+
+outputs: {}
diff --git a/tests/modules/net_vpn_static/examples/vpn-single-tunnel.yaml b/tests/modules/net_vpn_static/examples/vpn-single-tunnel.yaml
new file mode 100644
index 000000000..58e56c3a3
--- /dev/null
+++ b/tests/modules/net_vpn_static/examples/vpn-single-tunnel.yaml
@@ -0,0 +1,156 @@
+# Copyright 2026 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.addresses.google_compute_address.external["vpn"]:
+ address_type: EXTERNAL
+ description: Terraform managed.
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ip_collection: null
+ ip_version: null
+ ipv6_endpoint_type: null
+ labels: null
+ name: vpn
+ network: null
+ project: project-id
+ region: europe-west1
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.vpn.google_compute_forwarding_rule.esp:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: ESP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-remote-esp
+ no_automate_dns_zone: null
+ ports: null
+ project: project-id
+ recreate_closed_psc: false
+ region: europe-west8
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn.google_compute_forwarding_rule.udp-4500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-remote-udp-4500
+ no_automate_dns_zone: null
+ port_range: '4500'
+ ports: null
+ project: project-id
+ recreate_closed_psc: false
+ region: europe-west8
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn.google_compute_forwarding_rule.udp-500:
+ all_ports: null
+ allow_global_access: null
+ allow_psc_global_access: null
+ backend_service: null
+ description: null
+ ip_collection: null
+ ip_protocol: UDP
+ is_mirroring_collector: null
+ labels: null
+ load_balancing_scheme: EXTERNAL
+ name: vpn-remote-udp-500
+ no_automate_dns_zone: null
+ port_range: '500'
+ ports: null
+ project: project-id
+ recreate_closed_psc: false
+ region: europe-west8
+ service_label: null
+ source_ip_ranges: null
+ timeouts: null
+ module.vpn.google_compute_route.route["remote-0-10-10-0-0-24"]:
+ description: null
+ dest_range: 10.10.0.0/24
+ name: vpn-remote-remote-0-10-10-0-0-24
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ next_hop_gateway: null
+ next_hop_ilb: null
+ next_hop_instance: null
+ params: []
+ priority: 1000
+ project: project-id
+ tags: null
+ timeouts: null
+ module.vpn.google_compute_vpn_gateway.gateway:
+ description: null
+ name: remote
+ network: https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa
+ project: project-id
+ region: europe-west8
+ timeouts: null
+ module.vpn.google_compute_vpn_tunnel.tunnels["remote-0"]:
+ cipher_suite: []
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ike_version: 2
+ labels: null
+ local_traffic_selector:
+ - 0.0.0.0/0
+ name: remote-remote-0
+ peer_external_gateway: null
+ peer_external_gateway_interface: null
+ peer_gcp_gateway: null
+ peer_ip: 1.1.1.1
+ project: project-id
+ region: europe-west8
+ remote_traffic_selector:
+ - 0.0.0.0/0
+ router: null
+ shared_secret: mysecret
+ shared_secret_wo: null
+ shared_secret_wo_version: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ vpn_gateway: null
+ vpn_gateway_interface: null
+ module.vpn.random_id.secret:
+ byte_length: 8
+ keepers: null
+ prefix: null
+
+counts:
+ google_compute_address: 1
+ google_compute_forwarding_rule: 3
+ google_compute_route: 1
+ google_compute_vpn_gateway: 1
+ google_compute_vpn_tunnel: 1
+ modules: 2
+ random_id: 1
+ resources: 8
+
+outputs: {}