Skip to content

Commit

Permalink
Adds site 2 site vpn module (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelhar authored Sep 4, 2024
1 parent 343b7e6 commit 216bd85
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 5 deletions.
21 changes: 21 additions & 0 deletions examples/tfvars/vpn.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
deploy_id = "plantest0013"
region = "us-west-2"
ssh_pvt_key_path = "domino.pem"

default_node_groups = {
compute = {
availability_zone_ids = ["usw2-az1", "usw2-az2"]
}
gpu = {
availability_zone_ids = ["usw2-az1", "usw2-az2"]
}
platform = {
"availability_zone_ids" = ["usw2-az1", "usw2-az2"]
}
}

vpn_connection = {
create = true
shared_ip = "203.0.113.12"
cidr_block = "192.168.0.0/16"
}
3 changes: 3 additions & 0 deletions modules/infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
| <a name="module_cost_usage_report"></a> [cost\_usage\_report](#module\_cost\_usage\_report) | ./submodules/cost-usage-report | n/a |
| <a name="module_network"></a> [network](#module\_network) | ./submodules/network | n/a |
| <a name="module_storage"></a> [storage](#module\_storage) | ./submodules/storage | n/a |
| <a name="module_vpn"></a> [vpn](#module\_vpn) | ./submodules/vpn | n/a |

## Resources

Expand Down Expand Up @@ -66,6 +67,7 @@
| <a name="input_storage"></a> [storage](#input\_storage) | storage = {<br> filesystem\_type = File system type(netapp\|efs)<br> efs = {<br> access\_point\_path = Filesystem path for efs.<br> backup\_vault = {<br> create = Create backup vault for EFS toggle.<br> force\_destroy = Toggle to allow automatic destruction of all backups when destroying.<br> backup = {<br> schedule = Cron-style schedule for EFS backup vault (default: once a day at 12pm).<br> cold\_storage\_after = Move backup data to cold storage after this many days.<br> delete\_after = Delete backup data after this many days.<br> }<br> }<br> }<br> netapp = {<br> deployment\_type = netapp ontap deployment type,('MULTI\_AZ\_1', 'MULTI\_AZ\_2', 'SINGLE\_AZ\_1', 'SINGLE\_AZ\_2')<br> storage\_capacity = Filesystem Storage capacity<br> throughput\_capacity = Filesystem throughput capacity<br> automatic\_backup\_retention\_days = How many days to keep backups<br> daily\_automatic\_backup\_start\_time = Start time in 'HH:MM' format to initiate backups<br> }<br> s3 = {<br> force\_destroy\_on\_deletion = Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets.<br> }<br> ecr = {<br> force\_destroy\_on\_deletion = Toogle to allow recursive deletion of all objects in the ECR repositories. if 'false' terraform will NOT be able to delete non-empty repositories.<br> }<br> enable\_remote\_backup = Enable tagging required for cross-account backups<br> costs\_enabled = Determines whether to provision domino cost related infrastructures, ie, long term storage<br> }<br> } | <pre>object({<br> filesystem_type = optional(string, "efs")<br> efs = optional(object({<br> access_point_path = optional(string, "/domino")<br> backup_vault = optional(object({<br> create = optional(bool, true)<br> force_destroy = optional(bool, true)<br> backup = optional(object({<br> schedule = optional(string, "0 12 * * ? *")<br> cold_storage_after = optional(number, 35)<br> delete_after = optional(number, 125)<br> }), {})<br> }), {})<br> }), {})<br> netapp = optional(object({<br> deployment_type = optional(string, "SINGLE_AZ_1")<br> storage_capacity = optional(number, 1024)<br> throughput_capacity = optional(number, 128)<br> automatic_backup_retention_days = optional(number, 90)<br> daily_automatic_backup_start_time = optional(string, "00:00")<br> }), {})<br> s3 = optional(object({<br> force_destroy_on_deletion = optional(bool, true)<br> }), {})<br> ecr = optional(object({<br> force_destroy_on_deletion = optional(bool, true)<br> }), {}),<br> enable_remote_backup = optional(bool, false)<br> costs_enabled = optional(bool, true)<br> })</pre> | `{}` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no |
| <a name="input_use_fips_endpoint"></a> [use\_fips\_endpoint](#input\_use\_fips\_endpoint) | Use aws FIPS endpoints | `bool` | `false` | no |
| <a name="input_vpn_connection"></a> [vpn\_connection](#input\_vpn\_connection) | create = Create a VPN connection.<br> shared\_ip = Customer's shared IP Address.<br> cidr\_block = CIDR block for the customer's network. | <pre>object({<br> create = optional(bool, false)<br> shared_ip = optional(string, "")<br> cidr_block = optional(string, "")<br> })</pre> | `{}` | no |

## Outputs

Expand All @@ -89,4 +91,5 @@
| <a name="output_ssh_key"></a> [ssh\_key](#output\_ssh\_key) | SSH key path,name. |
| <a name="output_storage"></a> [storage](#output\_storage) | Storage details. |
| <a name="output_tags"></a> [tags](#output\_tags) | Deployment tags. |
| <a name="output_vpn_connection"></a> [vpn\_connection](#output\_vpn\_connection) | VPN connection information |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
8 changes: 8 additions & 0 deletions modules/infra/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ module "network" {
flow_log_bucket_arn = { arn = module.storage.info.s3.buckets.monitoring.arn }
}

module "vpn" {
count = var.vpn_connection.create ? 1 : 0
source = "./submodules/vpn"
deploy_id = var.deploy_id
network_info = module.network.info
vpn_connection = var.vpn_connection
}

locals {
ssh_pvt_key_path = abspath(pathexpand(var.ssh_pvt_key_path))
ssh_key = {
Expand Down
5 changes: 5 additions & 0 deletions modules/infra/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ output "cost_usage_report" {
description = "Cost Usage Report"
value = local.cost_usage_report_info
}

output "vpn_connection" {
description = "VPN connection information"
value = var.vpn_connection.create ? module.vpn[0].vpn_connection : null
}
4 changes: 4 additions & 0 deletions modules/infra/submodules/network/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ locals {
for subnet in data.aws_subnet.pod :
{ name = subnet.tags.Name, subnet_id = subnet.id, az = subnet.availability_zone, az_id = subnet.availability_zone_id }
]

public_route_table_ids = [for rt in aws_route_table.public : rt.id]
private_route_table_ids = [for rt in aws_route_table.private : rt.id]
pod_route_table_ids = [for rt in aws_route_table.pod : rt.id]
}
5 changes: 5 additions & 0 deletions modules/infra/submodules/network/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ output "info" {
private = local.private_subnets
pod = local.pod_subnets
}
route_tables = {
public = local.public_route_table_ids
private = local.private_route_table_ids
pod = local.pod_route_table_ids
}
eips = [for k, eip in aws_eip.public : eip.public_ip]
vpc_cidrs = var.network.cidrs.vpc
}
Expand Down
6 changes: 1 addition & 5 deletions modules/infra/submodules/network/vpc.tf
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ resource "aws_vpc_endpoint" "s3" {
service_name = "com.amazonaws.${var.region}.s3"
vpc_endpoint_type = "Gateway"

route_table_ids = concat(
[for s in aws_route_table.public : s.id],
[for s in aws_route_table.private : s.id],
[for s in aws_route_table.pod : s.id]
)
route_table_ids = concat(local.public_route_table_ids, local.private_route_table_ids, local.pod_route_table_ids)

tags = {
"Name" = "${var.deploy_id}-s3"
Expand Down
45 changes: 45 additions & 0 deletions modules/infra/submodules/vpn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# vpn

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 5.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_customer_gateway.customer_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/customer_gateway) | resource |
| [aws_vpn_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_connection) | resource |
| [aws_vpn_connection_route.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_connection_route) | resource |
| [aws_vpn_gateway.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway) | resource |
| [aws_vpn_gateway_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway_attachment) | resource |
| [aws_vpn_gateway_route_propagation.route_propagation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpn_gateway_route_propagation) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_deploy_id"></a> [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes |
| <a name="input_network_info"></a> [network\_info](#input\_network\_info) | id = VPC ID.<br> subnets = {<br> public = List of public Subnets.<br> [{<br> name = Subnet name.<br> subnet\_id = Subnet ud<br> az = Subnet availability\_zone<br> az\_id = Subnet availability\_zone\_id<br> }]<br> private = List of private Subnets.<br> [{<br> name = Subnet name.<br> subnet\_id = Subnet ud<br> az = Subnet availability\_zone<br> az\_id = Subnet availability\_zone\_id<br> }]<br> pod = List of pod Subnets.<br> [{<br> name = Subnet name.<br> subnet\_id = Subnet ud<br> az = Subnet availability\_zone<br> az\_id = Subnet availability\_zone\_id<br> }]<br> } | <pre>object({<br> vpc_id = string<br> route_tables = object({<br> public = optional(list(string))<br> private = optional(list(string))<br> pod = optional(list(string))<br> })<br> subnets = object({<br> public = list(object({<br> name = string<br> subnet_id = string<br> az = string<br> az_id = string<br> }))<br> private = list(object({<br> name = string<br> subnet_id = string<br> az = string<br> az_id = string<br> }))<br> pod = list(object({<br> name = string<br> subnet_id = string<br> az = string<br> az_id = string<br> }))<br> })<br> vpc_cidrs = string<br> })</pre> | n/a | yes |
| <a name="input_vpn_connection"></a> [vpn\_connection](#input\_vpn\_connection) | shared\_ip = Customer's shared IP Address.<br> cidr\_block = CIDR block for the customer's network. | <pre>object({<br> shared_ip = string<br> cidr_block = string<br> })</pre> | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_vpn_connection"></a> [vpn\_connection](#output\_vpn\_connection) | VPN connection information |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
45 changes: 45 additions & 0 deletions modules/infra/submodules/vpn/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@


resource "aws_customer_gateway" "customer_gateway" {
ip_address = var.vpn_connection.shared_ip
type = "ipsec.1"
}

resource "aws_vpn_gateway" "this" {
vpc_id = var.network_info.vpc_id
tags = {
Name = "${var.deploy_id}-vpn-gateway"
}
}

resource "aws_vpn_gateway_attachment" "this" {
vpc_id = var.network_info.vpc_id
vpn_gateway_id = aws_vpn_gateway.this.id
}

resource "aws_vpn_connection" "this" {
customer_gateway_id = aws_customer_gateway.customer_gateway.id
vpn_gateway_id = aws_vpn_gateway.this.id
type = "ipsec.1"

static_routes_only = true

tags = {
Name = "${var.deploy_id}-vpn-connection"
}
}

resource "aws_vpn_connection_route" "this" {
destination_cidr_block = var.vpn_connection.cidr_block
vpn_connection_id = aws_vpn_connection.this.id
}

locals {
route_table_ids = concat(var.network_info.route_tables.private, var.network_info.route_tables.pod)
}

resource "aws_vpn_gateway_route_propagation" "route_propagation" {
count = length(local.route_table_ids)
vpn_gateway_id = aws_vpn_gateway.this.id
route_table_id = local.route_table_ids[count.index]
}
14 changes: 14 additions & 0 deletions modules/infra/submodules/vpn/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
output "vpn_connection" {
description = "VPN connection information"
sensitive = true
value = {
ip_sec_tunnel_1 = {
address = aws_vpn_connection.this.tunnel1_address
preshared_key = aws_vpn_connection.this.tunnel1_preshared_key
}
ip_sec_tunnel_2 = {
address = aws_vpn_connection.this.tunnel2_address
preshared_key = aws_vpn_connection.this.tunnel2_preshared_key
}
}
}
87 changes: 87 additions & 0 deletions modules/infra/submodules/vpn/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
variable "deploy_id" {
type = string
description = "Domino Deployment ID"

validation {
condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id))
error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters."
}
}

variable "vpn_connection" {
description = <<EOF
shared_ip = Customer's shared IP Address.
cidr_block = CIDR block for the customer's network.
EOF
type = object({
shared_ip = string
cidr_block = string
})

validation {
condition = can(regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}$", var.vpn_connection.shared_ip))
error_message = "The 'shared_ip' must be a valid IP address."
}
validation {
condition = can(cidrhost(var.vpn_connection.cidr_block, 0))
error_message = "The 'cidr_block' must be a valid CIDR block."
}
}

variable "network_info" {
description = <<EOF
id = VPC ID.
subnets = {
public = List of public Subnets.
[{
name = Subnet name.
subnet_id = Subnet ud
az = Subnet availability_zone
az_id = Subnet availability_zone_id
}]
private = List of private Subnets.
[{
name = Subnet name.
subnet_id = Subnet ud
az = Subnet availability_zone
az_id = Subnet availability_zone_id
}]
pod = List of pod Subnets.
[{
name = Subnet name.
subnet_id = Subnet ud
az = Subnet availability_zone
az_id = Subnet availability_zone_id
}]
}
EOF
type = object({
vpc_id = string
route_tables = object({
public = optional(list(string))
private = optional(list(string))
pod = optional(list(string))
})
subnets = object({
public = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
private = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
pod = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
})
vpc_cidrs = string
})
}
9 changes: 9 additions & 0 deletions modules/infra/submodules/vpn/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
21 changes: 21 additions & 0 deletions modules/infra/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,24 @@ variable "use_fips_endpoint" {
type = bool
default = false
}

variable "vpn_connection" {
description = <<EOF
create = Create a VPN connection.
shared_ip = Customer's shared IP Address.
cidr_block = CIDR block for the customer's network.
EOF

type = object({
create = optional(bool, false)
shared_ip = optional(string, "")
cidr_block = optional(string, "")
})

default = {}

validation {
condition = !(var.vpn_connection.create) || (length(var.vpn_connection.shared_ip) >= 7 && length(var.vpn_connection.cidr_block) >= 7)
error_message = "When 'create' is true, both 'shared_ip' and 'cidr_block' must be a valid IPv4 IP."
}
}
1 change: 1 addition & 0 deletions tests/plan/terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
| <a name="input_storage"></a> [storage](#input\_storage) | storage = {<br> efs = {<br> access\_point\_path = Filesystem path for efs.<br> backup\_vault = {<br> create = Create backup vault for EFS toggle.<br> force\_destroy = Toggle to allow automatic destruction of all backups when destroying.<br> backup = {<br> schedule = Cron-style schedule for EFS backup vault (default: once a day at 12pm).<br> cold\_storage\_after = Move backup data to cold storage after this many days.<br> delete\_after = Delete backup data after this many days.<br> }<br> }<br> }<br> s3 = {<br> force\_destroy\_on\_deletion = Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets.<br> }<br> ecr = {<br> force\_destroy\_on\_deletion = Toogle to allow recursive deletion of all objects in the ECR repositories. if 'false' terraform will NOT be able to delete non-empty repositories.<br> }<br> }<br> } | <pre>object({<br> efs = optional(object({<br> access_point_path = optional(string, "/domino")<br> backup_vault = optional(object({<br> create = optional(bool, true)<br> force_destroy = optional(bool, true)<br> backup = optional(object({<br> schedule = optional(string, "0 12 * * ? *")<br> cold_storage_after = optional(number, 35)<br> delete_after = optional(number, 125)<br> }), {})<br> }), {})<br> }), {})<br> s3 = optional(object({<br> force_destroy_on_deletion = optional(bool, true)<br> }), {})<br> ecr = optional(object({<br> force_destroy_on_deletion = optional(bool, true)<br> }), {})<br> costs_enabled = optional(bool, true)<br> })</pre> | `{}` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no |
| <a name="input_use_fips_endpoint"></a> [use\_fips\_endpoint](#input\_use\_fips\_endpoint) | Use aws FIPS endpoints | `bool` | `false` | no |
| <a name="input_vpn_connection"></a> [vpn\_connection](#input\_vpn\_connection) | create = Create a VPN connection.<br> shared\_ip = Customer's shared IP Address.<br> cidr\_block = CIDR block for the customer's network. | <pre>object({<br> create = optional(bool, false)<br> shared_ip = optional(string, "")<br> cidr_block = optional(string, "")<br> })</pre> | `{}` | no |

## Outputs

Expand Down
1 change: 1 addition & 0 deletions tests/plan/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module "infra" {
tags = var.tags
domino_cur = var.domino_cur
use_fips_endpoint = var.use_fips_endpoint
vpn_connection = var.vpn_connection
}


Expand Down
17 changes: 17 additions & 0 deletions tests/plan/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,20 @@ variable "irsa_external_deployments_operator" {

default = {}
}


variable "vpn_connection" {
description = <<EOF
create = Create a VPN connection.
shared_ip = Customer's shared IP Address.
cidr_block = CIDR block for the customer's network.
EOF

type = object({
create = optional(bool, false)
shared_ip = optional(string, "")
cidr_block = optional(string, "")
})

default = {}
}

0 comments on commit 216bd85

Please sign in to comment.