Added recipe HA VPN between AWS and GCP (#3034)
* Added recipe HA VPN between AWS and GCP * Fix typo * Update providers to work without credentials * Add AWS resource to tools/lockfile/main.tf * Fixed error in recipe docs --------- Co-authored-by: Julio Castillo <jccb@google.com>
This commit is contained in:
@@ -2,6 +2,17 @@
|
||||
|
||||
This module makes it easy to deploy either GCP-to-GCP or GCP-to-On-prem [Cloud HA VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/overview#ha-vpn).
|
||||
|
||||
<!-- BEGIN TOC -->
|
||||
- [Examples](#examples)
|
||||
- [GCP to GCP](#gcp-to-gcp)
|
||||
- [GCP to on-prem](#gcp-to-on-prem)
|
||||
- [IPv6 (dual-stack)](#ipv6-dual-stack)
|
||||
- [Recipes](#recipes)
|
||||
- [Recipes](#recipes)
|
||||
- [Variables](#variables)
|
||||
- [Outputs](#outputs)
|
||||
<!-- END TOC -->
|
||||
|
||||
## Examples
|
||||
|
||||
### GCP to GCP
|
||||
@@ -204,7 +215,16 @@ module "vpn_ha" {
|
||||
```
|
||||
|
||||
You can optionally avoid to specify MD5 keys and the module will automatically generate them for you.
|
||||
|
||||
## Recipes
|
||||
|
||||
- [HA VPN connections between Google Cloud and AWS](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/blob/master/modules/net-vpn-ha/recipe-vpn-aws-gcp)
|
||||
|
||||
<!-- BEGIN TFDOC -->
|
||||
## Recipes
|
||||
|
||||
- [HA VPN connections between Google Cloud and AWS](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/blob/master/modules/net-vpn-ha/recipe-vpn-aws-gcp)
|
||||
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default |
|
||||
|
||||
48
modules/net-vpn-ha/recipe-vpn-aws-gcp/README.md
Normal file
48
modules/net-vpn-ha/recipe-vpn-aws-gcp/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# HA VPN connections between Google Cloud and AWS
|
||||
|
||||
This recipe demonstrates how to create highly available VPN connections between Google Cloud and Amazon Web Services (AWS) for direct communication between VPC networks across the two cloud platforms using a Virtual Private Gateway in AWS. For more details on this architecture have a look [here](https://cloud.google.com/network-connectivity/docs/vpn/tutorials/create-ha-vpn-connections-google-cloud-aws)
|
||||
|
||||
The architecture deployed by this recipe is the one depicted below:
|
||||
|
||||

|
||||
<!-- BEGIN TFDOC -->
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [aws_asn](variables.tf#L27) | AWS ASN. | <code>string</code> | ✓ | |
|
||||
| [aws_region](variables.tf#L32) | AWS Region. | <code>string</code> | ✓ | |
|
||||
| [aws_vpc_cidr_block](variables.tf#L37) | CIDR block. | <code>string</code> | ✓ | |
|
||||
| [gcp_asn](variables.tf#L42) | Google ASN. | <code>string</code> | ✓ | |
|
||||
| [gcp_region](variables.tf#L47) | GCP Region. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L52) | Project ID. | <code>string</code> | ✓ | |
|
||||
| [shared_secret](variables.tf#L63) | Shared secret. | <code>string</code> | ✓ | |
|
||||
| [_testing](variables.tf#L17) | Populate this variable to avoid triggering the data source. | <code title="object({ name = string number = number services_enabled = optional(list(string), []) })">object({…})</code> | | <code>null</code> |
|
||||
| [propagate_routes](variables.tf#L57) | Flag indicating whether routed received by AWS's Virtual Private Gateway should be propagated to main route table. | <code>bool</code> | | <code>false</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [external_gateway](outputs.tf#L17) | External VPN gateway resource. | |
|
||||
| [gateway](outputs.tf#L22) | VPN gateway resource (only if auto-created). | |
|
||||
| [id](outputs.tf#L27) | Fully qualified VPN gateway id. | |
|
||||
<!-- END TFDOC -->
|
||||
## Test
|
||||
|
||||
```hcl
|
||||
module "gcp_vpn" {
|
||||
source = "./fabric/modules/net-vpn-ha/recipe-vpn-aws-gcp"
|
||||
project_id = "project-1"
|
||||
_testing = {
|
||||
name = "project-1"
|
||||
number = 1234567890
|
||||
}
|
||||
aws_asn = 65001
|
||||
gcp_asn = 65534
|
||||
aws_region = "us-east-1"
|
||||
gcp_region = "us-east1"
|
||||
aws_vpc_cidr_block = "10.0.0.0/16"
|
||||
shared_secret = "test123456"
|
||||
}
|
||||
# tftest modules=4 resources=36
|
||||
69
modules/net-vpn-ha/recipe-vpn-aws-gcp/aws.tf
Normal file
69
modules/net-vpn-ha/recipe-vpn-aws-gcp/aws.tf
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
resource "aws_vpc" "vpc" {
|
||||
cidr_block = var.aws_vpc_cidr_block
|
||||
}
|
||||
|
||||
resource "aws_vpn_gateway" "vpn_gateway" {
|
||||
vpc_id = aws_vpc.vpc.id
|
||||
amazon_side_asn = var.aws_asn
|
||||
tags = {
|
||||
Name = "vpn_gateway"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_customer_gateway" "customer_gateways" {
|
||||
count = 2
|
||||
bgp_asn = var.gcp_asn
|
||||
ip_address = module.gcp_vpn.gateway.vpn_interfaces[count.index].ip_address
|
||||
type = "ipsec.1"
|
||||
|
||||
tags = {
|
||||
Name = "customer-gateway-${count.index}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpn_gateway_attachment" "vpn_gateway_attachment" {
|
||||
vpc_id = aws_vpc.vpc.id
|
||||
vpn_gateway_id = aws_vpn_gateway.vpn_gateway.id
|
||||
}
|
||||
|
||||
resource "aws_vpn_connection" "vpn_connections" {
|
||||
count = 2
|
||||
vpn_gateway_id = aws_vpn_gateway.vpn_gateway.id
|
||||
customer_gateway_id = aws_customer_gateway.customer_gateways[count.index].id
|
||||
type = "ipsec.1"
|
||||
tunnel1_preshared_key = var.shared_secret
|
||||
tunnel2_preshared_key = var.shared_secret
|
||||
}
|
||||
|
||||
|
||||
data "aws_route_table" "route_table" {
|
||||
count = var.propagate_routes ? 1 : 0
|
||||
vpc_id = aws_vpc.vpc.id
|
||||
filter {
|
||||
name = "association.main"
|
||||
values = ["true"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpn_gateway_route_propagation" "vpn_gateway_route_propagation" {
|
||||
count = var.propagate_routes ? 1 : 0
|
||||
vpn_gateway_id = aws_vpn_gateway.vpn_gateway.id
|
||||
route_table_id = data.aws_route_table.route_table[0].id
|
||||
}
|
||||
|
||||
BIN
modules/net-vpn-ha/recipe-vpn-aws-gcp/diagram.png
Normal file
BIN
modules/net-vpn-ha/recipe-vpn-aws-gcp/diagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
105
modules/net-vpn-ha/recipe-vpn-aws-gcp/gcp.tf
Normal file
105
modules/net-vpn-ha/recipe-vpn-aws-gcp/gcp.tf
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
module "project" {
|
||||
source = "../../../modules/project"
|
||||
name = var.project_id
|
||||
project_reuse = {
|
||||
use_data_source = var._testing == null
|
||||
project_attributes = var._testing
|
||||
}
|
||||
services = [
|
||||
"compute.googleapis.com",
|
||||
"dns.googleapis.com",
|
||||
]
|
||||
}
|
||||
|
||||
module "vpc" {
|
||||
source = "../../../modules/net-vpc"
|
||||
project_id = module.project.project_id
|
||||
name = "vpc"
|
||||
}
|
||||
|
||||
module "gcp_vpn" {
|
||||
source = "../../../modules/net-vpn-ha"
|
||||
project_id = module.project.project_id
|
||||
region = var.gcp_region
|
||||
network = module.vpc.self_link
|
||||
name = "vpn"
|
||||
peer_gateways = {
|
||||
default = {
|
||||
external = {
|
||||
redundancy_type = "FOUR_IPS_REDUNDANCY"
|
||||
interfaces = [
|
||||
aws_vpn_connection.vpn_connections[0].tunnel1_address,
|
||||
aws_vpn_connection.vpn_connections[0].tunnel2_address,
|
||||
aws_vpn_connection.vpn_connections[1].tunnel1_address,
|
||||
aws_vpn_connection.vpn_connections[1].tunnel2_address
|
||||
] # on-prem router ip address
|
||||
}
|
||||
}
|
||||
}
|
||||
router_config = {
|
||||
asn = var.gcp_asn
|
||||
custom_advertise = {
|
||||
all_subnets = true
|
||||
ip_ranges = {
|
||||
}
|
||||
}
|
||||
}
|
||||
tunnels = {
|
||||
remote-0 = {
|
||||
bgp_peer = {
|
||||
address = aws_vpn_connection.vpn_connections[0].tunnel1_vgw_inside_address
|
||||
asn = var.aws_asn
|
||||
}
|
||||
bgp_session_range = "${aws_vpn_connection.vpn_connections[0].tunnel1_cgw_inside_address}/30"
|
||||
peer_external_gateway_interface = 0
|
||||
shared_secret = var.shared_secret
|
||||
vpn_gateway_interface = 0
|
||||
}
|
||||
remote-1 = {
|
||||
bgp_peer = {
|
||||
address = aws_vpn_connection.vpn_connections[0].tunnel2_vgw_inside_address
|
||||
asn = var.aws_asn
|
||||
}
|
||||
bgp_session_range = "${aws_vpn_connection.vpn_connections[0].tunnel2_cgw_inside_address}/30"
|
||||
peer_external_gateway_interface = 1
|
||||
shared_secret = var.shared_secret
|
||||
vpn_gateway_interface = 0
|
||||
}
|
||||
remote-2 = {
|
||||
bgp_peer = {
|
||||
address = aws_vpn_connection.vpn_connections[1].tunnel1_vgw_inside_address
|
||||
asn = var.aws_asn
|
||||
}
|
||||
bgp_session_range = "${aws_vpn_connection.vpn_connections[1].tunnel1_cgw_inside_address}/30"
|
||||
peer_external_gateway_interface = 2
|
||||
shared_secret = var.shared_secret
|
||||
vpn_gateway_interface = 1
|
||||
}
|
||||
remote-3 = {
|
||||
bgp_peer = {
|
||||
address = aws_vpn_connection.vpn_connections[1].tunnel2_vgw_inside_address
|
||||
asn = var.aws_asn
|
||||
}
|
||||
bgp_session_range = "${aws_vpn_connection.vpn_connections[1].tunnel2_cgw_inside_address}/30"
|
||||
peer_external_gateway_interface = 3
|
||||
shared_secret = var.shared_secret
|
||||
vpn_gateway_interface = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
30
modules/net-vpn-ha/recipe-vpn-aws-gcp/outputs.tf
Normal file
30
modules/net-vpn-ha/recipe-vpn-aws-gcp/outputs.tf
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
output "external_gateway" {
|
||||
description = "External VPN gateway resource."
|
||||
value = module.gcp_vpn.external_gateway
|
||||
}
|
||||
|
||||
output "gateway" {
|
||||
description = "VPN gateway resource (only if auto-created)."
|
||||
value = module.gcp_vpn.gateway
|
||||
}
|
||||
|
||||
output "id" {
|
||||
description = "Fully qualified VPN gateway id."
|
||||
value = module.gcp_vpn.id
|
||||
}
|
||||
26
modules/net-vpn-ha/recipe-vpn-aws-gcp/providers.tf
Normal file
26
modules/net-vpn-ha/recipe-vpn-aws-gcp/providers.tf
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
# The values below are needed to allow the tests to work for this
|
||||
# recipe without requiring credentials
|
||||
skip_credentials_validation = true
|
||||
skip_requesting_account_id = true
|
||||
skip_metadata_api_check = true
|
||||
access_key = "mock_access_key"
|
||||
secret_key = "mock_secret_key"
|
||||
}
|
||||
67
modules/net-vpn-ha/recipe-vpn-aws-gcp/variables.tf
Normal file
67
modules/net-vpn-ha/recipe-vpn-aws-gcp/variables.tf
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
variable "_testing" {
|
||||
description = "Populate this variable to avoid triggering the data source."
|
||||
type = object({
|
||||
name = string
|
||||
number = number
|
||||
services_enabled = optional(list(string), [])
|
||||
})
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "aws_asn" {
|
||||
description = "AWS ASN."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "aws_region" {
|
||||
description = "AWS Region."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "aws_vpc_cidr_block" {
|
||||
description = "CIDR block."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "gcp_asn" {
|
||||
description = "Google ASN."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "gcp_region" {
|
||||
description = "GCP Region."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
description = "Project ID."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "propagate_routes" {
|
||||
description = "Flag indicating whether routed received by AWS's Virtual Private Gateway should be propagated to main route table."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "shared_secret" {
|
||||
description = "Shared secret."
|
||||
type = string
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -24,3 +24,4 @@ resource "time_static" "default" {}
|
||||
resource "tls_private_key" "default" {}
|
||||
resource "vsphere_role" "default" {}
|
||||
resource "kubernetes_secret" "default" {}
|
||||
resource "aws_vpc" "default" {}
|
||||
|
||||
Reference in New Issue
Block a user