From 6482f6b7445a41eaa80cba9f5ff4d5519dbf3a34 Mon Sep 17 00:00:00 2001 From: miguelhar <98769216+miguelhar@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:57:48 -0400 Subject: [PATCH] Miguelhar.plat-8802 (#266) --- examples/tfvars/vpn.tfvars | 18 +++++++--- modules/infra/README.md | 4 +-- modules/infra/main.tf | 10 +++--- modules/infra/outputs.tf | 4 +-- modules/infra/submodules/vpn/README.md | 4 +-- modules/infra/submodules/vpn/main.tf | 42 +++++++++++++++++------ modules/infra/submodules/vpn/outputs.tf | 25 ++++++++------ modules/infra/submodules/vpn/variables.tf | 35 +++++++++++++------ modules/infra/variables.tf | 22 ++++++------ tests/plan/terraform/README.md | 2 +- tests/plan/terraform/main.tf | 2 +- tests/plan/terraform/variables.tf | 17 +++++---- 12 files changed, 119 insertions(+), 66 deletions(-) diff --git a/examples/tfvars/vpn.tfvars b/examples/tfvars/vpn.tfvars index 23938dd5..cfe4bf88 100644 --- a/examples/tfvars/vpn.tfvars +++ b/examples/tfvars/vpn.tfvars @@ -14,8 +14,18 @@ default_node_groups = { } } -vpn_connection = { - create = true - shared_ip = "203.0.113.12" - cidr_block = "192.168.0.0/16" +vpn_connections = { + create = true + connections = [ + { + name = "vpn_connection_test_1" + shared_ip = "203.0.113.12" + cidr_blocks = ["192.168.0.0/16"] + }, + { + name = "vpn_connection_test_2" + shared_ip = "200.0.110.120" + cidr_blocks = ["3.4.5.6/16"] + } + ] } diff --git a/modules/infra/README.md b/modules/infra/README.md index d6b494e4..72cf60b2 100644 --- a/modules/infra/README.md +++ b/modules/infra/README.md @@ -67,7 +67,7 @@ | [storage](#input\_storage) | storage = {
filesystem\_type = File system type(netapp\|efs)
efs = {
access\_point\_path = Filesystem path for efs.
backup\_vault = {
create = Create backup vault for EFS toggle.
force\_destroy = Toggle to allow automatic destruction of all backups when destroying.
backup = {
schedule = Cron-style schedule for EFS backup vault (default: once a day at 12pm).
cold\_storage\_after = Move backup data to cold storage after this many days.
delete\_after = Delete backup data after this many days.
}
}
}
netapp = {
deployment\_type = netapp ontap deployment type,('MULTI\_AZ\_1', 'MULTI\_AZ\_2', 'SINGLE\_AZ\_1', 'SINGLE\_AZ\_2')
storage\_capacity = Filesystem Storage capacity
throughput\_capacity = Filesystem throughput capacity
automatic\_backup\_retention\_days = How many days to keep backups
daily\_automatic\_backup\_start\_time = Start time in 'HH:MM' format to initiate backups

storage\_capacity\_autosizing = Options for the FXN automatic storage capacity increase, cloudformation template
enabled = Enable automatic storage capacity increase.
threshold = Used storage capacity threshold.
percent\_capacity\_increase = The percentage increase in storage capacity when used storage exceeds
LowFreeDataStorageCapacityThreshold. Minimum increase is 10 %.
notification\_email\_address = The email address for alarm notification.
}))
}
s3 = {
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.
}
ecr = {
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.
}
enable\_remote\_backup = Enable tagging required for cross-account backups
costs\_enabled = Determines whether to provision domino cost related infrastructures, ie, long term storage
}
} |
object({
filesystem_type = optional(string, "efs")
efs = optional(object({
access_point_path = optional(string, "/domino")
backup_vault = optional(object({
create = optional(bool, true)
force_destroy = optional(bool, true)
backup = optional(object({
schedule = optional(string, "0 12 * * ? *")
cold_storage_after = optional(number, 35)
delete_after = optional(number, 125)
}), {})
}), {})
}), {})
netapp = optional(object({
deployment_type = optional(string, "SINGLE_AZ_1")
storage_capacity = optional(number, 1024)
throughput_capacity = optional(number, 128)
automatic_backup_retention_days = optional(number, 90)
daily_automatic_backup_start_time = optional(string, "00:00")
storage_capacity_autosizing = optional(object({
enabled = optional(bool, false)
threshold = optional(number, 70)
percent_capacity_increase = optional(number, 30)
notification_email_address = optional(string, "")
}), {})
}), {})
s3 = optional(object({
force_destroy_on_deletion = optional(bool, true)
}), {})
ecr = optional(object({
force_destroy_on_deletion = optional(bool, true)
}), {}),
enable_remote_backup = optional(bool, false)
costs_enabled = optional(bool, true)
})
| `{}` | no | | [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no | | [use\_fips\_endpoint](#input\_use\_fips\_endpoint) | Use aws FIPS endpoints | `bool` | `false` | no | -| [vpn\_connection](#input\_vpn\_connection) | create = Create a VPN connection.
shared\_ip = Customer's shared IP Address.
cidr\_block = CIDR block for the customer's network. |
object({
create = optional(bool, false)
shared_ip = optional(string, "")
cidr_block = optional(string, "")
})
| `{}` | no | +| [vpn\_connections](#input\_vpn\_connections) | create = Create a VPN connection.
connections = List of VPN connections, each with:
- name: Name for identification (optional).
- shared\_ip: Customer's shared IP Address (optional).
- cidr\_block: CIDR block for the customer's network (optional). |
object({
create = optional(bool, false)
connections = optional(list(object({
name = optional(string, "")
shared_ip = optional(string, "")
cidr_blocks = optional(list(string), [])
})), [])
})
| `{}` | no | ## Outputs @@ -91,5 +91,5 @@ | [ssh\_key](#output\_ssh\_key) | SSH key path,name. | | [storage](#output\_storage) | Storage details. | | [tags](#output\_tags) | Deployment tags. | -| [vpn\_connection](#output\_vpn\_connection) | VPN connection information | +| [vpn\_connections](#output\_vpn\_connections) | VPN connection information | diff --git a/modules/infra/main.tf b/modules/infra/main.tf index 4a1cfa5b..47754ad0 100644 --- a/modules/infra/main.tf +++ b/modules/infra/main.tf @@ -67,11 +67,11 @@ module "network" { } 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 + count = var.vpn_connections.create ? 1 : 0 + source = "./submodules/vpn" + deploy_id = var.deploy_id + network_info = module.network.info + vpn_connections = var.vpn_connections.connections } locals { diff --git a/modules/infra/outputs.tf b/modules/infra/outputs.tf index 0d651072..24affb89 100644 --- a/modules/infra/outputs.tf +++ b/modules/infra/outputs.tf @@ -88,7 +88,7 @@ output "cost_usage_report" { value = local.cost_usage_report_info } -output "vpn_connection" { +output "vpn_connections" { description = "VPN connection information" - value = var.vpn_connection.create ? module.vpn[0].vpn_connection : null + value = var.vpn_connections.create ? module.vpn[0].vpn_connections : null } diff --git a/modules/infra/submodules/vpn/README.md b/modules/infra/submodules/vpn/README.md index c92551da..fdaa4278 100644 --- a/modules/infra/submodules/vpn/README.md +++ b/modules/infra/submodules/vpn/README.md @@ -35,11 +35,11 @@ No modules. |------|-------------|------|---------|:--------:| | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [network\_info](#input\_network\_info) | 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
}]
} |
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
})
| n/a | yes | -| [vpn\_connection](#input\_vpn\_connection) | shared\_ip = Customer's shared IP Address.
cidr\_block = CIDR block for the customer's network. |
object({
shared_ip = string
cidr_block = string
})
| n/a | yes | +| [vpn\_connections](#input\_vpn\_connections) | List of VPN connections, each with:
- name: Name for identification
- shared\_ip: Customer's shared IP Address.
- cidr\_block: List of CIDR blocks for the customer's network. |
list(object({
name = string
shared_ip = string
cidr_blocks = list(string)
}))
| n/a | yes | ## Outputs | Name | Description | |------|-------------| -| [vpn\_connection](#output\_vpn\_connection) | VPN connection information | +| [vpn\_connections](#output\_vpn\_connections) | List of VPN connections information | diff --git a/modules/infra/submodules/vpn/main.tf b/modules/infra/submodules/vpn/main.tf index f94f00f0..e9fc71ce 100644 --- a/modules/infra/submodules/vpn/main.tf +++ b/modules/infra/submodules/vpn/main.tf @@ -1,8 +1,12 @@ - - resource "aws_customer_gateway" "customer_gateway" { - ip_address = var.vpn_connection.shared_ip + for_each = { for vpn in var.vpn_connections : vpn.name => vpn } + + ip_address = each.value.shared_ip type = "ipsec.1" + bgp_asn = "65000" + tags = { + Name = each.value.name + } } resource "aws_vpn_gateway" "this" { @@ -18,22 +22,40 @@ resource "aws_vpn_gateway_attachment" "this" { } resource "aws_vpn_connection" "this" { - customer_gateway_id = aws_customer_gateway.customer_gateway.id + for_each = aws_customer_gateway.customer_gateway + + customer_gateway_id = each.value.id vpn_gateway_id = aws_vpn_gateway.this.id type = "ipsec.1" - - static_routes_only = true - + static_routes_only = true tags = { - Name = "${var.deploy_id}-vpn-connection" + Name = "${each.key}-vpn-connection" } } +locals { + vpn_cidr_blocks = { + for vpn in var.vpn_connections : vpn.name => { + cidr_blocks = vpn.cidr_blocks + vpn_id = aws_vpn_connection.this[vpn.name].id + } + } + + flattened_vpn_cidr_block = merge([ + for vpn, data in local.vpn_cidr_blocks : { + for cidr in data.cidr_blocks : cidr => data.vpn_id + } + ]...) +} + resource "aws_vpn_connection_route" "this" { - destination_cidr_block = var.vpn_connection.cidr_block - vpn_connection_id = aws_vpn_connection.this.id + for_each = local.flattened_vpn_cidr_block + + destination_cidr_block = each.key + vpn_connection_id = each.value } + locals { route_table_ids = concat(var.network_info.route_tables.private, var.network_info.route_tables.pod) } diff --git a/modules/infra/submodules/vpn/outputs.tf b/modules/infra/submodules/vpn/outputs.tf index 06670b1e..40555eb3 100644 --- a/modules/infra/submodules/vpn/outputs.tf +++ b/modules/infra/submodules/vpn/outputs.tf @@ -1,14 +1,17 @@ -output "vpn_connection" { - description = "VPN connection information" +output "vpn_connections" { + description = "List of VPN connections information" sensitive = true - value = { - ip_sec_tunnel_1 = { - address = aws_vpn_connection.this.tunnel1_address - preshared_key = aws_vpn_connection.this.tunnel1_preshared_key + value = [ + for k, v in aws_vpn_connection.this : { + name = k + ip_sec_tunnel_1 = { + address = v.tunnel1_address + preshared_key = v.tunnel1_preshared_key + } + ip_sec_tunnel_2 = { + address = v.tunnel2_address + preshared_key = v.tunnel2_preshared_key + } } - ip_sec_tunnel_2 = { - address = aws_vpn_connection.this.tunnel2_address - preshared_key = aws_vpn_connection.this.tunnel2_preshared_key - } - } + ] } diff --git a/modules/infra/submodules/vpn/variables.tf b/modules/infra/submodules/vpn/variables.tf index 87f2e57f..574913f1 100644 --- a/modules/infra/submodules/vpn/variables.tf +++ b/modules/infra/submodules/vpn/variables.tf @@ -8,23 +8,36 @@ variable "deploy_id" { } } -variable "vpn_connection" { +variable "vpn_connections" { description = <= 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." - } } diff --git a/tests/plan/terraform/README.md b/tests/plan/terraform/README.md index 0f042858..c52c13cc 100644 --- a/tests/plan/terraform/README.md +++ b/tests/plan/terraform/README.md @@ -56,7 +56,7 @@ | [storage](#input\_storage) | storage = {
filesystem\_type = File system type(netapp\|efs)
efs = {
access\_point\_path = Filesystem path for efs.
backup\_vault = {
create = Create backup vault for EFS toggle.
force\_destroy = Toggle to allow automatic destruction of all backups when destroying.
backup = {
schedule = Cron-style schedule for EFS backup vault (default: once a day at 12pm).
cold\_storage\_after = Move backup data to cold storage after this many days.
delete\_after = Delete backup data after this many days.
}
}
}
netapp = {
deployment\_type = netapp ontap deployment type,('MULTI\_AZ\_1', 'MULTI\_AZ\_2', 'SINGLE\_AZ\_1', 'SINGLE\_AZ\_2')
storage\_capacity = Filesystem Storage capacity
throughput\_capacity = Filesystem throughput capacity
automatic\_backup\_retention\_days = How many days to keep backups
daily\_automatic\_backup\_start\_time = Start time in 'HH:MM' format to initiate backups

storage\_capacity\_autosizing = Options for the FXN automatic storage capacity increase, cloudformation template
enabled = Enable automatic storage capacity increase.
threshold = Used storage capacity threshold.
percent\_capacity\_increase = The percentage increase in storage capacity when used storage exceeds
LowFreeDataStorageCapacityThreshold. Minimum increase is 10 %.
notification\_email\_address = The email address for alarm notification.
}))
}
s3 = {
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.
}
ecr = {
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.
}
enable\_remote\_backup = Enable tagging required for cross-account backups
costs\_enabled = Determines whether to provision domino cost related infrastructures, ie, long term storage
}
} |
object({
filesystem_type = optional(string, "efs")
efs = optional(object({
access_point_path = optional(string, "/domino")
backup_vault = optional(object({
create = optional(bool, true)
force_destroy = optional(bool, true)
backup = optional(object({
schedule = optional(string, "0 12 * * ? *")
cold_storage_after = optional(number, 35)
delete_after = optional(number, 125)
}), {})
}), {})
}), {})
netapp = optional(object({
deployment_type = optional(string, "SINGLE_AZ_1")
storage_capacity = optional(number, 1024)
throughput_capacity = optional(number, 128)
automatic_backup_retention_days = optional(number, 90)
daily_automatic_backup_start_time = optional(string, "00:00")
storage_capacity_autosizing = optional(object({
enabled = optional(bool, false)
threshold = optional(number, 70)
percent_capacity_increase = optional(number, 30)
notification_email_address = optional(string, "")
}), {})
}), {})
s3 = optional(object({
force_destroy_on_deletion = optional(bool, true)
}), {})
ecr = optional(object({
force_destroy_on_deletion = optional(bool, true)
}), {}),
enable_remote_backup = optional(bool, false)
costs_enabled = optional(bool, true)
})
| `{}` | no | | [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no | | [use\_fips\_endpoint](#input\_use\_fips\_endpoint) | Use aws FIPS endpoints | `bool` | `false` | no | -| [vpn\_connection](#input\_vpn\_connection) | create = Create a VPN connection.
shared\_ip = Customer's shared IP Address.
cidr\_block = CIDR block for the customer's network. |
object({
create = optional(bool, false)
shared_ip = optional(string, "")
cidr_block = optional(string, "")
})
| `{}` | no | +| [vpn\_connections](#input\_vpn\_connections) | create = Create a VPN connection.
connections = List of VPN connections, each with:
- name: Name for identification (optional).
- shared\_ip: Customer's shared IP Address (optional).
- cidr\_block: CIDR block for the customer's network (optional). |
object({
create = optional(bool, false)
connections = optional(list(object({
name = optional(string, "")
shared_ip = optional(string, "")
cidr_blocks = optional(list(string), [])
})), [])
})
| `{}` | no | ## Outputs diff --git a/tests/plan/terraform/main.tf b/tests/plan/terraform/main.tf index 8f476547..388fcc4e 100644 --- a/tests/plan/terraform/main.tf +++ b/tests/plan/terraform/main.tf @@ -14,7 +14,7 @@ module "infra" { tags = var.tags domino_cur = var.domino_cur use_fips_endpoint = var.use_fips_endpoint - vpn_connection = var.vpn_connection + vpn_connections = var.vpn_connections } diff --git a/tests/plan/terraform/variables.tf b/tests/plan/terraform/variables.tf index da1556db..489ee938 100644 --- a/tests/plan/terraform/variables.tf +++ b/tests/plan/terraform/variables.tf @@ -496,17 +496,22 @@ variable "irsa_external_deployments_operator" { } -variable "vpn_connection" { +variable "vpn_connections" { description = <