From df5ae62d5d0a8d6cfe163bf4ce08a568adb1a115 Mon Sep 17 00:00:00 2001 From: badra001 Date: Sun, 2 May 2021 16:18:38 -0400 Subject: [PATCH] add vpn submodule --- vpn/data.tf | 1 + vpn/defaults.tf | 1 + vpn/main.tf | 157 ++++++++++++++++++++++++++++++++++++ vpn/outputs.tf | 18 +++++ vpn/prefixes.tf | 1 + vpn/variables.common.tf | 1 + vpn/variables.common.vpc.tf | 1 + vpn/variables.tf | 30 +++++++ vpn/version.tf | 1 + 9 files changed, 211 insertions(+) create mode 120000 vpn/data.tf create mode 120000 vpn/defaults.tf create mode 100644 vpn/main.tf create mode 100644 vpn/outputs.tf create mode 120000 vpn/prefixes.tf create mode 120000 vpn/variables.common.tf create mode 120000 vpn/variables.common.vpc.tf create mode 100644 vpn/variables.tf create mode 120000 vpn/version.tf diff --git a/vpn/data.tf b/vpn/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/vpn/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/vpn/defaults.tf b/vpn/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/vpn/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/vpn/main.tf b/vpn/main.tf new file mode 100644 index 0000000..218f81f --- /dev/null +++ b/vpn/main.tf @@ -0,0 +1,157 @@ +/* +* # About aws-vpc-setup :: vpn +* +* This sets up a VPN for the specified site (hq or bcc) and all the necessary related components: +* * vpn gateway +* * customer gateway per site +* * vpn connection per site +* +* It generates a password for each site and uses the same one for each of the site's two tunnels. +* +* To download the configuration, follow these directions [page 24 from AWS docs](https://docs.aws.amazon.com/vpn/latest/s2svpn/s2s-vpn-user-guide.pdf): +* +* > To download the configuration file +* > 1. Open the Amazon VPC console at https://console.aws.amazon.com/vpc/. +* > 1. In the navigation pane, choose Site-to-Site VPN Connections. +* > 1. Select your VPN connection and choose Download Configuration. +* > 1. Select the vendor, platform, and software that corresponds to your customer gateway device or +* > 1oftware. If your device is not listed, choose Generic. Choose Download. +* > * Vendor: Cisco Systems, Inc. +* > * Platform: Cisco ASR 1000 +* > * Software: IOS 12.4+ +* +* # Usage +* +* ```hcl +* module "vpn" +* source = "git@github.e.it.census.gov:terraform-modules/aws-vpc-setup.git//vpn" +* vpc_id = "vpc-1234568" +* vpc_full_name = "vpc2-dice-dev" +* vpc_environment = "dev" +* vpn_settings = [ +* { site = "hq", "bgp_asn_id" = 65510, "ip_address" = "148.129.160.100" }, +* { site = "bcc", "bgp_asn_id" = 65511, "ip_address" = "148.129.90.100" }, +* ] +* route_table_ids = [ "rtb-1234", "rtb-2345", "rtb-3456" ] +* tags = {} +* } +* ``` +*/ + +locals { + account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id + account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" + vpn_settings = { for v in var.vpn_settings : lower(v.site) => { + site = lower(v.site) + bgp_asn_id = v.bgp_asn_id + ip_address = v.ip_address + } } + + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:created_by" = "terraform" + } +} + + +#--- +# vpn gateway (one per vpc) +#--- +resource "aws_vpn_gateway" "vpn" { + vpc_id = var.vpc_id + + tags = merge( + local.base_tags, + local.tags, + map("Name", format("%v%v", local._prefixes["vpn-gateway"], var.vpc_full_name)) + ) +} + +resource "aws_vpn_gateway_attachment" "vpn" { + vpc_id = aws_vpc.vpc.id + vpn_gateway_id = aws_vpn_gateway.vpn.id +} + +#--- +# customer gateway, one per vpc per site +#--- +resource "aws_customer_gateway" "vpn" { + for_each = local.vpn_settings + bgp_asn = each.value.bgp_asn_id + ip_address = each.value.ip_address + type = "ipsec.1" + + tags = merge( + local.base_tags, + local.tags, + map("Name", format("%v%v-%v", local._prefixes["customer-gateway"], each.key, var.vpc_full_name)), + ) +} + +#--- +# vpn pre-shared key (same for each tunnel per site, one per site) +#--- +resource "random_string" "tunnel_preshared_key" { + for_each = local.vpn_settings + length = 32 + special = true + override_special = "._" +} + +#--- +# vpn connection, one per vpn endpoint +#--- +resource "aws_vpn_connection" "vpn" { + for_each = local.vpn_settings + type = "ipsec.1" + vpn_gateway_id = aws_vpn_gateway.vpn.id + customer_gateway_id = aws_customer_gateway.vpn[each.key].id + tunnel1_preshared_key = random_string.tunnel_preshared_key[each.key].result + tunnel2_preshared_key = random_string.tunnel_preshared_key[each.key].result + static_routes_only = var.vpc_vpn_dynamic_routing ? false : true + + tags = merge( + local.base_tags, + local.tags, + map("Name", format("%v%v-%v", local._prefixes["vpn-connection"], each.key, var.vpc_full_name)) + ) +} + + +#--- +# vpn routes and propagation +#--- +# do not use connection routes for vpn bgp dynamic routing +# assumes dynamic routing only, so this is commented out and will need to be re-worked if static is desired +#resource "aws_vpn_connection_route" "vpn" { +# count = var.vpc_vpn_dynamic_routing ? 0 : length(var.network_census) +# destination_cidr_block = var.network_census[count.index] +# vpn_connection_id = aws_vpn_connection.vpn.id +#} + +locals { + vpn_route_table_ids = [ + for pair in setproduct(keys(local.vpn_settings), var.route_table_ids) : { + site = pair[0].key + route_table_id = pair[1].key + } + ] +} + +# use this resource, do not use propagating_vgws on the route tables. Need this for one per route table ID +resource "aws_vpn_gateway_route_propagation" "vpn" { + for_each = { for v in local.vpn_route_table_ids : "${v.site}.${v.route_table_id}" => v } + + vpn_gateway_id = aws_vpn_gateway.vpn.id + route_table_id = each.value.route_table_id +} + +## #--- +## # export client configuartion +## # this wont work, not doing what I want +## #--- +## resource "null_resource" "vpn_hq" { +## provisioner "local-exec" { +## command = "aws --profile ${var.profile} ec2 export-client-vpn-client-configuration --client-vpn-endpoint-id ${aws_vpn_connection.vpn_hq.id} > generated.vpn_hq.${var.vpc_full_name}.config.txt" +## } +## } diff --git a/vpn/outputs.tf b/vpn/outputs.tf new file mode 100644 index 0000000..1a5aa19 --- /dev/null +++ b/vpn/outputs.tf @@ -0,0 +1,18 @@ +output "vpn_tunnel_endpoints" { + description = "VPN Tunnel Endpoint IP Addresses" + value = { for k in keys(local.vpn_settings) : k => { + site = k + tunnel1_address = aws_vpn_connection.vpn[k].tunnel1_address + tunnel2_address = aws_vpn_connection.vpn[k].tunnel2_address + } + } +} + +output "vpn_label" { + description = "VPN Label for Description field of Endpoint device (Cisco ASR)" + value = { for k in keys(local.vpn_settings) : k => { + site = k + label = format("aws:%v:%v:%v:%v", local.region, local.account_id, aws_vpn_connection.vpn[k].id, var.vpc_full_name) + } + } +} diff --git a/vpn/prefixes.tf b/vpn/prefixes.tf new file mode 120000 index 0000000..7e265d5 --- /dev/null +++ b/vpn/prefixes.tf @@ -0,0 +1 @@ +../common/prefixes.tf \ No newline at end of file diff --git a/vpn/variables.common.tf b/vpn/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/vpn/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/vpn/variables.common.vpc.tf b/vpn/variables.common.vpc.tf new file mode 120000 index 0000000..5e77d37 --- /dev/null +++ b/vpn/variables.common.vpc.tf @@ -0,0 +1 @@ +../common/variables.common.vpc.tf \ No newline at end of file diff --git a/vpn/variables.tf b/vpn/variables.tf new file mode 100644 index 0000000..f5f9ade --- /dev/null +++ b/vpn/variables.tf @@ -0,0 +1,30 @@ +# variable "source_site" { +# description = "Source site location (hq, bcc)" +# type = string +# } +# +# variable "vpn_site_bgp_asn" { +# description = "BGP ASN ID specific to source site, provided by TCO" +# type = number +# } +# +# variable "vpn_site_ip_address" { +# description = "IP termination address specific to source site, provided by TCO (on-prem VPN endpoint IP)" +# type =string +# } +# + +variable "vpn_settings" { + description = "List of VPN setting objects including site, BGP ASN ID, and VPN termination IP" + type = list(object({ + site = string + bgp_asn_id = number + ip_address = string + })) +} + +variable "route_table_ids" { + description = "List of created route table IDs for privating routing to be used for VPN route propagation" + type = list(string) + default = [] +} diff --git a/vpn/version.tf b/vpn/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/vpn/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file