Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bunch of modifications #1

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,71 @@
# terraform-aws-gcp-vpn

Terraform module to create an HA VPN between AWS and GCP
Terraform module to create an HA VPN between AWS and GCP.

The purpose of this project is to setup an HA VPN connection between AWS and GCP based on the following documentation :

- [GCP ha vpn](https://cloud.google.com/network-connectivity/docs/vpn/how-to/creating-ha-vpn)
- [AWS vpn setup connection](https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html)

## Compatibility

This module is meant for use with Terraform 0.13 and further. This has been tested with provider `google` in version 3.3 and `aws` in 3.25.

## Example

Example of how to use this module can be found in the [example](example) folder.

```hcl
module "gcp-vpn" {
source = "build-and-run/gcp-vpn/aws"
version = "1.0"

aws_vpc = aws_vpc.default.id
gcp_network = google_compute_network.vpc.name

gcp_asn = 65500
}
```

## Firewall rules / security group

This module does no handle AWS Security Groups creation and GCP firewall rules. After setting up the VPN, you have to create them to allow traffic between your VPCs.

## Cloud DNS

This module can route the traffic from GCP Cloud DNS to AWS using the CIDR *35.199.192.0/19*. This means you can setup Forwarding Zones in Cloud DNS and route them to AWS (provided you setup the Security Groups rules).

## Requirements

| Name | Version |
|------|---------|
| terraform | >= 0.13 |
| aws | ~>3.25 |
| google | ~> 3.3 |

## Providers

| Name | Version |
|------|---------|
| aws | ~>3.25 |
| google | ~> 3.3 |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| aws\_vpc | VPC ID for AWS | `string` | n/a | yes |
| gcp\_asn | Google Cloud side ASN | `number` | n/a | yes |
| gcp\_network | Network name for GCP | `string` | n/a | yes |
| aws\_route\_tables\_ids | Routing table ID for AWS. By default it will take all the route tables in the VPC | `list(string)` | `null` | no |
| cloud\_dns\_route\_propagation | Wether you want to add GCP Cloud DNS (35.199.192.0/19) to propagated routes, so that you can use Cloud DNS zone forwarding to AWS | `bool` | `false` | no |
| customer | Customer applied to this instance | `string` | `""` | no |
| environment | Environment applied to this instance | `string` | `""` | no |
| gcp\_subnetworks | Routing table ID for AWS. By default it will take all the subnetworks in the VPC | <pre>list(object({<br> name = string<br> region = string<br> }))</pre> | `null` | no |
| ha\_vpn | Creates an HA VPN with two tunnels | `bool` | `false` | no |
| name | Name applied to this instance | `string` | `""` | no |
| tags | Tags applied to this instance | `map(string)` | <pre>{<br> "ManagedBy": "terraform"<br>}</pre> | no |

## Outputs

No output.
46 changes: 11 additions & 35 deletions aws.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ resource "aws_customer_gateway" "customer_gateway1" {
}

resource "aws_customer_gateway" "customer_gateway2" {
count = var.ha_vpn ? 1 : 0
bgp_asn = var.gcp_asn
ip_address = google_compute_ha_vpn_gateway.ha_vpn_gateway.vpn_interfaces[1].ip_address
type = "ipsec.1"
Expand All @@ -15,7 +16,7 @@ resource "aws_customer_gateway" "customer_gateway2" {
}

resource "aws_vpn_gateway" "default" {
vpc_id = "${var.aws_vpc}"
vpc_id = var.aws_vpc

tags = merge({ Name = var.name }, local.interpolated_tags)
}
Expand All @@ -29,45 +30,20 @@ resource "aws_vpn_connection" "vpn1" {
}

resource "aws_vpn_connection" "vpn2" {
count = var.ha_vpn ? 1 : 0
vpn_gateway_id = aws_vpn_gateway.default.id
customer_gateway_id = aws_customer_gateway.customer_gateway2.id
type = aws_customer_gateway.customer_gateway2.type
customer_gateway_id = aws_customer_gateway.customer_gateway2[0].id
type = aws_customer_gateway.customer_gateway2[0].type

tags = merge({ Name = var.name }, local.interpolated_tags)
}

resource "aws_route" "gcp" {
count = length(var.aws_route_tables_ids)
route_table_id = var.aws_route_tables_ids[count.index]
gateway_id = aws_vpn_gateway.default.id
destination_cidr_block = var.gcp_cidr

# NB: tags not supported here
# tags = merge({Name = var.name}, local.interpolated_tags)
data "aws_route_tables" "rts" {
vpc_id = var.aws_vpc
}

# Allow inbound access to VPC resources from GCP CIDR
resource "aws_security_group_rule" "google_ingress_vpn" {
type = "ingress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [var.gcp_cidr]
security_group_id = var.aws_sg

# NB: tags not supported here
# tags = merge({Name = var.name}, local.interpolated_tags)
}

# Allow outbound access from VPC resources to GCP CIDR
resource "aws_security_group_rule" "google_egress_vpn" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [var.gcp_cidr]
security_group_id = var.aws_sg

# NB: tags not supported here
# tags = merge({Name = var.name}, local.interpolated_tags)
resource "aws_vpn_gateway_route_propagation" "gcp" {
for_each = var.aws_route_tables_ids != null ? toset(var.aws_route_tables_ids) : data.aws_route_tables.rts.ids
vpn_gateway_id = aws_vpn_gateway.default.id
route_table_id = each.value
}
13 changes: 3 additions & 10 deletions example/terraform.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,10 @@ resource "google_compute_subnetwork" "vpc_subnetworks" {

module "gcp-vpn" {
source = "build-and-run/gcp-vpn/aws"
version = "0.2.0"

gcp_cidr = google_compute_subnetwork.vpc_subnetworks.ip_cidr_range

aws_region = "eu-west-1"
gcp_region = "us-east-1"
version = "1.0"

aws_vpc = aws_vpc.default.id
aws_sg = aws_security_group.allow_nomad.id
aws_route_table_id = aws_vpc.default.main_route_table_id

gcp_network = google_compute_network.vpc.id
gcp_network = google_compute_network.vpc.name

gcp_asn = 65500
}
89 changes: 61 additions & 28 deletions gcp.tf
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
# Fetch network
data "google_compute_network" "network" {
name = var.gcp_network
}
# Fetch subnetworks
data "google_compute_subnetwork" "all_subnetworks" {
count = length(data.google_compute_network.network.subnetworks_self_links)
self_link = data.google_compute_network.network.subnetworks_self_links[count.index]
}
data "google_compute_subnetwork" "subnetworks" {
count = var.gcp_subnetworks != null ? length(var.gcp_subnetworks) : 0
name = var.gcp_subnetworks[count.index].name
region = var.gcp_subnetworks[count.index].region
}

resource "google_compute_ha_vpn_gateway" "ha_vpn_gateway" {
name = "ha-vpn-gateway"
name = var.name
network = var.gcp_network
region = var.gcp_region

# NB: tags not supported here
# tags = merge({Name = var.name}, local.interpolated_tags)
}

resource "google_compute_router" "ha_vpn_gateway_router" {
name = "ha-vpn-gateway-router"
name = var.name
network = var.gcp_network
description = "Google to AWS via Transit GW connection for AWS"
description = format("Google to AWS via Transit GW connection for AWS - %s", var.name)
bgp {
asn = var.gcp_asn
advertise_mode = "CUSTOM"
advertised_ip_ranges {
range = var.gcp_cidr
description = var.gcp_cidr
dynamic "advertised_ip_ranges" {
for_each = var.gcp_subnetworks != null ? toset([]) : toset(data.google_compute_subnetwork.all_subnetworks)
content {
range = advertised_ip_ranges.value.ip_cidr_range
description = advertised_ip_ranges.value.name
}
}
dynamic "advertised_ip_ranges" {
for_each = var.gcp_subnetworks != null ? toset(data.google_compute_subnetwork.subnetworks) : toset([])
content {
range = advertised_ip_ranges.value.ip_cidr_range
description = advertised_ip_ranges.value.name
}
}
dynamic "advertised_ip_ranges" {
for_each = var.cloud_dns_route_propagation ? toset([local.gcp_cloud_dns]) : toset([])
content {
range = advertised_ip_ranges.value
description = "Cloud DNS route propagation"
}
}
}

Expand All @@ -25,9 +56,9 @@ resource "google_compute_router" "ha_vpn_gateway_router" {
}

resource "google_compute_external_vpn_gateway" "external_gateway" {
name = "aws-external-gateway"
redundancy_type = "FOUR_IPS_REDUNDANCY"
description = "AWS Transit GW"
name = var.name
redundancy_type = var.ha_vpn ? "FOUR_IPS_REDUNDANCY" : "TWO_IPS_REDUNDANCY"
description = format("AWS Transit GW - %s", var.name)

dynamic "interface" {
for_each = local.external_vpn_gateway_interfaces
Expand All @@ -44,8 +75,8 @@ resource "google_compute_external_vpn_gateway" "external_gateway" {
resource "google_compute_vpn_tunnel" "tunnels" {
for_each = local.external_vpn_gateway_interfaces

name = "gcp-tunnel${each.key}"
description = "Tunnel to AWS - HA VPN interface ${each.key} to AWS interface ${each.value.tunnel_address}"
name = format("%s-%s", var.name, each.key)
description = format("Tunnel to AWS - HA VPN interface %s to AWS interface %s - %s", each.key, each.value.tunnel_address, var.name)
router = google_compute_router.ha_vpn_gateway_router.self_link
ike_version = 2
shared_secret = each.value.shared_secret
Expand All @@ -61,7 +92,7 @@ resource "google_compute_vpn_tunnel" "tunnels" {
resource "google_compute_router_interface" "interfaces" {
for_each = local.external_vpn_gateway_interfaces

name = "interface${each.key}"
name = format("%s-interface%s", var.name, each.key)
router = google_compute_router.ha_vpn_gateway_router.name
ip_range = each.value.cgw_inside_address
vpn_tunnel = google_compute_vpn_tunnel.tunnels[each.key].name
Expand All @@ -73,7 +104,7 @@ resource "google_compute_router_interface" "interfaces" {
resource "google_compute_router_peer" "router_peers" {
for_each = local.external_vpn_gateway_interfaces

name = "peer${each.key}"
name = format("%s-peer%s", var.name, each.key)
router = google_compute_router.ha_vpn_gateway_router.name
peer_ip_address = each.value.vgw_inside_address
peer_asn = each.value.asn
Expand All @@ -84,7 +115,7 @@ resource "google_compute_router_peer" "router_peers" {
}

locals {
external_vpn_gateway_interfaces = {
external_vpn_gateway_interfaces_nonha = {
"0" = {
tunnel_address = aws_vpn_connection.vpn1.tunnel1_address
vgw_inside_address = aws_vpn_connection.vpn1.tunnel1_vgw_inside_address
Expand All @@ -100,22 +131,24 @@ locals {
cgw_inside_address = "${aws_vpn_connection.vpn1.tunnel2_cgw_inside_address}/30"
shared_secret = aws_vpn_connection.vpn1.tunnel2_preshared_key
vpn_gateway_interface = 0
},
}
}
external_vpn_gateway_interfaces = var.ha_vpn ? merge(local.external_vpn_gateway_interfaces_nonha, {
"2" = {
tunnel_address = aws_vpn_connection.vpn2.tunnel1_address
vgw_inside_address = aws_vpn_connection.vpn2.tunnel1_vgw_inside_address
asn = aws_vpn_connection.vpn2.tunnel1_bgp_asn
cgw_inside_address = "${aws_vpn_connection.vpn2.tunnel1_cgw_inside_address}/30"
shared_secret = aws_vpn_connection.vpn2.tunnel1_preshared_key
tunnel_address = aws_vpn_connection.vpn2[0].tunnel1_address
vgw_inside_address = aws_vpn_connection.vpn2[0].tunnel1_vgw_inside_address
asn = aws_vpn_connection.vpn2[0].tunnel1_bgp_asn
cgw_inside_address = "${aws_vpn_connection.vpn2[0].tunnel1_cgw_inside_address}/30"
shared_secret = aws_vpn_connection.vpn2[0].tunnel1_preshared_key
vpn_gateway_interface = 1
},
"3" = {
tunnel_address = aws_vpn_connection.vpn2.tunnel2_address
vgw_inside_address = aws_vpn_connection.vpn2.tunnel2_vgw_inside_address
asn = aws_vpn_connection.vpn2.tunnel2_bgp_asn
cgw_inside_address = "${aws_vpn_connection.vpn2.tunnel2_cgw_inside_address}/30"
shared_secret = aws_vpn_connection.vpn2.tunnel2_preshared_key
tunnel_address = aws_vpn_connection.vpn2[0].tunnel2_address
vgw_inside_address = aws_vpn_connection.vpn2[0].tunnel2_vgw_inside_address
asn = aws_vpn_connection.vpn2[0].tunnel2_bgp_asn
cgw_inside_address = "${aws_vpn_connection.vpn2[0].tunnel2_cgw_inside_address}/30"
shared_secret = aws_vpn_connection.vpn2[0].tunnel2_preshared_key
vpn_gateway_interface = 1
},
}
}
}, local.external_vpn_gateway_interfaces_nonha) : local.external_vpn_gateway_interfaces_nonha
}
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ locals {
{ "Environment" = var.environment },
var.tags
)
gcp_cloud_dns = "35.199.192.0/19"
}
42 changes: 22 additions & 20 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,44 @@ variable "tags" {
}

# bellow are specific modules variables
variable "gcp_cidr" {
description = "CIDR group for GCP network"
type = string
}

variable "gcp_network" {
description = "Network name for GCP"
type = string
}

variable "gcp_region" {
description = "Region for GCP"
type = string
}

variable "aws_region" {
description = "Region for AWS"
type = string
variable "gcp_subnetworks" {
description = "Routing table ID for AWS. By default it will take all the subnetworks in the VPC"
type = list(object({
name = string
region = string
}))
default = null
}

variable "aws_vpc" {
description = "VPC ID for AWS"
type = string
}

variable "aws_sg" {
description = "Security group for AWS Network"
type = string
}

variable "aws_route_tables_ids" {
description = "Routing table ID for AWS"
description = "Routing table ID for AWS. By default it will take all the route tables in the VPC"
type = list(string)
default = null
}

variable "gcp_asn" {
description = "Google Cloud side ASN"
type = number
}
}

variable "cloud_dns_route_propagation" {
description = "Wether you want to add GCP Cloud DNS (35.199.192.0/19) to propagated routes, so that you can use Cloud DNS zone forwarding to AWS"
type = bool
default = false
}

variable "ha_vpn" {
description = "Creates an HA VPN with two tunnels"
type = bool
default = false
}
Loading