├── test ├── .gitignore ├── setup │ ├── .gitignore │ ├── versions.tf │ ├── variables.tf │ ├── main.tf │ ├── outputs.tf │ └── iam.tf └── integration │ ├── discover_test.go │ ├── vpn_ha │ └── vpn_ha_test.go │ ├── go.mod │ └── go.sum ├── docs ├── upgrading_to_vpn_v5.0.md ├── upgrading_to_vpn_v4.0.md ├── upgrading_to_vpn_v3.0.md └── upgrading_to_vpn_v2.0.md ├── .github ├── renovate.json ├── release-please.yml ├── trusted-contribution.yml └── workflows │ ├── stale.yml │ └── lint.yaml ├── CODEOWNERS ├── .gitignore ├── examples ├── multi_tunnels │ ├── variables.tf │ ├── mgmt.tf │ └── prod.tf ├── multi_external_vpn_gateways │ ├── variables.tf │ └── prod.tf ├── single_tunnels │ ├── mgmt.tf │ ├── prod.tf │ └── variables.tf └── vpn_ha │ ├── variables.tf │ ├── outputs.tf │ ├── mgmt.tf │ └── prod.tf ├── versions.tf ├── gateway.tf ├── modules └── vpn_ha │ ├── versions.tf │ ├── outputs.tf │ ├── variables.tf │ ├── metadata.yaml │ ├── main.tf │ └── README.md ├── .kitchen.yml ├── forwarding-rule.tf ├── outputs.tf ├── tunnel.tf ├── main.tf ├── Makefile ├── CONTRIBUTING.md ├── variables.tf ├── metadata.yaml ├── README.md ├── LICENSE └── CHANGELOG.md /test/.gitignore: -------------------------------------------------------------------------------- 1 | source.sh 2 | -------------------------------------------------------------------------------- /test/setup/.gitignore: -------------------------------------------------------------------------------- 1 | source.sh 2 | -------------------------------------------------------------------------------- /docs/upgrading_to_vpn_v5.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v5.0.0 2 | 3 | The v5.0 release contains backwards-incompatible changes. 4 | 5 | This update requires upgrading the minimum provider version `6.21`. 6 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>GoogleCloudPlatform/cloud-foundation-toolkit//infra/terraform/test-org/github/resources/renovate"] 4 | } 5 | -------------------------------------------------------------------------------- /docs/upgrading_to_vpn_v4.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v4.0.0 2 | 3 | The v4.0 release contains backwards-incompatible changes. 4 | 5 | This update requires upgrading the minimum provider version `5.7`. 6 | 7 | `google_compute_external_vpn_gateway`, `google_compute_router`, `google_compute_router_interface` and `google_compute_vpn_tunnel` are all set to use GA provider. 8 | -------------------------------------------------------------------------------- /docs/upgrading_to_vpn_v3.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v3.0.0 2 | 3 | The v3.0 release contains backwards-incompatible changes. 4 | 5 | This update requires upgrading the minimum provider version `4.74`. 6 | 7 | ### [Terraform](https://www.terraform.io/downloads.html) >= 1.3.0 is required as `peer_external_gateway`, `router_advertise_config`, `tunnels` and its nested attributes and objects are made optional 8 | Since [optional attributes](https://developer.hashicorp.com/terraform/language/expressions/type-constraints#optional-object-type-attributes) is a version 1.3 feature, the configuration will fail if the pinned version is < 1.3.. 9 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # NOTE: This file is automatically generated from values at: 2 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf 3 | 4 | * @terraform-google-modules/cft-admins @imrannayer 5 | 6 | # NOTE: GitHub CODEOWNERS locations: 7 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-and-branch-protection 8 | 9 | CODEOWNERS @terraform-google-modules/cft-admins 10 | .github/CODEOWNERS @terraform-google-modules/cft-admins 11 | docs/CODEOWNERS @terraform-google-modules/cft-admins 12 | 13 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | releaseType: terraform-module 16 | handleGHRelease: true 17 | -------------------------------------------------------------------------------- /test/setup/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 0.12" 19 | } 20 | -------------------------------------------------------------------------------- /test/setup/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | variable "org_id" { 17 | description = "The numeric organization id" 18 | } 19 | 20 | variable "folder_id" { 21 | description = "The folder to deploy in" 22 | } 23 | 24 | variable "billing_account" { 25 | description = "The billing account id associated with the project, e.g. XXXXXX-YYYYYY-ZZZZZZ" 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX leaves these everywhere on SMB shares 2 | ._* 3 | 4 | # OSX trash 5 | .DS_Store 6 | 7 | # Python 8 | *.pyc 9 | 10 | # Emacs save files 11 | *~ 12 | \#*\# 13 | .\#* 14 | 15 | # Vim-related files 16 | [._]*.s[a-w][a-z] 17 | [._]s[a-w][a-z] 18 | *.un~ 19 | Session.vim 20 | .netrwhist 21 | 22 | ### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore 23 | 24 | # Local .terraform directories 25 | **/.terraform/* 26 | 27 | # .tfstate files 28 | *.tfstate 29 | *.tfstate.* 30 | 31 | # Crash log files 32 | crash.log 33 | 34 | # Kitchen files 35 | **/inspec.lock 36 | **/.kitchen 37 | **/.kitchen.local.yml 38 | **/Gemfile.lock 39 | 40 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 41 | # .tfvars files are managed as part of configuration and so should be included in 42 | # version control. 43 | # 44 | # example.tfvars 45 | terraform.tfvars 46 | 47 | 48 | credentials.json 49 | 50 | # tf lock file 51 | .terraform.lock.hcl 52 | -------------------------------------------------------------------------------- /examples/multi_tunnels/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "prod_project_id" { 18 | type = string 19 | default = "" 20 | } 21 | 22 | variable "prod_network" { 23 | type = string 24 | default = "" 25 | } 26 | 27 | variable "mgt_project_id" { 28 | type = string 29 | default = "" 30 | } 31 | 32 | variable "mgt_network" { 33 | type = string 34 | default = "" 35 | } 36 | 37 | -------------------------------------------------------------------------------- /.github/trusted-contribution.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | annotations: 19 | - type: comment 20 | text: "/gcbrun" 21 | trustedContributors: 22 | - release-please[bot] 23 | - renovate[bot] 24 | - renovate-bot 25 | - forking-renovate[bot] 26 | - dependabot[bot] 27 | -------------------------------------------------------------------------------- /examples/multi_external_vpn_gateways/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "prod_project_id" { 18 | description = "Production Project ID." 19 | type = string 20 | } 21 | 22 | variable "prod_network_self_link" { 23 | description = "Production Network Self Link." 24 | type = string 25 | } 26 | 27 | variable "region" { 28 | description = "Region." 29 | type = string 30 | default = "europe-west4" 31 | } 32 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">=1.3" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | version = ">= 3.30.0, < 8" 23 | } 24 | random = { 25 | source = "hashicorp/random" 26 | version = "~> 3.4" 27 | } 28 | } 29 | 30 | provider_meta "google" { 31 | module_name = "blueprints/terraform/terraform-google-vpn/v6.1.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gateway.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | # Static External IP for the VPN Gateway 18 | resource "google_compute_address" "vpn_gw_ip" { 19 | count = var.vpn_gw_ip == "" ? 1 : 0 20 | name = "ip-${var.gateway_name}" 21 | region = var.region 22 | project = var.project_id 23 | } 24 | 25 | # VPN Gateways 26 | resource "google_compute_vpn_gateway" "vpn_gateway" { 27 | name = var.gateway_name 28 | network = var.network 29 | region = var.region 30 | project = var.project_id 31 | } 32 | 33 | -------------------------------------------------------------------------------- /test/integration/discover_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package test 16 | 17 | import ( 18 | // should be imported to enable testing for GO modules 19 | "testing" 20 | 21 | // should be imported to use terraform helpers in blueprints test framework 22 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 23 | ) 24 | 25 | // entry function for the test; can be named as Test* 26 | func TestAll(t *testing.T) { 27 | // the helper to autodiscover and test blueprint examples 28 | tft.AutoDiscoverAndTest(t) 29 | } 30 | -------------------------------------------------------------------------------- /examples/single_tunnels/mgmt.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module "vpn-gw-us-we1-mgt-prd-internal" { 18 | source = "terraform-google-modules/vpn/google" 19 | version = "~> 6.0" 20 | 21 | project_id = var.mgt_project_id 22 | network = var.mgt_network 23 | region = "us-west1" 24 | gateway_name = "vpn-gw-us-we1-mgt-prd-internal" 25 | tunnel_name_prefix = "vpn-tn-us-we1-mgt-prd-internal" 26 | shared_secret = "secrets" 27 | tunnel_count = 1 28 | peer_ips = [module.vpn-gw-us-we1-prd-mgt-internal.gateway_ip] 29 | 30 | route_priority = 1000 31 | remote_subnet = ["10.17.0.0/22", "10.16.80.0/24"] 32 | } 33 | -------------------------------------------------------------------------------- /examples/vpn_ha/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "prod_project_id" { 18 | description = "Production Project ID." 19 | type = string 20 | } 21 | 22 | variable "prod_network_self_link" { 23 | description = "Production Network Self Link." 24 | type = string 25 | } 26 | 27 | variable "mgt_project_id" { 28 | description = "Management Project ID." 29 | type = string 30 | } 31 | 32 | variable "mgt_network_self_link" { 33 | description = "Management Network Self Link." 34 | type = string 35 | } 36 | 37 | variable "region" { 38 | description = "Region." 39 | type = string 40 | default = "europe-west4" 41 | } 42 | -------------------------------------------------------------------------------- /examples/single_tunnels/prod.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module "vpn-gw-us-we1-prd-mgt-internal" { 18 | source = "terraform-google-modules/vpn/google" 19 | version = "~> 6.0" 20 | 21 | project_id = var.prod_project_id 22 | network = var.prod_network 23 | region = "us-west1" 24 | gateway_name = "vpn-gw-us-we1-prd-mgt-internal" 25 | tunnel_name_prefix = "vpn-tn-us-we1-prd-mgt-internal" 26 | shared_secret = "secrets" 27 | tunnel_count = 1 28 | peer_ips = [module.vpn-gw-us-we1-mgt-prd-internal.gateway_ip] 29 | 30 | route_priority = 1000 31 | remote_subnet = ["10.17.32.0/20", "10.17.16.0/20"] 32 | } 33 | 34 | -------------------------------------------------------------------------------- /modules/vpn_ha/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | version = ">= 6.21, < 8" 23 | } 24 | google-beta = { 25 | source = "hashicorp/google-beta" 26 | version = ">= 6.21, < 8" 27 | } 28 | random = { 29 | source = "hashicorp/random" 30 | version = "~> 3.4" 31 | } 32 | } 33 | 34 | provider_meta "google" { 35 | module_name = "blueprints/terraform/terraform-google-vpn/v6.1.0" 36 | } 37 | provider_meta "google-beta" { 38 | module_name = "blueprints/terraform/terraform-google-vpn/v6.1.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/single_tunnels/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | variable "prod_project_id" { 17 | type = string 18 | description = "The ID of the production project where the VPC will be created." 19 | } 20 | 21 | variable "prod_network" { 22 | type = string 23 | default = "default" 24 | description = "The name of the production VPC to be created." 25 | } 26 | 27 | variable "mgt_project_id" { 28 | type = string 29 | description = "The ID of the management project where the VPC will be created." 30 | } 31 | 32 | variable "mgt_network" { 33 | type = string 34 | default = "default" 35 | description = "The name of the management VPC to be created." 36 | } 37 | 38 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | platforms: 16 | - name: terraform 17 | 18 | provisioner: 19 | name: terraform 20 | 21 | suites: 22 | - name: single_tunnels 23 | driver: 24 | name: terraform 25 | root_module_directory: test/fixtures/single_tunnels 26 | verify_version: false 27 | command_timeout: 1800 28 | verifier: 29 | name: terraform 30 | color: false 31 | systems: 32 | - name: local 33 | backend: local 34 | controls: 35 | - local 36 | - name: vpn_ha 37 | driver: 38 | name: terraform 39 | root_module_directory: test/fixtures/vpn_ha 40 | verify_version: false 41 | command_timeout: 1800 42 | verifier: 43 | name: terraform 44 | color: false 45 | systems: 46 | - name: local 47 | backend: local 48 | controls: 49 | - gcloud 50 | -------------------------------------------------------------------------------- /test/setup/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module "prod-project" { 18 | source = "terraform-google-modules/project-factory/google" 19 | version = "~> 18.0" 20 | 21 | name = "ci-vpn" 22 | random_project_id = true 23 | auto_create_network = true 24 | org_id = var.org_id 25 | folder_id = var.folder_id 26 | billing_account = var.billing_account 27 | activate_apis = [ 28 | "cloudresourcemanager.googleapis.com", 29 | "compute.googleapis.com", 30 | ] 31 | } 32 | 33 | module "mgt-project" { 34 | source = "terraform-google-modules/project-factory/google" 35 | version = "~> 18.0" 36 | 37 | name = "ci-vpn" 38 | random_project_id = true 39 | auto_create_network = true 40 | org_id = var.org_id 41 | folder_id = var.folder_id 42 | billing_account = var.billing_account 43 | activate_apis = [ 44 | "cloudresourcemanager.googleapis.com", 45 | "compute.googleapis.com", 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /test/setup/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "prod_project_id" { 18 | value = module.prod-project.project_id 19 | description = "The name of the production VPC to be created." 20 | } 21 | 22 | output "prod_network_self_link" { 23 | value = format("https://www.googleapis.com/compute/v1/projects/%s/global/networks/default", module.prod-project.project_id) 24 | description = "Self link of the production VPC to be created." 25 | } 26 | 27 | output "mgt_project_id" { 28 | value = module.mgt-project.project_id 29 | description = "The ID of the management project where the VPC will be created." 30 | } 31 | 32 | output "mgt_network_self_link" { 33 | value = format("https://www.googleapis.com/compute/v1/projects/%s/global/networks/default", module.mgt-project.project_id) 34 | description = "Self link of the production VPC to be created." 35 | } 36 | 37 | output "sa_key" { 38 | value = google_service_account_key.int_test.private_key 39 | sensitive = true 40 | } 41 | -------------------------------------------------------------------------------- /test/setup/iam.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | int_required_roles = [ 19 | "roles/owner", 20 | "roles/compute.networkAdmin", 21 | "roles/compute.instanceAdmin", 22 | "roles/iam.serviceAccountUser", 23 | ] 24 | } 25 | 26 | resource "google_service_account" "int_test" { 27 | project = module.prod-project.project_id 28 | account_id = "vpn-int-test" 29 | display_name = "vpn-int-test" 30 | } 31 | 32 | resource "google_project_iam_member" "prod_int_test" { 33 | count = length(local.int_required_roles) 34 | 35 | project = module.prod-project.project_id 36 | role = local.int_required_roles[count.index] 37 | member = "serviceAccount:${google_service_account.int_test.email}" 38 | } 39 | 40 | resource "google_project_iam_member" "mgt_int_test" { 41 | count = length(local.int_required_roles) 42 | 43 | project = module.mgt-project.project_id 44 | role = local.int_required_roles[count.index] 45 | member = "serviceAccount:${google_service_account.int_test.email}" 46 | } 47 | 48 | resource "google_service_account_key" "int_test" { 49 | service_account_id = google_service_account.int_test.id 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | name: "Close stale issues" 19 | on: 20 | schedule: 21 | - cron: "0 23 * * *" 22 | 23 | permissions: 24 | contents: read 25 | issues: write 26 | pull-requests: write 27 | actions: write 28 | 29 | jobs: 30 | stale: 31 | if: github.repository_owner == 'GoogleCloudPlatform' || github.repository_owner == 'terraform-google-modules' 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/stale@v10 35 | with: 36 | repo-token: ${{ secrets.GITHUB_TOKEN }} 37 | stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' 38 | stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' 39 | exempt-issue-labels: 'triaged' 40 | exempt-pr-labels: 'dependencies,autorelease: pending' 41 | operations-per-run: 100 42 | -------------------------------------------------------------------------------- /examples/vpn_ha/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "mgt_project_id" { 18 | value = var.mgt_project_id 19 | } 20 | 21 | output "mgt_gateway_name" { 22 | description = "Mgt VPN gateway name." 23 | value = module.vpn-ha-to-prod.name 24 | } 25 | 26 | output "mgt_tunnel_names" { 27 | description = "Mgt VPN tunnel names." 28 | value = module.vpn-ha-to-prod.tunnel_names 29 | } 30 | 31 | output "mgt_tunnel_names_list" { 32 | description = "Mgt VPN tunnel names list." 33 | value = [for x, y in module.vpn-ha-to-prod.tunnel_names : y] 34 | } 35 | 36 | output "prod_project_id" { 37 | value = var.prod_project_id 38 | } 39 | 40 | output "prod_gateway_name" { 41 | description = "Prod VPN gateway name." 42 | value = module.vpn-ha-to-mgmt.name 43 | } 44 | 45 | output "prod_tunnel_names" { 46 | description = "Prod VPN tunnel names." 47 | value = module.vpn-ha-to-mgmt.tunnel_names 48 | } 49 | 50 | output "prod_tunnel_names_list" { 51 | description = "Prod VPN tunnel names list." 52 | value = [for x, y in module.vpn-ha-to-mgmt.tunnel_names : y] 53 | } 54 | 55 | output "region" { 56 | description = "Region" 57 | value = var.region 58 | } 59 | -------------------------------------------------------------------------------- /forwarding-rule.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | vpn_gw_ip = var.vpn_gw_ip == "" ? google_compute_address.vpn_gw_ip[0].address : var.vpn_gw_ip 19 | } 20 | # Assosciate external IP/Port-range to VPN-GW by using Forwarding rules 21 | resource "google_compute_forwarding_rule" "vpn_esp" { 22 | name = "${google_compute_vpn_gateway.vpn_gateway.name}-esp" 23 | ip_protocol = "ESP" 24 | ip_address = local.vpn_gw_ip 25 | target = google_compute_vpn_gateway.vpn_gateway.self_link 26 | project = var.project_id 27 | region = var.region 28 | } 29 | 30 | resource "google_compute_forwarding_rule" "vpn_udp500" { 31 | name = "${google_compute_vpn_gateway.vpn_gateway.name}-udp500" 32 | ip_protocol = "UDP" 33 | port_range = "500" 34 | ip_address = local.vpn_gw_ip 35 | target = google_compute_vpn_gateway.vpn_gateway.self_link 36 | project = var.project_id 37 | region = var.region 38 | } 39 | 40 | resource "google_compute_forwarding_rule" "vpn_udp4500" { 41 | name = "${google_compute_vpn_gateway.vpn_gateway.name}-udp4500" 42 | ip_protocol = "UDP" 43 | port_range = "4500" 44 | ip_address = local.vpn_gw_ip 45 | target = google_compute_vpn_gateway.vpn_gateway.self_link 46 | project = var.project_id 47 | region = var.region 48 | } 49 | 50 | -------------------------------------------------------------------------------- /examples/vpn_ha/mgmt.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | ##To Prod VPC 18 | module "vpn-ha-to-prod" { 19 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 20 | version = "~> 6.0" 21 | 22 | project_id = var.mgt_project_id 23 | region = var.region 24 | network = var.mgt_network_self_link 25 | name = "mgmt-to-prod" 26 | peer_gcp_gateway = module.vpn-ha-to-mgmt.self_link 27 | router_asn = 64514 28 | tunnels = { 29 | remote-0 = { 30 | bgp_peer = { 31 | address = "169.254.1.1" 32 | asn = 64513 33 | } 34 | bgp_peer_options = null 35 | bgp_session_range = "169.254.1.2/30" 36 | ike_version = 2 37 | vpn_gateway_interface = 0 38 | peer_external_gateway_interface = null 39 | shared_secret = "" 40 | } 41 | remote-1 = { 42 | bgp_peer = { 43 | address = "169.254.2.1" 44 | asn = 64513 45 | } 46 | bgp_peer_options = null 47 | bgp_session_range = "169.254.2.2/30" 48 | ike_version = 2 49 | vpn_gateway_interface = 1 50 | peer_external_gateway_interface = null 51 | shared_secret = "" 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/vpn_ha/prod.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | ##To MGMT VPC 18 | module "vpn-ha-to-mgmt" { 19 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 20 | version = "~> 6.0" 21 | 22 | project_id = var.prod_project_id 23 | region = var.region 24 | network = var.prod_network_self_link 25 | name = "prod-to-mgmt" 26 | router_asn = 64513 27 | peer_gcp_gateway = module.vpn-ha-to-prod.self_link 28 | tunnels = { 29 | remote-0 = { 30 | bgp_peer = { 31 | address = "169.254.1.2" 32 | asn = 64514 33 | } 34 | bgp_peer_options = null 35 | bgp_session_range = "169.254.1.1/30" 36 | ike_version = 2 37 | vpn_gateway_interface = 0 38 | peer_external_gateway_interface = null 39 | shared_secret = module.vpn-ha-to-prod.random_secret 40 | } 41 | remote-1 = { 42 | bgp_peer = { 43 | address = "169.254.2.2" 44 | asn = 64514 45 | } 46 | bgp_peer_options = null 47 | bgp_session_range = "169.254.2.1/30" 48 | ike_version = 2 49 | vpn_gateway_interface = 1 50 | peer_external_gateway_interface = null 51 | shared_secret = module.vpn-ha-to-prod.random_secret 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The Project-ID" 19 | value = google_compute_vpn_gateway.vpn_gateway.project 20 | } 21 | 22 | output "name" { 23 | description = "The name of the Gateway" 24 | value = google_compute_vpn_gateway.vpn_gateway.name 25 | } 26 | 27 | output "gateway_self_link" { 28 | description = "The self-link of the Gateway" 29 | value = google_compute_vpn_gateway.vpn_gateway.self_link 30 | } 31 | 32 | output "network" { 33 | description = "The name of the VPC" 34 | value = google_compute_vpn_gateway.vpn_gateway.network 35 | } 36 | 37 | output "gateway_ip" { 38 | description = "The VPN Gateway Public IP" 39 | value = local.vpn_gw_ip 40 | } 41 | 42 | output "vpn_tunnels_names-static" { 43 | description = "The VPN tunnel name is" 44 | value = google_compute_vpn_tunnel.tunnel-static[*].name 45 | } 46 | 47 | output "vpn_tunnels_self_link-static" { 48 | description = "The VPN tunnel self-link is" 49 | value = google_compute_vpn_tunnel.tunnel-static[*].self_link 50 | } 51 | 52 | output "ipsec_secret-static" { 53 | description = "The secret" 54 | value = google_compute_vpn_tunnel.tunnel-static[*].shared_secret 55 | sensitive = true 56 | } 57 | 58 | output "vpn_tunnels_names-dynamic" { 59 | description = "The VPN tunnel name is" 60 | value = google_compute_vpn_tunnel.tunnel-dynamic[*].name 61 | } 62 | 63 | output "vpn_tunnels_self_link-dynamic" { 64 | description = "The VPN tunnel self-link is" 65 | value = google_compute_vpn_tunnel.tunnel-dynamic[*].self_link 66 | } 67 | 68 | output "ipsec_secret-dynamic" { 69 | description = "The secret" 70 | value = google_compute_vpn_tunnel.tunnel-dynamic[*].shared_secret 71 | sensitive = true 72 | } 73 | -------------------------------------------------------------------------------- /modules/vpn_ha/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "gateway" { 18 | description = "HA VPN gateway resource." 19 | value = google_compute_ha_vpn_gateway.ha_gateway 20 | } 21 | 22 | output "external_gateway" { 23 | description = "External VPN gateway resource." 24 | value = ( 25 | var.peer_external_gateway != null 26 | ? google_compute_external_vpn_gateway.external_gateway[0] 27 | : null 28 | ) 29 | } 30 | 31 | output "name" { 32 | description = "VPN gateway name." 33 | value = regex("[\\w-]+$", lower(local.vpn_gateway_self_link)) 34 | } 35 | 36 | output "router" { 37 | description = "Router resource (only if auto-created)." 38 | value = var.router_name == "" ? google_compute_router.router[0] : null 39 | } 40 | 41 | output "router_name" { 42 | description = "Router name." 43 | value = local.router 44 | } 45 | 46 | output "self_link" { 47 | description = "HA VPN gateway self link." 48 | value = local.vpn_gateway_self_link 49 | } 50 | 51 | output "tunnels" { 52 | description = "VPN tunnel resources." 53 | sensitive = true 54 | value = { 55 | for name in keys(var.tunnels) : 56 | name => google_compute_vpn_tunnel.tunnels[name] 57 | } 58 | } 59 | 60 | output "tunnel_names" { 61 | description = "VPN tunnel names." 62 | value = { 63 | for name in keys(var.tunnels) : 64 | name => google_compute_vpn_tunnel.tunnels[name].name 65 | } 66 | } 67 | 68 | output "tunnel_self_links" { 69 | description = "VPN tunnel self links." 70 | sensitive = true 71 | value = { 72 | for name in keys(var.tunnels) : 73 | name => google_compute_vpn_tunnel.tunnels[name].self_link 74 | } 75 | } 76 | 77 | output "random_secret" { 78 | description = "Generated secret." 79 | sensitive = true 80 | value = local.secret 81 | } 82 | -------------------------------------------------------------------------------- /tunnel.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | # Creating the VPN tunnel 18 | resource "random_id" "ipsec_secret" { 19 | byte_length = var.ipsec_secret_length 20 | } 21 | 22 | resource "google_compute_vpn_tunnel" "tunnel-static" { 23 | count = !var.cr_enabled ? var.tunnel_count : 0 24 | name = var.tunnel_count == 1 ? format("%s-%s", local.tunnel_name_prefix, "1") : format("%s-%d", local.tunnel_name_prefix, count.index + 1) 25 | region = var.region 26 | project = var.project_id 27 | peer_ip = var.peer_ips[count.index] 28 | shared_secret = local.default_shared_secret 29 | 30 | target_vpn_gateway = google_compute_vpn_gateway.vpn_gateway.self_link 31 | local_traffic_selector = var.local_traffic_selector 32 | remote_traffic_selector = var.remote_traffic_selector 33 | 34 | ike_version = var.ike_version 35 | 36 | depends_on = [ 37 | google_compute_forwarding_rule.vpn_esp, 38 | google_compute_forwarding_rule.vpn_udp500, 39 | google_compute_forwarding_rule.vpn_udp4500, 40 | ] 41 | } 42 | 43 | resource "google_compute_vpn_tunnel" "tunnel-dynamic" { 44 | count = var.cr_enabled ? var.tunnel_count : 0 45 | name = var.tunnel_count == 1 ? format("%s-%s", local.tunnel_name_prefix, "1") : format("%s-%d", local.tunnel_name_prefix, count.index + 1) 46 | region = var.region 47 | project = var.project_id 48 | peer_ip = var.peer_ips[count.index] 49 | shared_secret = local.default_shared_secret 50 | 51 | target_vpn_gateway = google_compute_vpn_gateway.vpn_gateway.self_link 52 | 53 | router = var.cr_name 54 | ike_version = var.ike_version 55 | 56 | depends_on = [ 57 | google_compute_forwarding_rule.vpn_esp, 58 | google_compute_forwarding_rule.vpn_udp500, 59 | google_compute_forwarding_rule.vpn_udp4500, 60 | ] 61 | } 62 | 63 | -------------------------------------------------------------------------------- /docs/upgrading_to_vpn_v2.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to VPN v2.0 2 | 3 | The v2.0 release of the VPN module is a backward incompatible release. 4 | It only affects configurations which utilize dynamic routes with a 5 | Cloud Router. 6 | 7 | ## Upgrade Instructions 8 | 9 | In previous releases, using a Cloud Router required a hard-coded input 10 | of the Cloud Router name due to the use of the `cr_name` variable in an 11 | internal `count` expression which determines if a Cloud Router is to 12 | be used. 13 | 14 | ```hcl 15 | resource "google_compute_router" "cr_central1_to_mgt_vpc" { 16 | name = "cr-uscentral1-to-mgt-vpc-tunnels" 17 | region = "us-central1" 18 | network = var.prod_network 19 | project = var.prod_project_id 20 | 21 | bgp { 22 | asn = "64515" 23 | } 24 | } 25 | 26 | module "vpn_dynamic" { 27 | source = "terraform-google-modules/vpn/google" 28 | version = "~> 1.0" 29 | 30 | project_id = var.project_id 31 | network = var.network 32 | region = "us-west1" 33 | gateway_name = "vpn-gw-us-we1-dynamic" 34 | tunnel_name_prefix = "vpn-tn-us-we1-dynamic" 35 | shared_secret = "secrets" 36 | tunnel_count = 2 37 | peer_ips = ["1.1.1.1","2.2.2.2"] 38 | 39 | cr_name = "cr-uscentral1-to-mgt-vpc-tunnels" 40 | bgp_cr_session_range = ["169.254.0.1/30", "169.254.0.3/30"] 41 | bgp_remote_session_range = ["169.254.0.2", "169.254.0.4"] 42 | peer_asn = ["64516", "64517"] 43 | } 44 | ``` 45 | 46 | In the v2.0.0 release, the new `cr_enabled` variable is used to 47 | determine if a Cloud Router is to be used, which allows `cr_name` to 48 | support dynamic references to Cloud Router names. 49 | 50 | ```diff 51 | resource "google_compute_router" "cr_central1_to_mgt_vpc" { 52 | name = "cr-uscentral1-to-mgt-vpc-tunnels" 53 | region = "us-central1" 54 | network = var.prod_network 55 | project = var.prod_project_id 56 | 57 | bgp { 58 | asn = "64515" 59 | } 60 | } 61 | 62 | module "vpn-module-dynamic" { 63 | source = "terraform-google-modules/vpn/google" 64 | version = "~> 2.0" 65 | 66 | project_id = "var.project_id" 67 | network = "var.network" 68 | region = "us-west1" 69 | gateway_name = "vpn-gw-us-we1-dynamic" 70 | tunnel_name_prefix = "vpn-tn-us-we1-dynamic" 71 | shared_secret = "secrets" 72 | tunnel_count = 2 73 | peer_ips = ["1.1.1.1","2.2.2.2"] 74 | 75 | + cr_enabled = true 76 | - cr_name = "cr-uscentral1-to-mgt-vpc-tunnels" 77 | + cr_name = google_compute_router.cr_central1_to_mgt_vpc.name 78 | bgp_cr_session_range = ["169.254.0.1/30", "169.254.0.3/30"] 79 | bgp_remote_session_range = ["169.254.0.2", "169.254.0.4"] 80 | peer_asn = ["64516", "64517"] 81 | } 82 | ``` 83 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from values at: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf 17 | 18 | name: 'lint' 19 | 20 | on: 21 | workflow_dispatch: 22 | pull_request: 23 | types: [opened, edited, reopened, synchronize] 24 | branches: [main] 25 | 26 | permissions: 27 | contents: read 28 | 29 | concurrency: 30 | group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}' 31 | cancel-in-progress: true 32 | 33 | jobs: 34 | lint: 35 | name: 'lint' 36 | runs-on: 'ubuntu-latest' 37 | steps: 38 | - uses: 'actions/checkout@v6' 39 | - id: variables 40 | run: | 41 | MAKEFILE=$(find . -name Makefile -print -quit) 42 | if [ -z "$MAKEFILE" ]; then 43 | echo dev-tools=gcr.io/cloud-foundation-cicd/cft/developer-tools:1 >> "$GITHUB_OUTPUT" 44 | else 45 | VERSION=$(grep "DOCKER_TAG_VERSION_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) 46 | IMAGE=$(grep "DOCKER_IMAGE_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) 47 | REGISTRY=$(grep "REGISTRY_URL := " $MAKEFILE | cut -d\ -f3) 48 | echo dev-tools=${REGISTRY}/${IMAGE}:${VERSION} >> "$GITHUB_OUTPUT" 49 | fi 50 | - run: docker run --rm -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} module-swapper 51 | - run: docker run --rm -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} /usr/local/bin/test_lint.sh 52 | commitlint: 53 | runs-on: ubuntu-latest 54 | steps: 55 | - uses: actions/checkout@v6 56 | with: 57 | fetch-depth: 0 58 | - name: Setup node 59 | uses: actions/setup-node@v6 60 | with: 61 | node-version: lts/* 62 | - name: Install commitlint 63 | run: | 64 | npm install -D @commitlint/cli@20.2.0 @commitlint/config-conventional@20.2.0 65 | echo "module.exports = { extends: ['@commitlint/config-conventional'], rules: {'subject-case': [0], 'header-max-length': [0]} };" > commitlint.config.js 66 | npx commitlint --version 67 | - name: Validate PR commits with commitlint 68 | if: github.event_name == 'pull_request' 69 | env: 70 | TITLE: ${{ github.event.pull_request.title }} 71 | run: 'echo "$TITLE" | npx commitlint --verbose' 72 | -------------------------------------------------------------------------------- /test/integration/vpn_ha/vpn_ha_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package vpn_ha 16 | 17 | import ( 18 | "fmt" 19 | "testing" 20 | 21 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" 22 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestVpnHa(t *testing.T) { 27 | vpn := tft.NewTFBlueprintTest(t) 28 | 29 | vpn.DefineVerify(func(assert *assert.Assertions) { 30 | vpn.DefaultVerify(assert) 31 | 32 | prodProjectId := vpn.GetStringOutput("prod_project_id") 33 | mgtProjectId := vpn.GetStringOutput("mgt_project_id") 34 | mgtGatewayName := vpn.GetStringOutput("mgt_gateway_name") 35 | prodGatewayName := vpn.GetStringOutput("prod_gateway_name") 36 | mgtTunnelNames := vpn.GetStringOutput("mgt_tunnel_names_list") 37 | prodTunnelNames := vpn.GetStringOutput("prod_tunnel_names_list") 38 | region := vpn.GetStringOutput("region") 39 | 40 | mgtGateway := gcloud.Run(t, fmt.Sprintf("compute vpn-gateways describe %s --project %s --region=%s", mgtGatewayName, mgtProjectId, region)) 41 | assert.Equal(mgtGatewayName, mgtGateway.Get("name").String(), "has expected name") 42 | assert.Equal("IPV4_ONLY", mgtGateway.Get("stackType").String(), "has expected stackType") 43 | mgtVpnInterfaces := mgtGateway.Get("vpnInterfaces").Array() 44 | assert.Equal(2, len(mgtVpnInterfaces), "found 2 vpnInterfaces") 45 | 46 | prodGateway := gcloud.Run(t, fmt.Sprintf("compute vpn-gateways describe %s --project %s --region=%s", prodGatewayName, prodProjectId, region)) 47 | assert.Equal(prodGatewayName, prodGateway.Get("name").String(), "has expected name") 48 | assert.Equal("IPV4_ONLY", prodGateway.Get("stackType").String(), "has expected stackType") 49 | prodVpnInterfaces := prodGateway.Get("vpnInterfaces").Array() 50 | assert.Equal(2, len(prodVpnInterfaces), "found 2 vpnInterfaces") 51 | 52 | mgtTunnel := gcloud.Run(t, fmt.Sprintf("compute vpn-tunnels list --project %s", mgtProjectId)) 53 | for _, tunnel := range mgtTunnel.Array() { 54 | assert.Contains(mgtTunnelNames, tunnel.Get("name").String(), "tunnel name matched") 55 | } 56 | 57 | prodTunnel := gcloud.Run(t, fmt.Sprintf("compute vpn-tunnels list --project %s", prodProjectId)) 58 | for _, tunnel := range prodTunnel.Array() { 59 | assert.Contains(prodTunnelNames, tunnel.Get("name").String(), "tunnel name matched") 60 | } 61 | 62 | }) 63 | vpn.Test() 64 | } 65 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | tunnel_name_prefix = var.tunnel_name_prefix != "" ? var.tunnel_name_prefix : "${var.network}-${var.gateway_name}-tunnel" 19 | default_shared_secret = var.shared_secret != "" ? var.shared_secret : random_id.ipsec_secret.b64_url 20 | } 21 | 22 | # For VPN gateways with static routing 23 | ## Create Route (for static routing gateways) 24 | resource "google_compute_route" "route" { 25 | count = !var.cr_enabled ? var.tunnel_count * length(var.remote_subnet) : 0 26 | name = "${google_compute_vpn_gateway.vpn_gateway.name}-tunnel${floor(count.index / length(var.remote_subnet)) + 1}-route${count.index % length(var.remote_subnet) + 1}" 27 | network = var.network 28 | project = var.project_id 29 | dest_range = var.remote_subnet[count.index % length(var.remote_subnet)] 30 | priority = var.route_priority 31 | tags = var.route_tags 32 | 33 | next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel-static[floor(count.index / length(var.remote_subnet))].self_link 34 | 35 | depends_on = [google_compute_vpn_tunnel.tunnel-static] 36 | } 37 | 38 | # For VPN gateways routing through BGP and Cloud Routers 39 | ## Create Router Interfaces 40 | resource "google_compute_router_interface" "router_interface" { 41 | count = var.cr_enabled ? var.tunnel_count : 0 42 | name = "interface-${local.tunnel_name_prefix}-${count.index}" 43 | router = var.cr_name 44 | region = var.region 45 | ip_range = var.bgp_cr_session_range[count.index] 46 | vpn_tunnel = google_compute_vpn_tunnel.tunnel-dynamic[count.index].name 47 | project = var.project_id 48 | 49 | depends_on = [google_compute_vpn_tunnel.tunnel-dynamic] 50 | } 51 | 52 | ## Create Peers 53 | resource "google_compute_router_peer" "bgp_peer" { 54 | count = var.cr_enabled ? var.tunnel_count : 0 55 | name = "bgp-session-${local.tunnel_name_prefix}-${count.index}" 56 | router = var.cr_name 57 | region = var.region 58 | peer_ip_address = var.bgp_remote_session_range[count.index] 59 | peer_asn = var.peer_asn[count.index] 60 | advertised_route_priority = var.advertised_route_priority 61 | interface = "interface-${local.tunnel_name_prefix}-${count.index}" 62 | project = var.project_id 63 | 64 | depends_on = [google_compute_router_interface.router_interface] 65 | } 66 | 67 | -------------------------------------------------------------------------------- /test/integration/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/terraform-google-cloud-armor/test/integration 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.24.7 6 | 7 | require ( 8 | github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9 9 | github.com/stretchr/testify v1.11.1 10 | ) 11 | 12 | require ( 13 | github.com/agext/levenshtein v1.2.3 // indirect 14 | github.com/alexflint/go-filemutex v1.3.0 // indirect 15 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 16 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 17 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 18 | github.com/go-errors/errors v1.5.0 // indirect 19 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 20 | github.com/go-openapi/jsonreference v0.20.2 // indirect 21 | github.com/go-openapi/swag v0.23.0 // indirect 22 | github.com/google/gnostic-models v0.6.9 // indirect 23 | github.com/google/go-cmp v0.7.0 // indirect 24 | github.com/gruntwork-io/terratest v0.50.0 // indirect 25 | github.com/hashicorp/errwrap v1.1.0 // indirect 26 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 27 | github.com/hashicorp/go-getter/v2 v2.2.3 // indirect 28 | github.com/hashicorp/go-multierror v1.1.1 // indirect 29 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 30 | github.com/hashicorp/go-version v1.7.0 // indirect 31 | github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f // indirect 32 | github.com/hashicorp/hcl/v2 v2.22.0 // indirect 33 | github.com/hashicorp/terraform-config-inspect v0.0.0-20250731202709-e8a84eebd3e7 // indirect 34 | github.com/hashicorp/terraform-json v0.26.0 // indirect 35 | github.com/jinzhu/copier v0.4.0 // indirect 36 | github.com/josharian/intern v1.0.0 // indirect 37 | github.com/klauspost/compress v1.16.7 // indirect 38 | github.com/mailru/easyjson v0.7.7 // indirect 39 | github.com/mattn/go-shellwords v1.0.12 // indirect 40 | github.com/mattn/go-zglob v0.0.4 // indirect 41 | github.com/mitchellh/go-homedir v1.1.0 // indirect 42 | github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 // indirect 43 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 44 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 45 | github.com/tidwall/gjson v1.18.0 // indirect 46 | github.com/tidwall/match v1.1.1 // indirect 47 | github.com/tidwall/pretty v1.2.1 // indirect 48 | github.com/tidwall/sjson v1.2.5 // indirect 49 | github.com/tmccombs/hcl2json v0.6.4 // indirect 50 | github.com/ulikunitz/xz v0.5.14 // indirect 51 | github.com/zclconf/go-cty v1.16.3 // indirect 52 | go.yaml.in/yaml/v2 v2.4.2 // indirect 53 | go.yaml.in/yaml/v3 v3.0.3 // indirect 54 | golang.org/x/crypto v0.40.0 // indirect 55 | golang.org/x/mod v0.27.0 // indirect 56 | golang.org/x/net v0.42.0 // indirect 57 | golang.org/x/sync v0.16.0 // indirect 58 | golang.org/x/sys v0.34.0 // indirect 59 | golang.org/x/text v0.27.0 // indirect 60 | golang.org/x/tools v0.35.0 // indirect 61 | google.golang.org/protobuf v1.36.1 // indirect 62 | gopkg.in/yaml.v3 v3.0.1 // indirect 63 | k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect 64 | sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect 65 | ) 66 | -------------------------------------------------------------------------------- /examples/multi_external_vpn_gateways/prod.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | # Creating an external VPN gateway IP for DC1 18 | resource "google_compute_external_vpn_gateway" "external_gateway1" { 19 | provider = google-beta 20 | name = "vpn-peering-gw1" 21 | project = var.prod_project_id 22 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" 23 | description = "My VPN peering gateway1" 24 | 25 | interface { 26 | id = 0 27 | ip_address = "8.8.8.8" 28 | } 29 | } 30 | 31 | # Creating an external VPN gateway IP for DC2 32 | resource "google_compute_external_vpn_gateway" "external_gateway2" { 33 | provider = google-beta 34 | name = "vpn-peering-gw2" 35 | project = var.prod_project_id 36 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" 37 | description = "My VPN peering gateway2" 38 | 39 | interface { 40 | id = 0 41 | ip_address = "8.4.4.8" 42 | } 43 | } 44 | 45 | # In order to have successful setup, you need to configure the On-Premise 46 | # VPN by this below tunnels configuration. 47 | 48 | module "vpn-ha-to-onprem" { 49 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 50 | version = "~> 6.0" 51 | 52 | project_id = var.prod_project_id 53 | region = var.region 54 | network = var.prod_network_self_link 55 | name = "prod-to-onprem" 56 | router_asn = 64512 57 | 58 | tunnels = { 59 | # DC1 remote tunnel with specific external VPN gateway 60 | remote-0 = { 61 | bgp_peer = { 62 | address = "169.254.1.2" 63 | asn = 64515 64 | } 65 | bgp_peer_options = null 66 | bgp_session_range = "169.254.1.1/30" 67 | ike_version = 2 68 | vpn_gateway_interface = 0 69 | peer_external_gateway_self_link = google_compute_external_vpn_gateway.external_gateway1.self_link 70 | peer_external_gateway_interface = 0 71 | shared_secret = "Secret1" 72 | } 73 | 74 | # DC2 remote tunnel with specific external VPN gateway 75 | remote-1 = { 76 | bgp_peer = { 77 | address = "169.254.2.2" 78 | asn = 64516 79 | } 80 | bgp_peer_options = null 81 | bgp_session_range = "169.254.2.1/30" 82 | ike_version = 2 83 | vpn_gateway_interface = 1 84 | peer_external_gateway_self_link = google_compute_external_vpn_gateway.external_gateway2.self_link 85 | peer_external_gateway_interface = 0 86 | shared_secret = "Secret2" 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Please note that this file was generated from [terraform-google-module-template](https://github.com/terraform-google-modules/terraform-google-module-template). 16 | # Please make sure to contribute relevant changes upstream! 17 | 18 | # Make will use bash instead of sh 19 | SHELL := /usr/bin/env bash 20 | 21 | DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.25 22 | DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools 23 | REGISTRY_URL := gcr.io/cloud-foundation-cicd 24 | 25 | # Enter docker container for local development 26 | .PHONY: docker_run 27 | docker_run: 28 | docker run --rm -it \ 29 | -e SERVICE_ACCOUNT_JSON \ 30 | -v "$(CURDIR)":/workspace \ 31 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 32 | /bin/bash 33 | 34 | # Execute prepare tests within the docker container 35 | .PHONY: docker_test_prepare 36 | docker_test_prepare: 37 | docker run --rm -it \ 38 | -e SERVICE_ACCOUNT_JSON \ 39 | -e TF_VAR_org_id \ 40 | -e TF_VAR_folder_id \ 41 | -e TF_VAR_billing_account \ 42 | -v "$(CURDIR)":/workspace \ 43 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 44 | /usr/local/bin/execute_with_credentials.sh prepare_environment 45 | 46 | # Clean up test environment within the docker container 47 | .PHONY: docker_test_cleanup 48 | docker_test_cleanup: 49 | docker run --rm -it \ 50 | -e SERVICE_ACCOUNT_JSON \ 51 | -e TF_VAR_org_id \ 52 | -e TF_VAR_folder_id \ 53 | -e TF_VAR_billing_account \ 54 | -v "$(CURDIR)":/workspace \ 55 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 56 | /usr/local/bin/execute_with_credentials.sh cleanup_environment 57 | 58 | # Execute integration tests within the docker container 59 | .PHONY: docker_test_integration 60 | docker_test_integration: 61 | docker run --rm -it \ 62 | -e SERVICE_ACCOUNT_JSON \ 63 | -v "$(CURDIR)":/workspace \ 64 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 65 | /usr/local/bin/test_integration.sh 66 | 67 | # Execute lint tests within the docker container 68 | .PHONY: docker_test_lint 69 | docker_test_lint: 70 | docker run --rm -it \ 71 | -e EXCLUDE_LINT_DIRS \ 72 | -v "$(CURDIR)":/workspace \ 73 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 74 | /usr/local/bin/test_lint.sh 75 | 76 | # Generate documentation 77 | .PHONY: docker_generate_docs 78 | docker_generate_docs: 79 | docker run --rm -it \ 80 | -v "$(CURDIR)":/workspace \ 81 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 82 | /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_docs' 83 | 84 | # Alias for backwards compatibility 85 | .PHONY: generate_docs 86 | generate_docs: docker_generate_docs 87 | -------------------------------------------------------------------------------- /examples/multi_tunnels/mgmt.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | ##To Prod VPC 18 | resource "google_compute_router" "cr-uscentral1-to-prod-vpc-01" { 19 | name = "cr-uscentral1-to-prod-vpc-tunnels-01" 20 | region = "us-central1" 21 | network = var.mgt_network 22 | project = var.mgt_project_id 23 | 24 | bgp { 25 | asn = "64516" 26 | } 27 | } 28 | 29 | resource "google_compute_router" "cr-uscentral1-to-prod-vpc-02" { 30 | name = "cr-uscentral1-to-prod-vpc-tunnels-02" 31 | region = "us-central1" 32 | network = var.mgt_network 33 | project = var.mgt_project_id 34 | 35 | bgp { 36 | asn = "64521" 37 | } 38 | } 39 | 40 | module "vpn-gw-us-ce1-mgt-prd-internal-01" { 41 | source = "terraform-google-modules/vpn/google" 42 | version = "~> 6.0" 43 | 44 | project_id = var.mgt_project_id 45 | network = var.mgt_network 46 | region = "us-central1" 47 | gateway_name = "vpn-gw-us-ce1-mgt-prd-internal-01" 48 | tunnel_name_prefix = "vpn-tn-us-ce1-mgt-prd-internal-01-tunnel" 49 | shared_secret = "secrets" 50 | tunnel_count = 2 51 | peer_ips = [module.vpn-gw-us-ce1-prd-mgt-internal-01.gateway_ip, module.vpn-gw-us-ce1-prd-mgt-internal-02.gateway_ip] 52 | 53 | cr_name = "cr-uscentral1-to-prod-vpc-tunnels-01" 54 | cr_enabled = true 55 | bgp_cr_session_range = ["169.254.0.2/30", "169.254.0.26/30"] 56 | bgp_remote_session_range = ["169.254.0.1", "169.254.0.25"] 57 | peer_asn = ["64515", "64520"] 58 | } 59 | 60 | module "vpn-gw-us-ce1-mgt-prd-internal-02" { 61 | source = "terraform-google-modules/vpn/google" 62 | version = "~> 6.0" 63 | 64 | project_id = var.mgt_project_id 65 | network = var.mgt_network 66 | region = "us-central1" 67 | gateway_name = "vpn-gw-us-ce1-mgt-prd-internal-02" 68 | tunnel_name_prefix = "vpn-tn-us-ce1-mgt-prd-internal-02-tunnel" 69 | shared_secret = "secrets" 70 | tunnel_count = 2 71 | peer_ips = [module.vpn-gw-us-ce1-prd-mgt-internal-02.gateway_ip, module.vpn-gw-us-ce1-prd-mgt-internal-01.gateway_ip] 72 | 73 | cr_name = "cr-uscentral1-to-prod-vpc-tunnels-02" 74 | cr_enabled = true 75 | bgp_cr_session_range = ["169.254.0.6/30", "169.254.0.22/30"] 76 | bgp_remote_session_range = ["169.254.0.5", "169.254.0.21"] 77 | peer_asn = ["64520", "64515"] 78 | } 79 | 80 | module "vpn-gw-us-we1-mgt-prd-internal" { 81 | source = "terraform-google-modules/vpn/google" 82 | version = "~> 6.0" 83 | 84 | project_id = var.mgt_project_id 85 | network = var.mgt_network 86 | region = "us-west1" 87 | gateway_name = "vpn-gw-us-we1-mgt-prd-internal" 88 | tunnel_name_prefix = "vpn-tn-us-we1-mgt-prd-internal" 89 | shared_secret = "secrets" 90 | tunnel_count = 1 91 | peer_ips = [module.vpn-gw-us-we1-prd-mgt-internal.gateway_ip] 92 | 93 | route_priority = 1000 94 | remote_subnet = ["10.17.0.0/22", "10.16.80.0/24"] 95 | } 96 | 97 | -------------------------------------------------------------------------------- /examples/multi_tunnels/prod.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | ##To MGMT VPC 18 | resource "google_compute_router" "cr-uscentral1-to-mgt-vpc-01" { 19 | name = "cr-uscentral1-to-mgt-vpc-tunnels-01" 20 | region = "us-central1" 21 | network = var.prod_network 22 | project = var.prod_project_id 23 | 24 | bgp { 25 | asn = "64515" 26 | } 27 | } 28 | 29 | resource "google_compute_router" "cr-uscentral1-to-mgt-vpc-02" { 30 | name = "cr-uscentral1-to-mgt-vpc-tunnels-02" 31 | region = "us-central1" 32 | network = var.prod_network 33 | project = var.prod_project_id 34 | 35 | bgp { 36 | asn = "64520" 37 | } 38 | } 39 | 40 | module "vpn-gw-us-ce1-prd-mgt-internal-01" { 41 | source = "terraform-google-modules/vpn/google" 42 | version = "~> 6.0" 43 | 44 | project_id = var.prod_project_id 45 | network = var.prod_network 46 | region = "us-central1" 47 | gateway_name = "vpn-gw-us-ce1-prd-mgt-internal-01" 48 | tunnel_name_prefix = "vpn-tn-us-ce1-prd-mgt-internal-01-tunnel" 49 | shared_secret = "secrets" 50 | tunnel_count = 2 51 | peer_ips = [module.vpn-gw-us-ce1-mgt-prd-internal-01.gateway_ip, module.vpn-gw-us-ce1-mgt-prd-internal-02.gateway_ip] 52 | 53 | cr_name = "cr-uscentral1-to-mgt-vpc-tunnels-01" 54 | cr_enabled = true 55 | bgp_cr_session_range = ["169.254.0.1/30", "169.254.0.21/30"] 56 | bgp_remote_session_range = ["169.254.0.2", "169.254.0.22"] 57 | peer_asn = ["64516", "64521"] 58 | } 59 | 60 | module "vpn-gw-us-ce1-prd-mgt-internal-02" { 61 | source = "terraform-google-modules/vpn/google" 62 | version = "~> 6.0" 63 | 64 | project_id = var.prod_project_id 65 | network = var.prod_network 66 | region = "us-central1" 67 | gateway_name = "vpn-gw-us-ce1-prd-mgt-internal-02" 68 | tunnel_name_prefix = "vpn-tn-us-ce1-prd-mgt-internal-02-tunnel" 69 | shared_secret = "secrets" 70 | tunnel_count = 2 71 | peer_ips = [module.vpn-gw-us-ce1-mgt-prd-internal-02.gateway_ip, module.vpn-gw-us-ce1-mgt-prd-internal-01.gateway_ip] 72 | 73 | cr_name = "cr-uscentral1-to-mgt-vpc-tunnels-02" 74 | cr_enabled = true 75 | bgp_cr_session_range = ["169.254.0.5/30", "169.254.0.25/30"] 76 | bgp_remote_session_range = ["169.254.0.6", "169.254.0.26"] 77 | peer_asn = ["64521", "64516"] 78 | } 79 | 80 | module "vpn-gw-us-we1-prd-mgt-internal" { 81 | source = "terraform-google-modules/vpn/google" 82 | version = "~> 6.0" 83 | 84 | project_id = var.prod_project_id 85 | network = var.prod_network 86 | region = "us-west1" 87 | gateway_name = "vpn-gw-us-we1-prd-mgt-internal" 88 | tunnel_name_prefix = "vpn-tn-us-we1-prd-mgt-internal" 89 | shared_secret = "secrets" 90 | tunnel_count = 1 91 | peer_ips = [module.vpn-gw-us-we1-mgt-prd-internal.gateway_ip] 92 | 93 | route_priority = 1000 94 | remote_subnet = ["10.17.32.0/20", "10.17.16.0/20"] 95 | } 96 | 97 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This document provides guidelines for contributing to the module. 4 | 5 | ## Dependencies 6 | 7 | The following dependencies must be installed on the development system: 8 | 9 | - [Docker Engine][docker-engine] 10 | - [Google Cloud SDK][google-cloud-sdk] 11 | - [make] 12 | 13 | ## Generating Documentation for Inputs and Outputs 14 | 15 | The Inputs and Outputs tables in the READMEs of the root module, 16 | submodules, and example modules are automatically generated based on 17 | the `variables` and `outputs` of the respective modules. These tables 18 | must be refreshed if the module interfaces are changed. 19 | 20 | ### Execution 21 | 22 | Run `make generate_docs` to generate new Inputs and Outputs tables. 23 | 24 | ## Integration Testing 25 | 26 | Integration tests are used to verify the behaviour of the root module, 27 | submodules, and example modules. Additions, changes, and fixes should 28 | be accompanied with tests. 29 | 30 | The integration tests are run using [Kitchen][kitchen], 31 | [Kitchen-Terraform][kitchen-terraform], and [InSpec][inspec]. These 32 | tools are packaged within a Docker image for convenience. 33 | 34 | The general strategy for these tests is to verify the behaviour of the 35 | [example modules](./examples/), thus ensuring that the root module, 36 | submodules, and example modules are all functionally correct. 37 | 38 | ### Test Environment 39 | The easiest way to test the module is in an isolated test project. The setup for such a project is defined in [test/setup](./test/setup/) directory. 40 | 41 | To use this setup, you need a service account with Project Creator access on a folder. Export the Service Account credentials to your environment like so: 42 | 43 | ``` 44 | export SERVICE_ACCOUNT_JSON=$(< credentials.json) 45 | ``` 46 | 47 | You will also need to set a few environment variables: 48 | ``` 49 | export TF_VAR_org_id="your_org_id" 50 | export TF_VAR_folder_id="your_folder_id" 51 | export TF_VAR_billing_account="your_billing_account_id" 52 | ``` 53 | 54 | With these settings in place, you can prepare a test project using Docker: 55 | ``` 56 | make docker_test_prepare 57 | ``` 58 | 59 | ### Noninteractive Execution 60 | 61 | Run `make docker_test_integration` to test all of the example modules 62 | noninteractively, using the prepared test project. 63 | 64 | ### Interactive Execution 65 | 66 | 1. Run `make docker_run` to start the testing Docker container in 67 | interactive mode. 68 | 69 | 1. Run `kitchen_do create ` to initialize the working 70 | directory for an example module. 71 | 72 | 1. Run `kitchen_do converge ` to apply the example module. 73 | 74 | 1. Run `kitchen_do verify ` to test the example module. 75 | 76 | 1. Run `kitchen_do destroy ` to destroy the example module 77 | state. 78 | 79 | ## Linting and Formatting 80 | 81 | Many of the files in the repository can be linted or formatted to 82 | maintain a standard of quality. 83 | 84 | ### Execution 85 | 86 | Run `make docker_test_lint`. 87 | 88 | [docker-engine]: https://www.docker.com/products/docker-engine 89 | [flake8]: http://flake8.pycqa.org/en/latest/ 90 | [gofmt]: https://golang.org/cmd/gofmt/ 91 | [google-cloud-sdk]: https://cloud.google.com/sdk/install 92 | [hadolint]: https://github.com/hadolint/hadolint 93 | [inspec]: https://inspec.io/ 94 | [kitchen-terraform]: https://github.com/newcontext-oss/kitchen-terraform 95 | [kitchen]: https://kitchen.ci/ 96 | [make]: https://en.wikipedia.org/wiki/Make_(software) 97 | [shellcheck]: https://www.shellcheck.net/ 98 | [terraform-docs]: https://github.com/segmentio/terraform-docs 99 | [terraform]: https://terraform.io/ 100 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The ID of the project where this VPC will be created" 20 | } 21 | 22 | variable "network" { 23 | type = string 24 | description = "The name of VPC being created" 25 | } 26 | 27 | variable "region" { 28 | type = string 29 | description = "The region in which you want to create the VPN gateway" 30 | } 31 | 32 | variable "gateway_name" { 33 | type = string 34 | description = "The name of VPN gateway" 35 | default = "test-vpn" 36 | } 37 | 38 | variable "tunnel_count" { 39 | type = number 40 | description = "The number of tunnels from each VPN gw (default is 1)" 41 | default = 1 42 | } 43 | 44 | variable "tunnel_name_prefix" { 45 | type = string 46 | description = "The optional custom name of VPN tunnel being created" 47 | default = "" 48 | } 49 | 50 | variable "local_traffic_selector" { 51 | description = <=0.13.0' 30 | examples: 31 | - name: multi_tunnels 32 | location: examples/multi_tunnels 33 | - name: single_tunnels 34 | location: examples/single_tunnels 35 | - name: vpn_ha 36 | location: examples/vpn_ha 37 | variables: 38 | - name: create_vpn_gateway 39 | description: create a VPN gateway 40 | type: bool 41 | default: true 42 | required: false 43 | - name: labels 44 | description: Labels for vpn components 45 | type: map(string) 46 | default: {} 47 | required: false 48 | - name: name 49 | description: VPN gateway name, and prefix used for dependent resources. 50 | type: string 51 | required: true 52 | - name: network 53 | description: VPC used for the gateway and routes. 54 | type: string 55 | required: true 56 | - name: peer_external_gateway 57 | description: Configuration of an external VPN gateway to which this VPN is connected. 58 | type: |- 59 | object({ 60 | redundancy_type = string 61 | interfaces = list(object({ 62 | id = number 63 | ip_address = string 64 | })) 65 | }) 66 | required: false 67 | - name: peer_gcp_gateway 68 | description: Self Link URL of the peer side HA GCP VPN gateway to which this VPN tunnel is connected. 69 | type: string 70 | required: false 71 | - name: project_id 72 | description: Project where resources will be created. 73 | type: string 74 | required: true 75 | - name: region 76 | description: Region used for resources. 77 | type: string 78 | required: true 79 | - name: route_priority 80 | description: Route priority, defaults to 1000. 81 | type: number 82 | default: 1000 83 | required: false 84 | - name: router_advertise_config 85 | description: Router custom advertisement configuration, ip_ranges is a map of address ranges and descriptions. 86 | type: |- 87 | object({ 88 | groups = list(string) 89 | ip_ranges = map(string) 90 | mode = string 91 | }) 92 | required: false 93 | - name: router_asn 94 | description: Router ASN used for auto-created router. 95 | type: number 96 | default: 64514 97 | required: false 98 | - name: router_name 99 | description: Name of router, leave blank to create one. 100 | type: string 101 | default: "" 102 | required: false 103 | - name: tunnels 104 | description: VPN tunnel configurations, bgp_peer_options is usually null. 105 | type: |- 106 | map(object({ 107 | bgp_peer = object({ 108 | address = string 109 | asn = number 110 | }) 111 | bgp_peer_options = object({ 112 | ip_address = string 113 | advertise_groups = list(string) 114 | advertise_ip_ranges = map(string) 115 | advertise_mode = string 116 | route_priority = number 117 | }) 118 | bgp_session_range = string 119 | ike_version = number 120 | vpn_gateway_interface = number 121 | peer_external_gateway_interface = number 122 | shared_secret = string 123 | })) 124 | default: {} 125 | required: false 126 | - name: vpn_gateway_self_link 127 | description: self_link of existing VPN gateway to be used for the vpn tunnel 128 | type: string 129 | required: false 130 | outputs: 131 | - name: external_gateway 132 | description: External VPN gateway resource. 133 | - name: gateway 134 | description: HA VPN gateway resource. 135 | - name: name 136 | description: VPN gateway name. 137 | - name: random_secret 138 | description: Generated secret. 139 | - name: router 140 | description: Router resource (only if auto-created). 141 | - name: router_name 142 | description: Router name. 143 | - name: self_link 144 | description: HA VPN gateway self link. 145 | - name: tunnel_names 146 | description: VPN tunnel names. 147 | - name: tunnel_self_links 148 | description: VPN tunnel self links. 149 | - name: tunnels 150 | description: VPN tunnel resources. 151 | roles: 152 | - level: Project 153 | roles: 154 | - roles/owner 155 | - roles/compute.networkAdmin 156 | - roles/compute.instanceAdmin 157 | - roles/iam.serviceAccountUser 158 | services: 159 | - cloudresourcemanager.googleapis.com 160 | - compute.googleapis.com 161 | -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-vpn 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | title: 'Terraform Google Cloud Platform - ' 23 | source: 24 | repo: https://github.com/terraform-google-modules/terraform-google-vpn 25 | sourceType: git 26 | version: 6.1.0 27 | actuationTool: 28 | type: Terraform 29 | version: '>=0.13.0' 30 | subBlueprints: 31 | - name: vpn_ha 32 | location: modules/vpn_ha 33 | examples: 34 | - name: multi_tunnels 35 | location: examples/multi_tunnels 36 | - name: single_tunnels 37 | location: examples/single_tunnels 38 | - name: vpn_ha 39 | location: examples/vpn_ha 40 | variables: 41 | - name: advertised_route_priority 42 | description: Please enter the priority for the advertised route to BGP peer(default is 100) 43 | type: number 44 | default: 100 45 | required: false 46 | - name: bgp_cr_session_range 47 | description: Please enter the cloud-router interface IP/Session IP 48 | type: list(string) 49 | default: 50 | - 169.254.1.1/30 51 | - 169.254.1.5/30 52 | required: false 53 | - name: bgp_remote_session_range 54 | description: Please enter the remote environments BGP Session IP 55 | type: list(string) 56 | default: 57 | - 169.254.1.2 58 | - 169.254.1.6 59 | required: false 60 | - name: cr_enabled 61 | description: If there is a cloud router for BGP routing 62 | type: bool 63 | default: false 64 | required: false 65 | - name: cr_name 66 | description: The name of cloud router for BGP routing 67 | type: string 68 | default: "" 69 | required: false 70 | - name: gateway_name 71 | description: The name of VPN gateway 72 | type: string 73 | default: test-vpn 74 | required: false 75 | - name: ike_version 76 | description: Please enter the IKE version used by this tunnel (default is IKEv2) 77 | type: number 78 | default: 2 79 | required: false 80 | - name: local_traffic_selector 81 | description: | 82 | Local traffic selector to use when establishing the VPN tunnel with peer VPN gateway. 83 | Value should be list of CIDR formatted strings and ranges should be disjoint. 84 | type: list(string) 85 | default: 86 | - 0.0.0.0/0 87 | required: false 88 | - name: network 89 | description: The name of VPC being created 90 | type: string 91 | required: true 92 | - name: peer_asn 93 | description: Please enter the ASN of the BGP peer that cloud router will use 94 | type: list(string) 95 | default: 96 | - "65101" 97 | required: false 98 | - name: peer_ips 99 | description: IP address of remote-peer/gateway 100 | type: list(string) 101 | required: true 102 | - name: project_id 103 | description: The ID of the project where this VPC will be created 104 | type: string 105 | required: true 106 | - name: region 107 | description: The region in which you want to create the VPN gateway 108 | type: string 109 | required: true 110 | - name: remote_subnet 111 | description: remote subnet ip range in CIDR format - x.x.x.x/x 112 | type: list(string) 113 | default: [] 114 | required: false 115 | - name: remote_traffic_selector 116 | description: | 117 | Remote traffic selector to use when establishing the VPN tunnel with peer VPN gateway. 118 | Value should be list of CIDR formatted strings and ranges should be disjoint. 119 | type: list(string) 120 | default: 121 | - 0.0.0.0/0 122 | required: false 123 | - name: route_priority 124 | description: Priority for static route being created 125 | type: number 126 | default: 1000 127 | required: false 128 | - name: route_tags 129 | description: A list of instance tags to which this route applies. 130 | type: list(string) 131 | default: [] 132 | required: false 133 | - name: shared_secret 134 | description: Please enter the shared secret/pre-shared key 135 | type: string 136 | default: "" 137 | required: false 138 | - name: tunnel_count 139 | description: The number of tunnels from each VPN gw (default is 1) 140 | type: number 141 | default: 1 142 | required: false 143 | - name: tunnel_name_prefix 144 | description: The optional custom name of VPN tunnel being created 145 | type: string 146 | default: "" 147 | required: false 148 | - name: vpn_gw_ip 149 | description: Please enter the public IP address of the VPN Gateway, if you have already one. Do not set this variable to autocreate one 150 | type: string 151 | default: "" 152 | required: false 153 | outputs: 154 | - name: gateway_ip 155 | description: The VPN Gateway Public IP 156 | - name: gateway_self_link 157 | description: The self-link of the Gateway 158 | - name: ipsec_secret-dynamic 159 | description: The secret 160 | - name: ipsec_secret-static 161 | description: The secret 162 | - name: name 163 | description: The name of the Gateway 164 | - name: network 165 | description: The name of the VPC 166 | - name: project_id 167 | description: The Project-ID 168 | - name: vpn_tunnels_names-dynamic 169 | description: The VPN tunnel name is 170 | - name: vpn_tunnels_names-static 171 | description: The VPN tunnel name is 172 | - name: vpn_tunnels_self_link-dynamic 173 | description: The VPN tunnel self-link is 174 | - name: vpn_tunnels_self_link-static 175 | description: The VPN tunnel self-link is 176 | roles: 177 | - level: Project 178 | roles: 179 | - roles/owner 180 | - roles/compute.networkAdmin 181 | - roles/compute.instanceAdmin 182 | - roles/iam.serviceAccountUser 183 | services: 184 | - cloudresourcemanager.googleapis.com 185 | - compute.googleapis.com 186 | -------------------------------------------------------------------------------- /modules/vpn_ha/main.tf: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Copyright 2020 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | locals { 19 | router = ( 20 | var.router_name == "" 21 | ? google_compute_router.router[0].name 22 | : var.router_name 23 | ) 24 | peer_external_gateway = ( 25 | var.peer_external_gateway != null 26 | ? google_compute_external_vpn_gateway.external_gateway[0].self_link 27 | : null 28 | ) 29 | secret = random_id.secret.b64_url 30 | vpn_gateway_self_link = ( 31 | var.create_vpn_gateway 32 | ? google_compute_ha_vpn_gateway.ha_gateway[0].self_link 33 | : var.vpn_gateway_self_link 34 | ) 35 | } 36 | 37 | resource "google_compute_ha_vpn_gateway" "ha_gateway" { 38 | count = var.create_vpn_gateway == true ? 1 : 0 39 | name = var.name 40 | project = var.project_id 41 | region = var.region 42 | network = var.network 43 | stack_type = var.stack_type 44 | labels = var.labels 45 | dynamic "vpn_interfaces" { 46 | for_each = { for idx, val in var.interconnect_attachment : idx => val } 47 | content { 48 | id = vpn_interfaces.key 49 | interconnect_attachment = vpn_interfaces.value 50 | } 51 | } 52 | } 53 | 54 | resource "google_compute_external_vpn_gateway" "external_gateway" { 55 | count = var.peer_external_gateway != null ? 1 : 0 56 | name = var.peer_external_gateway.name != null ? var.peer_external_gateway.name : "external-${var.name}" 57 | project = var.project_id 58 | redundancy_type = var.peer_external_gateway.redundancy_type 59 | description = var.external_vpn_gateway_description 60 | labels = var.labels 61 | dynamic "interface" { 62 | for_each = var.peer_external_gateway.interfaces 63 | content { 64 | id = interface.value.id 65 | ip_address = interface.value.ip_address 66 | } 67 | } 68 | } 69 | 70 | resource "google_compute_router" "router" { 71 | count = var.router_name == "" ? 1 : 0 72 | name = "vpn-${var.name}" 73 | project = var.project_id 74 | region = var.region 75 | network = var.network 76 | bgp { 77 | advertise_mode = ( 78 | var.router_advertise_config == null 79 | ? null 80 | : var.router_advertise_config.mode 81 | ) 82 | advertised_groups = ( 83 | var.router_advertise_config == null ? null : ( 84 | var.router_advertise_config.mode != "CUSTOM" 85 | ? null 86 | : var.router_advertise_config.groups 87 | ) 88 | ) 89 | dynamic "advertised_ip_ranges" { 90 | for_each = ( 91 | var.router_advertise_config == null ? {} : ( 92 | var.router_advertise_config.mode != "CUSTOM" 93 | ? {} 94 | : var.router_advertise_config.ip_ranges 95 | ) 96 | ) 97 | iterator = range 98 | content { 99 | range = range.key 100 | description = range.value 101 | } 102 | } 103 | asn = var.router_asn 104 | keepalive_interval = var.keepalive_interval 105 | } 106 | } 107 | 108 | resource "google_compute_router_peer" "bgp_peer" { 109 | provider = google-beta 110 | for_each = var.tunnels 111 | region = var.region 112 | project = var.project_id 113 | name = each.value.bgp_session_name != null ? each.value.bgp_session_name : "${var.name}-${each.key}" 114 | router = local.router 115 | peer_ip_address = each.value.bgp_peer.address 116 | peer_asn = each.value.bgp_peer.asn 117 | ip_address = each.value.bgp_peer_options == null ? null : each.value.bgp_peer_options.ip_address 118 | advertised_route_priority = ( 119 | each.value.bgp_peer_options == null ? var.route_priority : ( 120 | each.value.bgp_peer_options.route_priority == null 121 | ? var.route_priority 122 | : each.value.bgp_peer_options.route_priority 123 | ) 124 | ) 125 | advertise_mode = ( 126 | each.value.bgp_peer_options == null ? null : each.value.bgp_peer_options.advertise_mode 127 | ) 128 | advertised_groups = ( 129 | each.value.bgp_peer_options == null ? null : ( 130 | each.value.bgp_peer_options.advertise_mode != "CUSTOM" 131 | ? null 132 | : each.value.bgp_peer_options.advertise_groups 133 | ) 134 | ) 135 | import_policies = ( 136 | each.value.bgp_peer_options == null ? null : each.value.bgp_peer_options.import_policies 137 | ) 138 | export_policies = ( 139 | each.value.bgp_peer_options == null ? null : each.value.bgp_peer_options.export_policies 140 | ) 141 | dynamic "advertised_ip_ranges" { 142 | for_each = ( 143 | each.value.bgp_peer_options == null ? {} : ( 144 | each.value.bgp_peer_options.advertise_mode != "CUSTOM" 145 | ? {} 146 | : each.value.bgp_peer_options.advertise_ip_ranges 147 | ) 148 | ) 149 | iterator = range 150 | content { 151 | range = range.key 152 | description = range.value 153 | } 154 | } 155 | interface = google_compute_router_interface.router_interface[each.key].name 156 | } 157 | 158 | resource "google_compute_router_interface" "router_interface" { 159 | for_each = var.tunnels 160 | project = var.project_id 161 | region = var.region 162 | name = each.value.bgp_session_name != null ? each.value.bgp_session_name : "${var.name}-${each.key}" 163 | router = local.router 164 | ip_range = each.value.bgp_session_range == "" ? null : each.value.bgp_session_range 165 | vpn_tunnel = google_compute_vpn_tunnel.tunnels[each.key].name 166 | } 167 | 168 | resource "google_compute_vpn_tunnel" "tunnels" { 169 | for_each = var.tunnels 170 | project = var.project_id 171 | region = var.region 172 | name = "${var.name}-${each.key}" 173 | router = local.router 174 | peer_external_gateway = each.value.peer_external_gateway_self_link != null ? each.value.peer_external_gateway_self_link : local.peer_external_gateway 175 | peer_external_gateway_interface = each.value.peer_external_gateway_interface 176 | peer_gcp_gateway = var.peer_gcp_gateway 177 | vpn_gateway_interface = each.value.vpn_gateway_interface 178 | ike_version = each.value.ike_version 179 | shared_secret = each.value.shared_secret == "" ? local.secret : each.value.shared_secret 180 | vpn_gateway = local.vpn_gateway_self_link 181 | labels = var.labels 182 | } 183 | 184 | resource "random_id" "secret" { 185 | byte_length = var.ipsec_secret_length 186 | } 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Google Cloud Platform - [VPN Module](https://registry.terraform.io/modules/terraform-google-modules/vpn/google) 2 | 3 | This modules makes it easy to set up VPN connectivity in GCP by defining your gateways and tunnels in a concise syntax. 4 | 5 | It supports creating: 6 | 7 | - A Google VPN Gateway 8 | - Tunnels connecting the gateway to defined peers 9 | - Static routes for subnets across tunnel -or- dynamic routes with cloud router 10 | 11 | If you want to deploy [HA VPN](https://cloud.google.com/vpn/docs/how-to/moving-to-ha-vpn) please refer to the [VPN HA Submodule](./modules/vpn_ha/) 12 | 13 | ## Compatibility 14 | 15 | This module is meant for use with Terraform 1.3+. If you haven't [upgraded](https://developer.hashicorp.com/terraform/language/v1.3.x/upgrade-guides) 16 | and need a Terraform 0.11.x-compatible version of this module, the last released version intended for 17 | Terraform 0.11.x is [0.3.0](https://registry.terraform.io/modules/terraform-google-modules/vpn/google/0.3.0). 18 | 19 | ## Upgrading 20 | 21 | The following guides are available to assist with upgrades: 22 | 23 | - [1.X -> 2.0](./docs/upgrading_to_vpn_v2.0.md) 24 | - [2.X -> 3.0](./docs/upgrading_to_vpn_v3.0.md) 25 | 26 | ## Usage 27 | 28 | You can go to the examples folder, however the usage of the module could be like this in your own main.tf file: 29 | 30 | ```hcl 31 | resource "google_compute_router" "cr-uscentral1-to-prod-vpc" { 32 | name = "cr-uscentral1-to-prod-vpc-tunnels" 33 | region = "us-central1" 34 | network = "default" 35 | project = var.project_id 36 | 37 | bgp { 38 | asn = "64519" 39 | } 40 | } 41 | 42 | module "vpn-prod-internal" { 43 | source = "terraform-google-modules/vpn/google" 44 | version = "~> 1.2.0" 45 | 46 | project_id = var.project_id 47 | network = "default" 48 | region = "us-west1" 49 | gateway_name = "vpn-prod-internal" 50 | tunnel_name_prefix = "vpn-tn-prod-internal" 51 | shared_secret = "secrets" 52 | tunnel_count = 1 53 | peer_ips = ["1.1.1.1", "2.2.2.2"] 54 | 55 | route_priority = 1000 56 | remote_subnet = ["10.17.0.0/22", "10.16.80.0/24"] 57 | } 58 | 59 | module "vpn-manage-internal" { 60 | source = "terraform-google-modules/vpn/google" 61 | version = "~> 1.2.0" 62 | project_id = var.project_id 63 | network = "default" 64 | region = "us-west1" 65 | gateway_name = "vpn-manage-internal" 66 | tunnel_name_prefix = "vpn-tn-manage-internal" 67 | shared_secret = "secrets" 68 | tunnel_count = 1 69 | peer_ips = ["1.1.1.1", "2.2.2.2"] 70 | 71 | route_priority = 1000 72 | remote_subnet = ["10.17.32.0/20", "10.17.16.0/20"] 73 | } 74 | ``` 75 | 76 | Then perform the following commands on the root folder: 77 | 78 | - `terraform init` to get the plugins 79 | - `terraform plan` to see the infrastructure plan 80 | - `terraform apply` to apply the infrastructure build 81 | - `terraform destroy` to destroy the built infrastructure 82 | 83 | ## Static vs Dynamic 84 | Depending on if the VPN tunnel(s) will be using dynamic or static routing, 85 | different variables will need to be used in the module. 86 | References the variable descriptions below to determine the right configuration. 87 | 88 | 89 | ## Inputs 90 | 91 | | Name | Description | Type | Default | Required | 92 | |------|-------------|------|---------|:--------:| 93 | | advertised\_route\_priority | Please enter the priority for the advertised route to BGP peer(default is 100) | `number` | `100` | no | 94 | | bgp\_cr\_session\_range | Please enter the cloud-router interface IP/Session IP | `list(string)` |
[
"169.254.1.1/30",
"169.254.1.5/30"
]
| no | 95 | | bgp\_remote\_session\_range | Please enter the remote environments BGP Session IP | `list(string)` |
[
"169.254.1.2",
"169.254.1.6"
]
| no | 96 | | cr\_enabled | If there is a cloud router for BGP routing | `bool` | `false` | no | 97 | | cr\_name | The name of cloud router for BGP routing | `string` | `""` | no | 98 | | gateway\_name | The name of VPN gateway | `string` | `"test-vpn"` | no | 99 | | ike\_version | Please enter the IKE version used by this tunnel (default is IKEv2) | `number` | `2` | no | 100 | | ipsec\_secret\_length | The lnegth the of shared secret for VPN tunnels | `number` | `8` | no | 101 | | local\_traffic\_selector | Local traffic selector to use when establishing the VPN tunnel with peer VPN gateway.
Value should be list of CIDR formatted strings and ranges should be disjoint. | `list(string)` |
[
"0.0.0.0/0"
]
| no | 102 | | network | The name of VPC being created | `string` | n/a | yes | 103 | | peer\_asn | Please enter the ASN of the BGP peer that cloud router will use | `list(string)` |
[
"65101"
]
| no | 104 | | peer\_ips | IP address of remote-peer/gateway | `list(string)` | n/a | yes | 105 | | project\_id | The ID of the project where this VPC will be created | `string` | n/a | yes | 106 | | region | The region in which you want to create the VPN gateway | `string` | n/a | yes | 107 | | remote\_subnet | remote subnet ip range in CIDR format - x.x.x.x/x | `list(string)` | `[]` | no | 108 | | remote\_traffic\_selector | Remote traffic selector to use when establishing the VPN tunnel with peer VPN gateway.
Value should be list of CIDR formatted strings and ranges should be disjoint. | `list(string)` |
[
"0.0.0.0/0"
]
| no | 109 | | route\_priority | Priority for static route being created | `number` | `1000` | no | 110 | | route\_tags | A list of instance tags to which this route applies. | `list(string)` | `[]` | no | 111 | | shared\_secret | Please enter the shared secret/pre-shared key | `string` | `""` | no | 112 | | tunnel\_count | The number of tunnels from each VPN gw (default is 1) | `number` | `1` | no | 113 | | tunnel\_name\_prefix | The optional custom name of VPN tunnel being created | `string` | `""` | no | 114 | | vpn\_gw\_ip | Please enter the public IP address of the VPN Gateway, if you have already one. Do not set this variable to autocreate one | `string` | `""` | no | 115 | 116 | ## Outputs 117 | 118 | | Name | Description | 119 | |------|-------------| 120 | | gateway\_ip | The VPN Gateway Public IP | 121 | | gateway\_self\_link | The self-link of the Gateway | 122 | | ipsec\_secret-dynamic | The secret | 123 | | ipsec\_secret-static | The secret | 124 | | name | The name of the Gateway | 125 | | network | The name of the VPC | 126 | | project\_id | The Project-ID | 127 | | vpn\_tunnels\_names-dynamic | The VPN tunnel name is | 128 | | vpn\_tunnels\_names-static | The VPN tunnel name is | 129 | | vpn\_tunnels\_self\_link-dynamic | The VPN tunnel self-link is | 130 | | vpn\_tunnels\_self\_link-static | The VPN tunnel self-link is | 131 | 132 | 133 | 134 | ## Requirements 135 | ### Terraform plugins 136 | - [Terraform](https://www.terraform.io/downloads.html) 1.3+ 137 | - [terraform-provider-google](https://github.com/terraform-providers/terraform-provider-google) plugin v4.64+ 138 | 139 | ### Configure a Service Account 140 | In order to execute this module you must have a Service Account with the following roles: 141 | - roles/compute.networkAdmin on the organization 142 | 143 | ### Enable API's 144 | In order to operate with the Service Account you must activate the following API on the project where the Service Account was created: 145 | - Compute Engine API - compute.googleapis.com 146 | 147 | ## Development 148 | ### File structure 149 | The project has the following folders and files: 150 | 151 | - /: root folder 152 | - /examples: examples for using this module 153 | - /main.tf: main file for this module, contains the routing resources 154 | - /gateway.tf: contains the gateway resources 155 | - /tunnel.tf: contains the tunnel resources 156 | - /forwarding-rule.tf: contains the forwarding rules 157 | - /variables.tf: all the variables for the module 158 | - /output.tf: the outputs of the module 159 | - /modules/vpn_ha/: vpn ha submodule 160 | - /README.md: this file 161 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 4 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 5 | 6 | ## [6.1.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v6.0.0...v6.1.0) (2025-09-04) 7 | 8 | 9 | ### Features 10 | 11 | * **deps:** Update Terraform Google Provider to v7 (major) ([#194](https://github.com/terraform-google-modules/terraform-google-vpn/issues/194)) ([a9a5b30](https://github.com/terraform-google-modules/terraform-google-vpn/commit/a9a5b30c0a12ee9e03a25d8992d1711d0fff32cd)) 12 | 13 | ## [6.0.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v5.0.0...v6.0.0) (2025-06-04) 14 | 15 | 16 | ### ⚠ BREAKING CHANGES 17 | 18 | * **TPG beta:** add support for BGP Route Policy in vpn_ha sub-module ([#188](https://github.com/terraform-google-modules/terraform-google-vpn/issues/188)) 19 | 20 | ### Features 21 | 22 | * **TPG beta:** add support for BGP Route Policy in vpn_ha sub-module ([#188](https://github.com/terraform-google-modules/terraform-google-vpn/issues/188)) ([8c44816](https://github.com/terraform-google-modules/terraform-google-vpn/commit/8c4481669153dd8e16f688742d16293218a32c49)) 23 | 24 | ## [5.0.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v4.2.0...v5.0.0) (2025-03-05) 25 | 26 | 27 | ### ⚠ BREAKING CHANGES 28 | 29 | * **TPG>= 6.21:** Add lables to google_compute_ha_vpn_gateway ([#176](https://github.com/terraform-google-modules/terraform-google-vpn/issues/176)) 30 | 31 | ### Features 32 | 33 | * add support for HA VPN over interconnect ([#178](https://github.com/terraform-google-modules/terraform-google-vpn/issues/178)) ([0d5d7f0](https://github.com/terraform-google-modules/terraform-google-vpn/commit/0d5d7f0f7f680a3b27189142f30bda6bddd8a6e6)) 34 | * **TPG>= 6.21:** Add lables to google_compute_ha_vpn_gateway ([#176](https://github.com/terraform-google-modules/terraform-google-vpn/issues/176)) ([f9d73d9](https://github.com/terraform-google-modules/terraform-google-vpn/commit/f9d73d90b012b18d8b00827e5da871f1194a7163)) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * Update versions.tf min 1.3 ([#179](https://github.com/terraform-google-modules/terraform-google-vpn/issues/179)) ([f38c80e](https://github.com/terraform-google-modules/terraform-google-vpn/commit/f38c80e7ae226296f0d9032ebee33efe3ea41f20)) 40 | 41 | ## [4.2.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v4.1.0...v4.2.0) (2024-11-12) 42 | 43 | 44 | ### Features 45 | 46 | * Making IPSEC PSK length configurable ([#171](https://github.com/terraform-google-modules/terraform-google-vpn/issues/171)) ([0621d9c](https://github.com/terraform-google-modules/terraform-google-vpn/commit/0621d9c87bfd53680bebaa4d9863a735c2f99e26)) 47 | 48 | ## [4.1.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v4.0.1...v4.1.0) (2024-09-11) 49 | 50 | 51 | ### Features 52 | 53 | * **deps:** Update Terraform Google Provider to v6 (major) ([#166](https://github.com/terraform-google-modules/terraform-google-vpn/issues/166)) ([badb0d5](https://github.com/terraform-google-modules/terraform-google-vpn/commit/badb0d593a6d982806a3107581e309fc4a2936dc)) 54 | 55 | ## [4.0.1](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v4.0.0...v4.0.1) (2024-07-25) 56 | 57 | 58 | ### Bug Fixes 59 | 60 | * mark secret outputs sensitive for classic vpn Ref: [#158](https://github.com/terraform-google-modules/terraform-google-vpn/issues/158) ([#159](https://github.com/terraform-google-modules/terraform-google-vpn/issues/159)) ([c3c7812](https://github.com/terraform-google-modules/terraform-google-vpn/commit/c3c78122c572017e34231c813d56eb45534ddfd3)) 61 | 62 | ## [4.0.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v3.1.1...v4.0.0) (2023-11-21) 63 | 64 | 65 | ### ⚠ BREAKING CHANGES 66 | 67 | * migrate to GA Terraform Provider ([#134](https://github.com/terraform-google-modules/terraform-google-vpn/issues/134)) 68 | 69 | ### Bug Fixes 70 | 71 | * migrate to GA Terraform Provider ([#134](https://github.com/terraform-google-modules/terraform-google-vpn/issues/134)) ([b289d32](https://github.com/terraform-google-modules/terraform-google-vpn/commit/b289d32ceea6c03d653fa28fd352791bbbd464dc)) 72 | 73 | ## [3.1.1](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v3.1.0...v3.1.1) (2023-10-31) 74 | 75 | 76 | ### Bug Fixes 77 | 78 | * upgraded versions.tf to include minor bumps from tpg v5 ([#125](https://github.com/terraform-google-modules/terraform-google-vpn/issues/125)) ([72bb554](https://github.com/terraform-google-modules/terraform-google-vpn/commit/72bb5545228ec9643ba4428af599f9cdcffb8665)) 79 | 80 | ## [3.1.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v3.0.1...v3.1.0) (2023-09-11) 81 | 82 | 83 | ### Features 84 | 85 | * support multiple external VPN peering gateways ([#119](https://github.com/terraform-google-modules/terraform-google-vpn/issues/119)) ([c51aee7](https://github.com/terraform-google-modules/terraform-google-vpn/commit/c51aee7a43c520a7fdf11ec8023806c5bc6fbd30)) 86 | 87 | ## [3.0.1](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v3.0.0...v3.0.1) (2023-08-17) 88 | 89 | 90 | ### Bug Fixes 91 | 92 | * updated docs and variable description ([#117](https://github.com/terraform-google-modules/terraform-google-vpn/issues/117)) ([a6b543d](https://github.com/terraform-google-modules/terraform-google-vpn/commit/a6b543dea5d893d2549c46e76cfb51dd9750063b)) 93 | 94 | ## [3.0.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v2.4.0...v3.0.0) (2023-07-25) 95 | 96 | 97 | ### ⚠ BREAKING CHANGES 98 | 99 | * **TPG >= 4.74:** Added labels, update TPG and Terraform version requirements ([#112](https://github.com/terraform-google-modules/terraform-google-vpn/issues/112)) 100 | 101 | ### Features 102 | 103 | * adds stack_type and an option to set the router name ([#110](https://github.com/terraform-google-modules/terraform-google-vpn/issues/110)) ([2382abd](https://github.com/terraform-google-modules/terraform-google-vpn/commit/2382abda421bafab111b13b83428c4e955f83dc1)) 104 | * **TPG >= 4.74:** Added labels, update TPG and Terraform version requirements ([#112](https://github.com/terraform-google-modules/terraform-google-vpn/issues/112)) ([24a946c](https://github.com/terraform-google-modules/terraform-google-vpn/commit/24a946cf5d6cce4cc5c1398cc47f1e4d8dcf2de9)) 105 | 106 | ## [2.4.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v2.3.1...v2.4.0) (2023-07-12) 107 | 108 | 109 | ### Features 110 | 111 | * Add ip_address to bgp_peer_options in vpn_ha ([#100](https://github.com/terraform-google-modules/terraform-google-vpn/issues/100)) ([ca72e53](https://github.com/terraform-google-modules/terraform-google-vpn/commit/ca72e53e76336c53a2944a4ad1938225207483f2)) 112 | * adds variables required for FS ([#106](https://github.com/terraform-google-modules/terraform-google-vpn/issues/106)) ([442b40d](https://github.com/terraform-google-modules/terraform-google-vpn/commit/442b40dea068f1f9fe649ab5067df75a223cdd3e)) 113 | 114 | ## [2.3.1](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v2.3.0...v2.3.1) (2022-12-29) 115 | 116 | 117 | ### Bug Fixes 118 | 119 | * fixes lint issues and generates metadata ([#93](https://github.com/terraform-google-modules/terraform-google-vpn/issues/93)) ([0e3e19c](https://github.com/terraform-google-modules/terraform-google-vpn/commit/0e3e19c09971660a2905237bf58a294198a41a83)) 120 | 121 | ## [2.3.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v2.2.0...v2.3.0) (2022-06-11) 122 | 123 | 124 | ### Features 125 | 126 | * Add labels to VPN tunnel ([#76](https://github.com/terraform-google-modules/terraform-google-vpn/issues/76)) ([c2e563b](https://github.com/terraform-google-modules/terraform-google-vpn/commit/c2e563b4d5cf6b907898fd56f287fcbbb72274b5)) 127 | 128 | 129 | ### Bug Fixes 130 | 131 | * remove Classic VPN tunnels dynamic example ([#82](https://github.com/terraform-google-modules/terraform-google-vpn/issues/82)) ([2ab8e68](https://github.com/terraform-google-modules/terraform-google-vpn/commit/2ab8e68a0b8cc2508bfcab3aa9516ac2cbc9ed64)) 132 | 133 | ## [2.2.0](https://github.com/terraform-google-modules/terraform-google-vpn/compare/v2.1.0...v2.2.0) (2022-01-18) 134 | 135 | 136 | ### Features 137 | 138 | * update TPG version constraints to allow 4.0 ([#66](https://github.com/terraform-google-modules/terraform-google-vpn/issues/66)) ([a9bd3a7](https://github.com/terraform-google-modules/terraform-google-vpn/commit/a9bd3a70635e0229119618c8872e200369b8d6e2)) 139 | 140 | 141 | ### Bug Fixes 142 | 143 | * for_each can not receive null vpn_ha ([#67](https://github.com/terraform-google-modules/terraform-google-vpn/issues/67)) ([50120ec](https://github.com/terraform-google-modules/terraform-google-vpn/commit/50120ec35c0961d6cb79b2e640a7d154ebc341c5)) 144 | 145 | ## [2.1.0](https://www.github.com/terraform-google-modules/terraform-google-vpn/compare/v2.0.0...v2.1.0) (2021-09-23) 146 | 147 | 148 | ### Features 149 | 150 | * added variable route_tags ([#61](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/61)) ([b85d3fa](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/b85d3fa02dcdb3b7c26254673301e7065b2af927)) 151 | 152 | ## [2.0.0](https://www.github.com/terraform-google-modules/terraform-google-vpn/compare/v1.5.0...v2.0.0) (2021-08-26) 153 | 154 | 155 | ### ⚠ BREAKING CHANGES 156 | 157 | * The BGP session name now includes the tunnel name. This may cause recreation of the VPN tunnel. 158 | 159 | ### Bug Fixes 160 | 161 | * Prefix BGP session name with tunnel name ([#58](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/58)) ([f8d08fd](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/f8d08fd34c34a9d6e01e510d9888616010e606de)), closes [#54](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/54) 162 | 163 | ## [1.5.0](https://www.github.com/terraform-google-modules/terraform-google-vpn/compare/v1.4.1...v1.5.0) (2021-02-03) 164 | 165 | 166 | ### Features 167 | 168 | * Add option to use an existing vpn_gateway ([#48](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/48)) ([712720a](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/712720a231bdb14b8ad5e310a5ff55284d27762e)) 169 | 170 | 171 | ### Bug Fixes 172 | 173 | * Mark certain output values as sensitive for TF 0.14 ([#51](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/51)) ([2e55b02](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/2e55b029f73de94ea5ad6e0d44a53a4897074652)) 174 | 175 | ### [1.4.1](https://www.github.com/terraform-google-modules/terraform-google-vpn/compare/v1.4.0...v1.4.1) (2020-08-28) 176 | 177 | 178 | ### Bug Fixes 179 | 180 | * Fix numeric indexes for tunnels and subnets ([#43](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/43)) ([a78f08d](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/a78f08d598259b067452c0b6ef6806c0aceb26d5)) 181 | 182 | ## [1.4.0](https://www.github.com/terraform-google-modules/terraform-google-vpn/compare/v1.3.1...v1.4.0) (2020-05-28) 183 | 184 | 185 | ### Features 186 | 187 | * enable usage of a already created public IP address([#40](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/40)) ([537d81e](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/537d81ee10a1e7b142cf5a1f84e9d1c31b22a9dd)) 188 | 189 | ### [1.3.1](https://www.github.com/terraform-google-modules/terraform-google-vpn/compare/v1.3.0...v1.3.1) (2020-03-04) 190 | 191 | 192 | ### Bug Fixes 193 | 194 | * Add the project argument to external_gateway ([#33](https://www.github.com/terraform-google-modules/terraform-google-vpn/issues/33)) ([a901ab7](https://www.github.com/terraform-google-modules/terraform-google-vpn/commit/a901ab7e89aed7dffddbcd90920918fac33a71be)) 195 | 196 | ## [1.3.0] - 2020-03-03 197 | 198 | ### Features 199 | - Added support for HA VPN through a [submodule](./modules/vpn_ha). [#32](https://github.com/terraform-google-modules/terraform-google-vpn/pull/32) 200 | 201 | ## [1.2.0] - 2019-11-20 202 | 203 | ### Added 204 | - Added support for dynamic router [#16] 205 | 206 | ## [1.1.0] - 2019-08-21 207 | 208 | ### Change 209 | 210 | - Added self-links of the tunnels and gateway to output [#17] 211 | 212 | ## [1.0.0] - 2019-07-26 213 | 214 | ### Change 215 | 216 | - Upgraded for usage with terraform-0.12.x [#12] 217 | 218 | ## [0.3.0] - 2019-01-22 219 | 220 | ### Changed 221 | 222 | - Made `local_traffic_selector` and `remote_traffic_selector` configurable. 223 | - Update examples to use registry with versions 224 | - Reorganize README 225 | 226 | ## [0.2.0] - 2019-01-17 227 | 228 | ### Changed 229 | 230 | - Made `ike_version` configurable. #2 231 | 232 | ## [0.1.0] - 2019-01-17 233 | 234 | ### Added 235 | 236 | - Initial module release. 237 | 238 | [1.3.0]: https://github.com/terraform-google-modules/terraform-google-vpn/compare/v1.2.0...v1.3.0 239 | [1.2.0]: https://github.com/terraform-google-modules/terraform-google-vpn/compare/v1.1.0...v1.2.0 240 | [1.1.0]: https://github.com/terraform-google-modules/terraform-google-vpn/compare/v1.0.0...v1.1.0 241 | [1.0.0]: https://github.com/terraform-google-modules/terraform-google-vpn/compare/v0.3.0...v1.0.0 242 | [0.3.0]: https://github.com/terraform-google-modules/terraform-google-vpn/compare/v0.2.0...v0.3.0 243 | [0.2.0]: https://github.com/terraform-google-modules/terraform-google-vpn/compare/v0.1.0...v0.2.0 244 | [0.1.0]: https://github.com/terraform-google-modules/terraform-google-vpn/releases/tag/v0.1.0 245 | 246 | [#12]: https://github.com/terraform-google-modules/terraform-google-vpn/pull/12 247 | [#16]: https://github.com/terraform-google-modules/terraform-google-vpn/pull/16/ 248 | [#17]: https://github.com/terraform-google-modules/terraform-google-vpn/pull/17 249 | -------------------------------------------------------------------------------- /test/integration/go.sum: -------------------------------------------------------------------------------- 1 | github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9 h1:R7TF5kSOr+6fu9CFCdza5DIFLCQYGrQP923G7SaHd2Y= 2 | github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9/go.mod h1:KfuvXj6g70rv3AI3D0+4aq9Icf/Axu156s6h1JeDJt4= 3 | github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= 4 | github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 5 | github.com/alexflint/go-filemutex v1.3.0 h1:LgE+nTUWnQCyRKbpoceKZsPQbs84LivvgwUymZXdOcM= 6 | github.com/alexflint/go-filemutex v1.3.0/go.mod h1:U0+VA/i30mGBlLCrFPGtTe9y6wGQfNAWPBTekHQ+c8A= 7 | github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= 8 | github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= 9 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= 10 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= 11 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 12 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 13 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 14 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 15 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 16 | github.com/go-errors/errors v1.5.0 h1:/EuijeGOu7ckFxzhkj4CXJ8JaenxK7bKUxpPYqeLHqQ= 17 | github.com/go-errors/errors v1.5.0/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= 18 | github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= 19 | github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= 20 | github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= 21 | github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= 22 | github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= 23 | github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 24 | github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= 25 | github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= 26 | github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= 27 | github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= 28 | github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= 29 | github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= 30 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 31 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 32 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 33 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 34 | github.com/gruntwork-io/terratest v0.50.0 h1:AbBJ7IRCpLZ9H4HBrjeoWESITv8nLjN6/f1riMNcAsw= 35 | github.com/gruntwork-io/terratest v0.50.0/go.mod h1:see0lbKvAqz6rvzvN2wyfuFQQG4PWcAb2yHulF6B2q4= 36 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 37 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 38 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 39 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 40 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 41 | github.com/hashicorp/go-getter/v2 v2.2.3 h1:6CVzhT0KJQHqd9b0pK3xSP0CM/Cv+bVhk+jcaRJ2pGk= 42 | github.com/hashicorp/go-getter/v2 v2.2.3/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY= 43 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 44 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 45 | github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= 46 | github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= 47 | github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= 48 | github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 49 | github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+DbLISwf2B8WXEolNRA8BGCwI9jws= 50 | github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= 51 | github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= 52 | github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= 53 | github.com/hashicorp/terraform-config-inspect v0.0.0-20250731202709-e8a84eebd3e7 h1:NIwoxkIKF4OAbTze/gukXLJqS9MISRXCqn4SnurhZ1I= 54 | github.com/hashicorp/terraform-config-inspect v0.0.0-20250731202709-e8a84eebd3e7/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI= 55 | github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4= 56 | github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= 57 | github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= 58 | github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= 59 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 60 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 61 | github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= 62 | github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 63 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 64 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 65 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 66 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 67 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 68 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 69 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 70 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 71 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 72 | github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= 73 | github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= 74 | github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= 75 | github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= 76 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 77 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 78 | github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 h1:drhDO54gdT/a15GBcMRmunZiNcLgPiFIJa23KzmcvcU= 79 | github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770/go.mod h1:SO/iHr6q2EzbqRApt+8/E9wqebTwQn5y+UlB04bxzo0= 80 | github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= 81 | github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= 82 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 83 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 84 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 85 | github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 86 | github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 87 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 88 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 89 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 90 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 91 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 92 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 93 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 94 | github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 95 | github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 96 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 97 | github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= 98 | github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 99 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 100 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 101 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 102 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 103 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 104 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 105 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 106 | github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw= 107 | github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk= 108 | github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= 109 | github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= 110 | github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= 111 | github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= 112 | github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= 113 | github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= 114 | go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= 115 | go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= 116 | go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= 117 | go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= 118 | golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= 119 | golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= 120 | golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= 121 | golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= 122 | golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= 123 | golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= 124 | golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= 125 | golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 126 | golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 127 | golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= 128 | golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 129 | golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= 130 | golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= 131 | golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= 132 | golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= 133 | golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= 134 | golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= 135 | google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= 136 | google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 137 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 138 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 139 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 140 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 141 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 142 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 143 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 144 | k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= 145 | k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= 146 | sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= 147 | sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= 148 | sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= 149 | sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= 150 | sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= 151 | sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= 152 | -------------------------------------------------------------------------------- /modules/vpn_ha/README.md: -------------------------------------------------------------------------------- 1 | # Cloud VPN HA Module 2 | This module makes it easy to deploy either GCP-to-GCP or GCP-to-On-prem [Cloud HA VPN](https://cloud.google.com/vpn/docs/concepts/overview#ha-vpn). 3 | 4 | ## Compatibility 5 | 6 | This module is meant for use with Terraform 1.3+ and tested using Terraform 1.3+. If you find incompatibilities using Terraform >=1.3, please open an issue. 7 | 8 | ## Version 9 | 10 | Current version is 1.0. Upgrade guides: 11 | 12 | - [1.X -> 2.0.](/docs/upgrading_to_vpn_v2.0.md) 13 | - [2.X -> 3.0.](/docs/upgrading_to_vpn_v3.0.md) 14 | - [3.X -> 4.0.](/docs/upgrading_to_vpn_v4.0.md) 15 | 16 | ## Module Format 17 | 18 | ``` 19 | module "vpn_ha" { 20 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 21 | version = "~> 4.0" 22 | project_id = 23 | region = "us-central1" 24 | network = 25 | name = "my-ha-vpn-gateway" 26 | 27 | create_vpn_gateway = true 28 | vpn_gateway_self_link = null 29 | 30 | router_name = "my-vpn-router" 31 | router_asn = 64514 32 | 33 | external_vpn_gateway_description = "My VPN peering gateway" 34 | peer_external_gateway = {} 35 | tunnels = { 36 | 37 | tunel-0 = { 38 | 39 | } 40 | 41 | tunel-1 = { 42 | 43 | } 44 | 45 | } 46 | } 47 | ``` 48 | 49 | See section [peer_external_gateway](#peer_external_gateway) and [tunnels](#tunnels) for details. 50 | 51 | ## Usage 52 | 53 | ### GCP to GCP 54 | ```hcl 55 | module "vpn_ha-1" { 56 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 57 | version = "~> 4.0" 58 | project_id = "" 59 | region = "europe-west4" 60 | network = "https://www.googleapis.com/compute/v1/projects//global/networks/network-1" 61 | name = "net1-to-net-2" 62 | peer_gcp_gateway = module.vpn_ha-2.self_link 63 | router_asn = 64514 64 | 65 | tunnels = { 66 | remote-0 = { 67 | bgp_peer = { 68 | address = "169.254.1.1" 69 | asn = 64513 70 | } 71 | bgp_peer_options = null 72 | bgp_session_range = "169.254.1.2/30" 73 | ike_version = 2 74 | vpn_gateway_interface = 0 75 | peer_external_gateway_interface = null 76 | shared_secret = "" 77 | } 78 | 79 | remote-1 = { 80 | bgp_peer = { 81 | address = "169.254.2.1" 82 | asn = 64513 83 | } 84 | bgp_peer_options = null 85 | bgp_session_range = "169.254.2.2/30" 86 | ike_version = 2 87 | vpn_gateway_interface = 1 88 | peer_external_gateway_interface = null 89 | shared_secret = "" 90 | } 91 | 92 | } 93 | } 94 | 95 | module "vpn_ha-2" { 96 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 97 | version = "~> 4.0" 98 | project_id = "" 99 | region = "europe-west4" 100 | network = "https://www.googleapis.com/compute/v1/projects//global/networks/local-network" 101 | name = "net2-to-net1" 102 | router_asn = 64513 103 | peer_gcp_gateway = module.vpn_ha-1.self_link 104 | 105 | tunnels = { 106 | remote-0 = { 107 | bgp_peer = { 108 | address = "169.254.1.2" 109 | asn = 64514 110 | } 111 | bgp_session_range = "169.254.1.1/30" 112 | ike_version = 2 113 | vpn_gateway_interface = 0 114 | shared_secret = module.vpn_ha-1.random_secret 115 | } 116 | 117 | remote-1 = { 118 | bgp_peer = { 119 | address = "169.254.2.2" 120 | asn = 64514 121 | } 122 | bgp_session_range = "169.254.2.1/30" 123 | ike_version = 2 124 | vpn_gateway_interface = 1 125 | shared_secret = module.vpn_ha-1.random_secret 126 | } 127 | 128 | } 129 | } 130 | ``` 131 | ### GCP to on-prem 132 | 133 | ```hcl 134 | module "vpn_ha" { 135 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 136 | version = "~> 4.0" 137 | project_id = "" 138 | region = "europe-west4" 139 | network = "https://www.googleapis.com/compute/v1/projects//global/networks/my-network" 140 | name = "mynet-to-onprem" 141 | create_vpn_gateway = true 142 | vpn_gateway_self_link = null 143 | external_vpn_gateway_description = "My VPN peering gateway" 144 | router_name = "my-vpn-router" 145 | router_asn = 64515 146 | 147 | peer_external_gateway = { 148 | name = "vpn-peering-gw" 149 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" 150 | interfaces = [ 151 | { 152 | id = 0 153 | ip_address = "8.8.8.8" # on-prem router ip address 154 | }, 155 | ] 156 | } 157 | 158 | tunnels = { 159 | 160 | remote-0 = { 161 | bgp_peer = { 162 | address = "169.254.1.1" 163 | asn = 64513 164 | } 165 | bgp_session_name = "bgp-peer-0" 166 | bgp_session_range = "169.254.1.2/30" 167 | ike_version = 2 168 | peer_external_gateway_interface = 0 169 | vpn_gateway_interface = 0 170 | shared_secret = "mySecret" 171 | } 172 | 173 | remote-1 = { 174 | bgp_peer = { 175 | address = "169.254.2.1" 176 | asn = 64513 177 | } 178 | bgp_session_name = "bgp-peer-1" 179 | bgp_session_range = "169.254.2.2/30" 180 | ike_version = 2 181 | peer_external_gateway_interface = 0 182 | vpn_gateway_interface = 1 183 | shared_secret = "mySecret" 184 | } 185 | 186 | } 187 | } 188 | ``` 189 | 190 | ### GCP to on-prem using multiple external VPN gateways 191 | 192 | ```hcl 193 | 194 | resource "google_compute_external_vpn_gateway" "external_gateway1" { 195 | name = "vpn-peering-gw1" 196 | project = "" 197 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" 198 | description = "My VPN peering gateway1" 199 | 200 | interface { 201 | id = 0 202 | ip_address = "8.8.8.8" 203 | } 204 | } 205 | 206 | resource "google_compute_external_vpn_gateway" "external_gateway2" { 207 | name = "vpn-peering-gw2" 208 | project = "" 209 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" 210 | description = "My VPN peering gateway2" 211 | 212 | interface { 213 | id = 0 214 | ip_address = "8.8.4.4" 215 | } 216 | } 217 | 218 | module "vpn_ha" { 219 | source = "terraform-google-modules/vpn/google//modules/vpn_ha" 220 | version = "~> 4.0" 221 | project_id = "" 222 | region = "europe-west4" 223 | network = "https://www.googleapis.com/compute/v1/projects//global/networks/my-network" 224 | name = "mynet-to-onprem" 225 | create_vpn_gateway = true 226 | vpn_gateway_self_link = null 227 | router_name = "my-vpn-router" 228 | router_asn = 64515 229 | 230 | tunnels = { 231 | 232 | remote-0 = { 233 | bgp_peer = { 234 | address = "169.254.1.1" 235 | asn = 64513 236 | } 237 | bgp_session_name = "bgp-peer-0" 238 | bgp_session_range = "169.254.1.2/30" 239 | ike_version = 2 240 | peer_external_gateway_self_link = google_compute_external_vpn_gateway.external_gateway1.self_link # set a resource link 241 | peer_external_gateway_interface = 0 242 | vpn_gateway_interface = 0 243 | shared_secret = "mySecret" 244 | } 245 | 246 | remote-1 = { 247 | bgp_peer = { 248 | address = "169.254.2.1" 249 | asn = 64513 250 | } 251 | bgp_session_name = "bgp-peer-1" 252 | bgp_session_range = "169.254.2.2/30" 253 | ike_version = 2 254 | peer_external_gateway_self_link = google_compute_external_vpn_gateway.external_gateway2.self_link # set a resource link 255 | peer_external_gateway_interface = 0 256 | vpn_gateway_interface = 1 257 | shared_secret = "mySecret" 258 | } 259 | 260 | } 261 | } 262 | ``` 263 | 264 | 265 | ## Inputs 266 | 267 | | Name | Description | Type | Default | Required | 268 | |------|-------------|------|---------|:--------:| 269 | | create\_vpn\_gateway | create a VPN gateway | `bool` | `true` | no | 270 | | external\_vpn\_gateway\_description | An optional description of external VPN Gateway | `string` | `"Terraform managed external VPN gateway"` | no | 271 | | interconnect\_attachment | URL of the interconnect attachment resource. When the value of this field is present, the VPN Gateway will be used for IPsec-encrypted Cloud Interconnect. | `list(string)` | `[]` | no | 272 | | ipsec\_secret\_length | The lnegth the of shared secret for VPN tunnels | `number` | `8` | no | 273 | | keepalive\_interval | The interval in seconds between BGP keepalive messages that are sent to the peer. | `number` | `20` | no | 274 | | labels | Labels for vpn components | `map(string)` | `{}` | no | 275 | | name | VPN gateway name, and prefix used for dependent resources. | `string` | n/a | yes | 276 | | network | VPC used for the gateway and routes. | `string` | n/a | yes | 277 | | peer\_external\_gateway | Configuration of an external VPN gateway to which this VPN is connected. |
object({
name = optional(string)
redundancy_type = optional(string)
interfaces = list(object({
id = number
ip_address = string
}))
})
| `null` | no | 278 | | peer\_gcp\_gateway | Self Link URL of the peer side HA GCP VPN gateway to which this VPN tunnel is connected. | `string` | `null` | no | 279 | | project\_id | Project where resources will be created. | `string` | n/a | yes | 280 | | region | Region used for resources. | `string` | n/a | yes | 281 | | route\_priority | Route priority, defaults to 1000. | `number` | `1000` | no | 282 | | router\_advertise\_config | Router custom advertisement configuration, ip\_ranges is a map of address ranges and descriptions. |
object({
groups = list(string)
ip_ranges = map(string)
mode = optional(string)
})
| `null` | no | 283 | | router\_asn | Router ASN used for auto-created router. | `number` | `64514` | no | 284 | | router\_name | Name of router, leave blank to create one. | `string` | `""` | no | 285 | | stack\_type | The IP stack type will apply to all the tunnels associated with this VPN gateway. | `string` | `"IPV4_ONLY"` | no | 286 | | tunnels | VPN tunnel configurations, bgp\_peer\_options is usually null. |
map(object({
bgp_peer = object({
address = string
asn = number
})
bgp_session_name = optional(string)
bgp_peer_options = optional(object({
ip_address = optional(string)
advertise_groups = optional(list(string))
advertise_ip_ranges = optional(map(string))
advertise_mode = optional(string)
route_priority = optional(number)
import_policies = optional(list(string))
export_policies = optional(list(string))
}))
bgp_session_range = optional(string)
ike_version = optional(number)
vpn_gateway_interface = optional(number)
peer_external_gateway_self_link = optional(string, null)
peer_external_gateway_interface = optional(number)
shared_secret = optional(string, "")
}))
| `{}` | no | 287 | | vpn\_gateway\_self\_link | self\_link of existing VPN gateway to be used for the vpn tunnel. create\_vpn\_gateway should be set to false | `string` | `null` | no | 288 | 289 | ## Outputs 290 | 291 | | Name | Description | 292 | |------|-------------| 293 | | external\_gateway | External VPN gateway resource. | 294 | | gateway | HA VPN gateway resource. | 295 | | name | VPN gateway name. | 296 | | random\_secret | Generated secret. | 297 | | router | Router resource (only if auto-created). | 298 | | router\_name | Router name. | 299 | | self\_link | HA VPN gateway self link. | 300 | | tunnel\_names | VPN tunnel names. | 301 | | tunnel\_self\_links | VPN tunnel self links. | 302 | | tunnels | VPN tunnel resources. | 303 | 304 | 305 | 306 | ## peer_external_gateway 307 | 308 | # Format 309 | 310 | ``` 311 | peer_external_gateway = { 312 | name = "vpn-peering-gw" 313 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" # can be SINGLE_IP_INTERNALLY_REDUNDANT, TWO_IPS_REDUNDANCY or FOUR_IPS_REDUNDANCY 314 | interfaces = [] 315 | } 316 | ``` 317 | 318 | # Examples 319 | 320 | - Single Interfaces 321 | 322 | ``` 323 | peer_external_gateway = { 324 | name = "vpn-peering-gw" 325 | redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" # can be SINGLE_IP_INTERNALLY_REDUNDANT, TWO_IPS_REDUNDANCY or FOUR_IPS_REDUNDANCY 326 | interfaces = [ 327 | { 328 | id = 0 329 | ip_address = "130.100.0.10" 330 | }, 331 | ] 332 | } 333 | ``` 334 | 335 | - Two Interfaces 336 | 337 | ``` 338 | peer_external_gateway = { 339 | name = "vpn-peering-gw" 340 | redundancy_type = "TWO_IPS_REDUNDANCY" # can be SINGLE_IP_INTERNALLY_REDUNDANT, TWO_IPS_REDUNDANCY or FOUR_IPS_REDUNDANCY 341 | interfaces = [ 342 | { 343 | id = 0 344 | ip_address = "130.100.0.10" 345 | }, 346 | { 347 | id = 1 348 | ip_address = "130.100.0.20" 349 | }, 350 | ] 351 | } 352 | 353 | ``` 354 | 355 | 356 | - Four Interfaces 357 | 358 | ``` 359 | peer_external_gateway = { 360 | name = "vpn-peering-gw" 361 | redundancy_type = "FOUR_IPS_REDUNDANCY" # can be SINGLE_IP_INTERNALLY_REDUNDANT, TWO_IPS_REDUNDANCY or FOUR_IPS_REDUNDANCY 362 | interfaces = [ 363 | { 364 | id = 0 365 | ip_address = "130.100.0.10" 366 | }, 367 | { 368 | id = 1 369 | ip_address = "130.100.0.20" 370 | }, 371 | { 372 | id = 2 373 | ip_address = "130.100.0.100" 374 | }, 375 | { 376 | id = 3 377 | ip_address = "130.100.0.120" 378 | }, 379 | ] 380 | } 381 | 382 | ``` 383 | 384 | 385 | 386 | ## tunnels 387 | 388 | # Format 389 | 390 | ``` 391 | tunnels = { 392 | remote-0 = { 393 | 394 | bgp_peer = { 395 | address = "169.254.20.2" # Peer Router BGP IP address "169.254.20.2" 396 | asn = 31898 # Peer Router ASN 397 | } 398 | 399 | bgp_session_name = "bgp-peer0" 400 | 401 | bgp_peer_options = { 402 | advertise_mode = "CUSTOM" 403 | 404 | # advertise_ip_ranges is a map fo strings in format "ip-address" = "description of the IP address" ex: "199.36.153.4/30" = "restricted.googleapis.com IPs". advertise_mode should be "CUSTOM". Not needed if routes are advertised from cloud router. 405 | advertise_ip_ranges = { 406 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 407 | "199.36.153.8/30" = "private.googleapis.com IPs" 408 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 409 | "10.10.10.0/24" = "VPC IPs" 410 | } 411 | # ip_address = optional(string) # Optional GCP Router BGP IP address "169.254.20.1". Not needed. Will be pulled automatically from bgp_session_range 412 | # advertise_groups = optional(list(string)) 413 | # route_priority = optional(number) 414 | } 415 | 416 | bgp_session_range = "169.254.20.1/30" # GCP BGP session IP address in this format: "169.254.X.X/30" 417 | ike_version = 2 418 | vpn_gateway_interface = 0 419 | peer_external_gateway_interface = 0 420 | shared_secret = random_string.secret.result 421 | 422 | } 423 | } 424 | ``` 425 | 426 | # Examples 427 | 428 | - two tunnels 429 | 430 | ``` 431 | tunnels = { 432 | remote-0 = { 433 | 434 | bgp_peer = { 435 | address = "169.254.20.2" 436 | asn = 31898 437 | } 438 | 439 | bgp_session_name = "bgp-peer0" 440 | 441 | bgp_peer_options = { 442 | advertise_mode = "CUSTOM" 443 | advertise_ip_ranges = { 444 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 445 | "199.36.153.8/30" = "private.googleapis.com IPs" 446 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 447 | "10.10.10.0/24" = "VPC IPs" 448 | } 449 | } 450 | 451 | bgp_session_range = "169.254.20.1/30" 452 | ike_version = 2 453 | vpn_gateway_interface = 0 454 | peer_external_gateway_interface = 0 455 | shared_secret = random_string.secret.result 456 | 457 | } 458 | 459 | remote-1 = { 460 | 461 | bgp_peer = { 462 | address = "169.254.20.6" 463 | asn = 31898 464 | } 465 | 466 | bgp_session_name = "bgp-peer1" 467 | 468 | bgp_peer_options = { 469 | advertise_mode = "CUSTOM" 470 | advertise_ip_ranges = { 471 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 472 | "199.36.153.8/30" = "private.googleapis.com IPs" 473 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 474 | "10.10.10.0/24" = "VPC IPs" 475 | } 476 | } 477 | 478 | bgp_session_range = "169.254.20.5/30" 479 | ike_version = 2 480 | vpn_gateway_interface = 1 481 | peer_external_gateway_interface = 1 482 | shared_secret = random_string.secret.result 483 | } 484 | 485 | } 486 | ``` 487 | 488 | - Four tunnels 489 | 490 | ``` 491 | tunnels = { 492 | remote-0-0 = { 493 | 494 | bgp_peer = { 495 | address = "169.254.20.2" 496 | asn = 31898 497 | } 498 | 499 | bgp_session_name = "bgp-peer-0-0" 500 | 501 | bgp_peer_options = { 502 | advertise_mode = "CUSTOM" 503 | advertise_ip_ranges = { 504 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 505 | "199.36.153.8/30" = "private.googleapis.com IPs" 506 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 507 | "10.10.10.0/24" = "VPC IPs" 508 | } 509 | } 510 | 511 | bgp_session_range = "169.254.20.1/30" 512 | ike_version = 2 513 | vpn_gateway_interface = 0 514 | peer_external_gateway_interface = 0 515 | shared_secret = random_string.secret.result 516 | } 517 | 518 | remote-0-1 = { 519 | 520 | bgp_peer = { 521 | address = "169.254.20.6" 522 | asn = 31898 523 | } 524 | 525 | bgp_session_name = "bgp-peer-0-1" 526 | 527 | bgp_peer_options = { 528 | advertise_mode = "CUSTOM" 529 | advertise_ip_ranges = { 530 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 531 | "199.36.153.8/30" = "private.googleapis.com IPs" 532 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 533 | "10.10.10.0/24" = "VPC IPs" 534 | } 535 | } 536 | 537 | bgp_session_range = "169.254.20.5/30" 538 | ike_version = 2 539 | vpn_gateway_interface = 0 540 | peer_external_gateway_interface = 1 541 | shared_secret = random_string.secret.result 542 | } 543 | 544 | remote-1-0 = { 545 | 546 | bgp_peer = { 547 | address = "169.254.20.10" 548 | asn = 31898 549 | } 550 | 551 | bgp_session_name = "bgp-peer-1-0" 552 | 553 | bgp_peer_options = { 554 | advertise_mode = "CUSTOM" 555 | advertise_ip_ranges = { 556 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 557 | "199.36.153.8/30" = "private.googleapis.com IPs" 558 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 559 | "10.10.10.0/24" = "VPC IPs" 560 | } 561 | } 562 | 563 | bgp_session_range = "169.254.20.9/30" 564 | ike_version = 2 565 | vpn_gateway_interface = 1 566 | peer_external_gateway_interface = 2 567 | shared_secret = random_string.secret.result 568 | } 569 | 570 | remote-1-1 = { 571 | 572 | bgp_peer = { 573 | address = "169.254.20.14" 574 | asn = 31898 575 | } 576 | 577 | bgp_session_name = "bgp-peer-1-1" 578 | 579 | bgp_peer_options = { 580 | advertise_mode = "CUSTOM" 581 | advertise_ip_ranges = { 582 | "199.36.153.4/30" = "restricted.googleapis.com IPs" 583 | "199.36.153.8/30" = "private.googleapis.com IPs" 584 | "10.200.5.0/32" = "My GoogleAPIS PSC IP address" 585 | "10.10.10.0/24" = "VPC IPs" 586 | } 587 | } 588 | 589 | bgp_session_range = "169.254.20.13/30" 590 | ike_version = 2 591 | vpn_gateway_interface = 1 592 | peer_external_gateway_interface = 3 593 | shared_secret = random_string.secret.result 594 | } 595 | 596 | } 597 | ``` 598 | 599 | 600 | 601 | ## Requirements 602 | ### Terraform plugins 603 | - [Terraform](https://www.terraform.io/downloads.html) 1.3+ 604 | - [terraform-provider-google](https://github.com/terraform-providers/terraform-provider-google) plugin v5.7+ 605 | 606 | ### Configure a Service Account 607 | In order to execute this module you must have a Service Account with the following roles: 608 | - roles/compute.networkAdmin on the organization 609 | 610 | ### Enable API's 611 | In order to operate with the Service Account you must activate the following API on the project where the Service Account was created: 612 | - Compute Engine API - compute.googleapis.com 613 | 614 | --------------------------------------------------------------------------------