Files
hunfabric/modules/net-vpn-ha
Hemanand eaa420534b Add agent engine BYOC support (#3885)
* feat(agent-engine): add support for container and custom image specs

- Add container_config to deployment_files.
- Add image_spec with build_args to source_config.
- Make agent_framework optional and document supported values.
- Implement dynamic specs for container and source deployments.
- Add examples and automated tests for new deployment types.

* chore: update Google provider version to 7.28.0 across modules

Mechanical update of versions.tf and versions.tofu files using tools/versions.py.

* feat(agent-engine): refactor for container deployments and API alignment

- Group deployment settings under 'deployment_config' (renamed from 'deployment_files').
- Support container-based deployments via 'container_config' and 'image_spec'.
- Refactor 'source_files_config' (renamed from 'source_config') to include mutually exclusive 'python_spec' and 'image_spec'.
- Support 'developer_connect_config' as a source code type.
- Group engine settings (framework, env, secrets) under 'agent_engine_config'.
- Add support for 'memory_bank_config' persistent memory.
- Overhaul reasoning engine resources with dynamic blocks to match provider schema.
- Update all documentation examples, add TOC, and refresh test inventories.

* Update dynamic python_spec block and related example yamls

* Ignore changes setting for developer_connect_source under lifecycle management

* fixing review comments for `try` and default path for `source_path`

---------

Co-authored-by: Hemanand <hemr@google.com>
Co-authored-by: Julio Castillo <jccb@google.com>
2026-04-21 17:46:20 +00:00
..

Cloud HA VPN Module

This module makes it easy to deploy either GCP-to-GCP or GCP-to-On-prem Cloud HA VPN.

Examples

GCP to GCP

module "vpn-1" {
  source     = "./fabric/modules/net-vpn-ha"
  project_id = var.project_id
  region     = "europe-west4"
  network    = var.vpc1.self_link
  name       = "net1-to-net-2"
  peer_gateways = {
    default = { gcp = module.vpn-2.self_link }
  }
  router_config = {
    asn = 64514
    custom_advertise = {
      all_subnets = true
      ip_ranges = {
        "10.0.0.0/8" = "default"
      }
    }
  }
  tunnels = {
    remote-0 = {
      bgp_peer = {
        address = "169.254.1.1"
        asn     = 64513
      }
      bgp_session_range     = "169.254.1.2/30"
      vpn_gateway_interface = 0
    }
    remote-1 = {
      bgp_peer = {
        address = "169.254.2.1"
        asn     = 64513
      }
      bgp_session_range     = "169.254.2.2/30"
      vpn_gateway_interface = 1
    }
  }
}

module "vpn-2" {
  source        = "./fabric/modules/net-vpn-ha"
  project_id    = var.project_id
  region        = "europe-west4"
  network       = var.vpc2.self_link
  name          = "net2-to-net1"
  router_config = { asn = 64513 }
  peer_gateways = {
    default = { gcp = module.vpn-1.self_link }
  }
  tunnels = {
    remote-0 = {
      bgp_peer = {
        address = "169.254.1.2"
        asn     = 64514
      }
      bgp_session_range     = "169.254.1.1/30"
      shared_secret         = module.vpn-1.shared_secrets["remote-0"]
      vpn_gateway_interface = 0
    }
    remote-1 = {
      bgp_peer = {
        address = "169.254.2.2"
        asn     = 64514
      }
      bgp_session_range     = "169.254.2.1/30"
      shared_secret         = module.vpn-1.shared_secrets["remote-1"]
      vpn_gateway_interface = 1
    }
  }
}
# tftest modules=2 resources=22 inventory=gcp-to-gcp.yaml

Note: When using the for_each meta-argument you might experience a Cycle Error due to the multiple net-vpn-ha modules referencing each other. To fix this you can create the google_compute_ha_vpn_gateway resources separately and reference them in the net-vpn-ha module via the vpn_gateway and peer_gcp_gateway variables.

GCP to on-prem

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"
      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"
      peer_external_gateway_interface = 0
      shared_secret                   = "mySecret"
      vpn_gateway_interface           = 1
    }
  }
}
# tftest modules=1 resources=12 inventory=gcp-to-onprem.yaml

GCP to on-prem with custom ciphers

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.

module "vpn_ha" {
  source     = "./fabric/modules/net-vpn-ha"
  project_id = var.project_id
  region     = var.region
  name       = "mynet-to-onprem"
  network    = var.vpc.self_link
  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
        ipv6    = {}
      }
      bgp_session_range               = "169.254.1.2/30"
      peer_external_gateway_interface = 0
      shared_secret                   = "mySecret"
      vpn_gateway_interface           = 0
    }
    remote-1 = {
      bgp_peer = {
        address = "169.254.2.1"
        asn     = 64513
        ipv6 = {
          nexthop_address      = "2600:2d00:0:2::1"
          peer_nexthop_address = "2600:2d00:0:3::1"
        }
      }
      bgp_session_range               = "169.254.2.2/30"
      peer_external_gateway_interface = 0
      shared_secret                   = "mySecret"
      vpn_gateway_interface           = 1
    }
  }
  vpn_gateway_create = {
    ipv6 = true
  }
}
# 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.

Recipes

Variables

name description type required default
name VPN Gateway name (if an existing VPN Gateway is not used), and prefix used for dependent resources. string
network VPC used for the gateway and routes. string
project_id Project where resources will be created. string
region Region used for resources. string
router_config 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 Context-specific interpolations. object({…}) {}
peer_gateways Configuration of the (external or GCP) peer gateway. map(object({…})) {}
tunnels VPN tunnel configurations. map(object({…})) {}
vpn_gateway 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 Create HA VPN Gateway. Set to null to avoid creation. object({…}) {}

Outputs

name description sensitive
bgp_peers BGP peer resources.
external_gateway External VPN gateway resource.
gateway VPN gateway resource (only if auto-created).
id Fully qualified VPN gateway id.
md5_keys BGP tunnels MD5 keys.
name VPN gateway name (only if auto-created).
random_secret Generated secret.
router Router resource (only if auto-created).
router_name Router name.
self_link HA VPN gateway self link.
shared_secrets IPSEC tunnels shared secrets.
tunnel_names VPN tunnel names.
tunnel_self_links VPN tunnel self links.
tunnels VPN tunnel resources.