diff --git a/apps-devstg/us-east-1/base-network/config.tf b/apps-devstg/us-east-1/base-network/config.tf index 806bdbd95..7f54f0233 100644 --- a/apps-devstg/us-east-1/base-network/config.tf +++ b/apps-devstg/us-east-1/base-network/config.tf @@ -54,38 +54,49 @@ data "terraform_remote_state" "tools-vpn-server" { } } -# -# data type from output for vpc -# -data "terraform_remote_state" "vpc-shared" { +# VPC remote states for network +data "terraform_remote_state" "network-vpcs" { + for_each = local.network-vpcs + backend = "s3" config = { - region = var.region - profile = "${var.project}-shared-devops" - bucket = "${var.project}-shared-terraform-backend" - key = "shared/network/terraform.tfstate" + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") } } -data "terraform_remote_state" "vpc-network" { +# VPC remote states for shared +data "terraform_remote_state" "shared-vpcs" { + + for_each = local.shared-vpcs + backend = "s3" config = { - region = var.region - profile = "${var.project}-network-devops" - bucket = "${var.project}-network-terraform-backend" - key = "network/network/terraform.tfstate" + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") } } -data "terraform_remote_state" "k8s-eks-demoapps" { +# VPC remote states for apps-devstg +data "terraform_remote_state" "apps-devstg-vpcs" { + + for_each = { + for k, v in local.apps-devstg-vpcs : + k => v if !v["tgw"] + } + backend = "s3" config = { - region = var.region - profile = "${var.project}-apps-devstg-devops" - bucket = "${var.project}-apps-devstg-terraform-backend" - key = "apps-devstg/k8s-eks-demoapps/network/terraform.tfstate" + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") } } diff --git a/apps-devstg/us-east-1/base-network/locals.tf b/apps-devstg/us-east-1/base-network/locals.tf index 3b8b19960..3d45a595d 100644 --- a/apps-devstg/us-east-1/base-network/locals.tf +++ b/apps-devstg/us-east-1/base-network/locals.tf @@ -55,6 +55,21 @@ locals { } locals { + # private inbounds + private_inbound = flatten([ + for index, state in local.datasources-vpcs : [ + for k, v in state.outputs.private_subnets_cidr : + { + rule_number = 10 * (index(keys(local.datasources-vpcs), index) + 1) + 100 * k + rule_action = "allow" + from_port = 0 + to_port = 65535 + protocol = "all" + cidr_block = state.outputs.private_subnets_cidr[k] + } + ] + ]) + network_acls = { # # Allow / Deny VPC private subnets inbound default traffic @@ -69,7 +84,15 @@ locals { cidr_block = local.private_subnets_cidr[0] }, { - rule_number = 900 # NTP traffic + rule_number = 900 # shared pritunl vpn server + rule_action = "allow" + from_port = 0 + to_port = 65535 + protocol = "all" + cidr_block = "${data.terraform_remote_state.tools-vpn-server.outputs.instance_private_ip}/32" + }, + { + rule_number = 910 # NTP traffic rule_action = "allow" from_port = 123 to_port = 123 @@ -77,18 +100,18 @@ locals { cidr_block = "0.0.0.0/0" }, { - rule_number = 910 # Fltering known TCP ports (0-1024) + rule_number = 920 # Fltering known TCP ports (0-1024) rule_action = "allow" from_port = 1024 - to_port = 65535 + to_port = 65525 protocol = "tcp" cidr_block = "0.0.0.0/0" }, { - rule_number = 920 # Fltering known UDP ports (0-1024) + rule_number = 930 # Fltering known UDP ports (0-1024) rule_action = "allow" from_port = 1024 - to_port = 65535 + to_port = 65525 protocol = "udp" cidr_block = "0.0.0.0/0" }, @@ -97,23 +120,75 @@ locals { # # Allow VPC private subnets inbound traffic # - private_inbound = [ - { - rule_number = 100 # shared pritunl vpn server - rule_action = "allow" - from_port = 0 - to_port = 65535 - protocol = "all" - cidr_block = "${data.terraform_remote_state.tools-vpn-server.outputs.instance_private_ip}/32" - }, - { - rule_number = 110 # shared private subnets - rule_action = "allow" - from_port = 0 - to_port = 65535 - protocol = "all" - cidr_block = data.terraform_remote_state.vpc-shared.outputs.private_subnets_cidr[0] - } - ] + private_inbound = local.private_inbound + } + + # + # Data source definitions + # + + ######### + # NACLs # + ######### + + # shared + shared-vpcs = { + shared-base = { + region = var.region + profile = "${var.project}-shared-devops" + bucket = "${var.project}-shared-terraform-backend" + key = "shared/network/terraform.tfstate" + } + } + + # network + network-vpcs = { + network-base = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network/terraform.tfstate" + } + network-firewall = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network-firewall/terraform.tfstate" + } } + + datasources-vpcs = merge( + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.shared-vpcs, # shared + ) + + ################ + # VPC Peerings # + ################ + + # apps-devstg + apps-devstg-vpcs = { + apps-devstg-base = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/network/terraform.tfstate" + tgw = false + } + apps-devstg-k8s-eks = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/k8s-eks/network/terraform.tfstate" + tgw = false + } + apps-devstg-k8s-eks-demoapps = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/k8s-eks-demoapps/network/terraform.tfstate" + tgw = false + } + } + } diff --git a/apps-devstg/us-east-1/base-network/network.tf b/apps-devstg/us-east-1/base-network/network.tf index 3aa189f63..88644c4e5 100644 --- a/apps-devstg/us-east-1/base-network/network.tf +++ b/apps-devstg/us-east-1/base-network/network.tf @@ -1,8 +1,8 @@ # -# Network Resources +# VPC # module "vpc" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v2.71.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -11,16 +11,15 @@ module "vpc" { private_subnets = local.private_subnets public_subnets = local.public_subnets - enable_nat_gateway = var.vpc_enable_nat_gateway - single_nat_gateway = var.vpc_single_nat_gateway - enable_dns_hostnames = var.vpc_enable_dns_hostnames - enable_vpn_gateway = var.vpc_enable_vpn_gateway - enable_s3_endpoint = var.vpc_enable_s3_endpoint - enable_dynamodb_endpoint = var.vpc_enable_dynamodb_endpoint + enable_nat_gateway = var.vpc_enable_nat_gateway + single_nat_gateway = var.vpc_single_nat_gateway + enable_dns_hostnames = var.vpc_enable_dns_hostnames + enable_vpn_gateway = var.vpc_enable_vpn_gateway + # Use a custom network ACL rules for private and public subnets manage_default_network_acl = false - public_dedicated_network_acl = true // use dedicated network ACL for the public subnets. - private_dedicated_network_acl = true // use dedicated network ACL for the private subnets. + public_dedicated_network_acl = true + private_dedicated_network_acl = true private_inbound_acl_rules = concat( local.network_acls["default_inbound"], local.network_acls["private_inbound"], @@ -30,3 +29,74 @@ module "vpc" { private_subnet_tags = local.private_subnet_tags tags = local.tags } + +# VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} + +module "vpc_endpoints" { + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" + + for_each = local.vpc_endpoints + + vpc_id = module.vpc.vpc_id + + endpoints = { + endpoint = merge(each.value, + { + route_table_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + } + ) + } + + tags = local.tags +} + +# +# KMS VPC Endpoint: Security Group +# +resource "aws_security_group" "kms_vpce" { + count = var.enable_kms_endpoint ? 1 : 0 + name = "kms_vpce" + description = "Allow TLS inbound traffic" + vpc_id = module.vpc.vpc_id + + ingress { + description = "TLS from VPC" + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [local.vpc_cidr_block] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = local.tags +} diff --git a/apps-devstg/us-east-1/base-network/network_vpc_peering_accepters.tf b/apps-devstg/us-east-1/base-network/network_vpc_peering_accepters.tf deleted file mode 100644 index 1c26d87a1..000000000 --- a/apps-devstg/us-east-1/base-network/network_vpc_peering_accepters.tf +++ /dev/null @@ -1,29 +0,0 @@ -# -# VPC Peering Connection - Accepter Side -# -resource "aws_vpc_peering_connection_accepter" "eks_demoapps" { - vpc_peering_connection_id = data.terraform_remote_state.k8s-eks-demoapps.outputs.vpc_peering_id_with_devstg - auto_accept = true - - tags = merge(tomap({ "Name" = "accepter-devstg-from-eks-demoapps" }), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Both private and public subnets traffic will be routed and permitted through VPC Peerings (filtered by Private Inbound NACLs) -# If stryctly needed private subnets must be exposed via Load Balancers (NLBs || ALBs) -# reducing public IPs exposure whenever possible. -# read more: https://github.com/binbashar/le-tf-infra-aws/issues/49 -# -resource "aws_route" "priv_route_table_to_apps_devstg_eks_demoapps" { - route_table_id = element(module.vpc.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.k8s-eks-demoapps.outputs.vpc_cidr_block - vpc_peering_connection_id = data.terraform_remote_state.k8s-eks-demoapps.outputs.vpc_peering_id_with_devstg -} - -resource "aws_route" "pub_route_table_to_apps_devstg_eks_demoapps" { - route_table_id = element(module.vpc.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.k8s-eks-demoapps.outputs.vpc_cidr_block - vpc_peering_connection_id = data.terraform_remote_state.k8s-eks-demoapps.outputs.vpc_peering_id_with_devstg -} diff --git a/apps-devstg/us-east-1/base-network/network_vpc_peering_requester_apps_dev_to_shared.tf b/apps-devstg/us-east-1/base-network/network_vpc_peering_requester_apps_dev_to_shared.tf deleted file mode 100644 index 23d1832a6..000000000 --- a/apps-devstg/us-east-1/base-network/network_vpc_peering_requester_apps_dev_to_shared.tf +++ /dev/null @@ -1,44 +0,0 @@ -# -# VPC Peering Connection with Share: Requester Side -# -# Consider 'destination_cidr_block' parameter will be the CIDR of the remote VPC/Subnets (originator of the VPC -# peering request) and 'route_table_id' the route table ID to add the destination route to. -# - -# -# VPC Apps Dev w/ Shared -# -resource "aws_vpc_peering_connection" "apps_devstg_vpc_with_shared_vpc" { - count = var.vpc_shared_created == true ? 1 : 0 - - peer_owner_id = var.shared_account_id - peer_vpc_id = data.terraform_remote_state.vpc-shared.outputs.vpc_id - vpc_id = module.vpc.vpc_id - auto_accept = false - - tags = merge(map("Name", "requester-apps-dev-to-shared"), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Both private and public subnets traffic will be routed and permitted through VPC Peerings (filtered by Private Inbound NACLs) -# If stryctly needed private subnets must be exposed via Load Balancers (NLBs || ALBs) -# reducing public IPs exposure whenever possible. -# read more: https://github.com/binbashar/le-tf-infra-aws/issues/49 -# -resource "aws_route" "priv_route_table_1_apps_devstg_vpc_to_shared_vpc" { - count = var.vpc_shared_created == true ? 1 : 0 - - route_table_id = element(module.vpc.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.vpc-shared.outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_vpc_with_shared_vpc[0].id -} - -resource "aws_route" "pub_route_table_1_apps_devstg_vpc_to_shared_vpc" { - count = var.vpc_shared_created == true ? 1 : 0 - - route_table_id = element(module.vpc.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.vpc-shared.outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_vpc_with_shared_vpc[0].id -} diff --git a/apps-devstg/us-east-1/base-network/outputs.tf b/apps-devstg/us-east-1/base-network/outputs.tf index 0e01d187f..94bb7c0a9 100644 --- a/apps-devstg/us-east-1/base-network/outputs.tf +++ b/apps-devstg/us-east-1/base-network/outputs.tf @@ -54,8 +54,3 @@ output "private_route_table_ids" { description = "List of IDs of private route tables" value = module.vpc.private_route_table_ids } - -output "vpc_peering_id_with_shared" { - description = "VPC peering ID with shared" - value = join("", try(aws_vpc_peering_connection.apps_devstg_vpc_with_shared_vpc[*].id, null)) -} diff --git a/apps-devstg/us-east-1/base-network/variables.tf b/apps-devstg/us-east-1/base-network/variables.tf index 867d0017b..905a9df68 100644 --- a/apps-devstg/us-east-1/base-network/variables.tf +++ b/apps-devstg/us-east-1/base-network/variables.tf @@ -134,16 +134,16 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_enable_s3_endpoint" { - description = "Enable S3 endpoint" +variable "enable_kms_endpoint" { + description = "Enable KMS endpoint" type = bool - default = true + default = false } -variable "vpc_enable_dynamodb_endpoint" { - description = "Enable DynamoDB endpoint" +variable "enable_kms_endpoint_private_dns" { + description = "Enable KMS endpoint" type = bool - default = true + default = false } variable "enable_tgw" { diff --git a/apps-devstg/us-east-1/base-network/vpc_peerings.tf b/apps-devstg/us-east-1/base-network/vpc_peerings.tf new file mode 100644 index 000000000..e45757779 --- /dev/null +++ b/apps-devstg/us-east-1/base-network/vpc_peerings.tf @@ -0,0 +1,32 @@ +# +# VPC Peering: apps-devstg base VPC => eks clusters VPC +module "vpc_peering_apps_devstg_to_eks_clusters" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.apps-devstg-vpcs : + k => v if !v["tgw"] && k != "apps-devstg-base" # No peerings when TGW enabled or against the base network + } + + providers = { + aws.this = aws + aws.peer = aws + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-devstg-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.apps-devstg-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-devstg-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "apps-devstg-to-${each.key}", + "PeeringRequester" = each.key, + "PeeringAccepter" = "apps-devstg" + }) +} diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/build.env b/apps-devstg/us-east-1/k8s-eks-demoapps/network/build.env deleted file mode 100644 index 030267261..000000000 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/build.env +++ /dev/null @@ -1 +0,0 @@ -TERRAFORM_IMAGE_TAG=0.14.4 diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/config.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/config.tf index 7b3e99b8d..4c372f5c5 100644 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/config.tf +++ b/apps-devstg/us-east-1/k8s-eks-demoapps/network/config.tf @@ -29,49 +29,79 @@ terraform { } } +#=============================# +# Data sources # +#=============================# + # -# Data sources +# data type from output for tools-ec2 # -data "terraform_remote_state" "devstg-vpc" { +data "terraform_remote_state" "tools-vpn-server" { backend = "s3" config = { region = var.region - profile = "${var.project}-apps-devstg-devops" - bucket = "${var.project}-apps-devstg-terraform-backend" - key = "apps-devstg/network/terraform.tfstate" + profile = "${var.project}-shared-devops" + bucket = "${var.project}-shared-terraform-backend" + key = "shared/vpn/terraform.tfstate" } } +# +# VPC remote states for network +data "terraform_remote_state" "network-vpcs" { + for_each = local.network-vpcs -data "terraform_remote_state" "shared-vpc" { backend = "s3" config = { - region = var.region - profile = "${var.project}-shared-devops" - bucket = "${var.project}-shared-terraform-backend" - key = "shared/network/terraform.tfstate" + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") } } -data "terraform_remote_state" "shared-dns" { +# VPC remote states for shared +data "terraform_remote_state" "shared-vpcs" { + + for_each = local.shared-vpcs + backend = "s3" config = { - region = var.region - profile = "${var.project}-shared-devops" - bucket = "${var.project}-shared-terraform-backend" - key = "shared/dns/binbash.com.ar/terraform.tfstate" + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") } } -data "terraform_remote_state" "tools-vpn-server" { +# VPC remote states for apps-devstg +data "terraform_remote_state" "apps-devstg-vpcs" { + + for_each = { + for k, v in local.apps-devstg-vpcs : + k => v if !v["tgw"] + } + + backend = "s3" + + config = { + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") + } +} + + +data "terraform_remote_state" "shared-dns" { backend = "s3" config = { region = var.region profile = "${var.project}-shared-devops" bucket = "${var.project}-shared-terraform-backend" - key = "shared/vpn/terraform.tfstate" + key = "shared/dns/binbash.com.ar/terraform.tfstate" } } diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/locals.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/locals.tf index fed950344..b592a23a5 100644 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/locals.tf +++ b/apps-devstg/us-east-1/k8s-eks-demoapps/network/locals.tf @@ -49,81 +49,140 @@ locals { } locals { - network_acls = { - # - # Allow / Deny VPC private subnets inbound default traffic - # - default_inbound = [ - { - rule_number = 900 # Allow NTP - rule_action = "allow" - from_port = 123 - to_port = 123 - protocol = "udp" - cidr_block = "0.0.0.0/0" - }, - { - rule_number = 910 # Do not allow TCP low ports (0-1024) - rule_action = "allow" - from_port = 1024 - to_port = 65535 - protocol = "tcp" - cidr_block = "0.0.0.0/0" - }, + # private inbounds + private_inbound = flatten([ + for index, state in local.datasources-vpcs : [ + for k, v in state.outputs.private_subnets_cidr : { - rule_number = 920 # Do now allow UDP low ports (0-1024) + rule_number = 10 * (index(keys(local.datasources-vpcs), index) + 1) + 100 * k rule_action = "allow" - from_port = 1024 + from_port = 0 to_port = 65535 - protocol = "udp" - cidr_block = "0.0.0.0/0" - }, + protocol = "all" + cidr_block = state.outputs.private_subnets_cidr[k] + } ] + ]) + network_acls = { # - # Allow VPC private subnets inbound traffic + # Allow / Deny VPC private subnets inbound default traffic # - private_inbound = [ + default_inbound = [ { - rule_number = 100 # Allow traffic from Pritunl VPN server + rule_number = 800 # own private subnet cidr rule_action = "allow" from_port = 0 to_port = 65535 protocol = "all" - cidr_block = "${data.terraform_remote_state.tools-vpn-server.outputs.instance_private_ip}/32" + cidr_block = local.private_subnets_cidr[0] }, { - rule_number = 110 # Allow traffic from Shared private subnets + rule_number = 900 # shared pritunl vpn server rule_action = "allow" from_port = 0 to_port = 65535 protocol = "all" - cidr_block = data.terraform_remote_state.shared-vpc.outputs.private_subnets_cidr[0] + cidr_block = "${data.terraform_remote_state.tools-vpn-server.outputs.instance_private_ip}/32" }, { - rule_number = 200 # Allow traffic from EKS DemoApps VPC private subnets + rule_number = 910 # NTP traffic rule_action = "allow" - from_port = 0 - to_port = 65535 - protocol = "all" - cidr_block = local.private_subnets_cidr[0] + from_port = 123 + to_port = 123 + protocol = "udp" + cidr_block = "0.0.0.0/0" }, { - rule_number = 250 # Allow traffic from DevStg VPC private subnets + rule_number = 920 # Fltering known TCP ports (0-1024) rule_action = "allow" - from_port = 0 - to_port = 65535 - protocol = "all" - cidr_block = data.terraform_remote_state.devstg-vpc.outputs.private_subnets_cidr[0] + from_port = 1024 + to_port = 65525 + protocol = "tcp" + cidr_block = "0.0.0.0/0" }, { - rule_number = 300 # vault hvn vpc + rule_number = 930 # Fltering known UDP ports (0-1024) rule_action = "allow" - from_port = 0 - to_port = 65535 - protocol = "all" - cidr_block = var.vpc_vault_hvn_cird + from_port = 1024 + to_port = 65525 + protocol = "udp" + cidr_block = "0.0.0.0/0" }, ] + + # + # Allow VPC private subnets inbound traffic + # + private_inbound = local.private_inbound + } + + # + # Data source definitions + # + + ######### + # NACLs # + ######### + + # shared + shared-vpcs = { + shared-base = { + region = var.region + profile = "${var.project}-shared-devops" + bucket = "${var.project}-shared-terraform-backend" + key = "shared/network/terraform.tfstate" + } + } + + # network + network-vpcs = { + network-base = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network/terraform.tfstate" + } + network-firewall = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network-firewall/terraform.tfstate" + } + } + + datasources-vpcs = merge( + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.shared-vpcs, # shared + ) + + ################ + # VPC Peerings # + ################ + + # apps-devstg + apps-devstg-vpcs = { + apps-devstg-base = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/network/terraform.tfstate" + tgw = false + } + apps-devstg-k8s-eks = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/k8s-eks/network/terraform.tfstate" + tgw = false + } + apps-devstg-k8s-eks-demoapps = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/k8s-eks-demoapps/network/terraform.tfstate" + tgw = false + } } + } diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/network.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/network.tf index 3bef7167f..2a56602f5 100644 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/network.tf +++ b/apps-devstg/us-east-1/k8s-eks-demoapps/network/network.tf @@ -2,7 +2,7 @@ # EKS VPC # module "vpc-eks" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -30,11 +30,37 @@ module "vpc-eks" { tags = local.tags } +# VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} + # VPC Endpoints module "vpc_endpoints" { - source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" - for_each = var.vpc_endpoints + for_each = local.vpc_endpoints vpc_id = module.vpc-eks.vpc_id @@ -48,3 +74,31 @@ module "vpc_endpoints" { tags = local.tags } + +# +# +# KMS VPC Endpoint: Security Group +# +resource "aws_security_group" "kms_vpce" { + count = var.enable_kms_endpoint ? 1 : 0 + name = "kms_vpce" + description = "Allow TLS inbound traffic" + vpc_id = module.vpc-eks.vpc_id + + ingress { + description = "TLS from VPC" + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [local.vpc_cidr_block] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = local.tags +} diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/outputs.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/outputs.tf index f5116c0ad..a80977b32 100644 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/outputs.tf +++ b/apps-devstg/us-east-1/k8s-eks-demoapps/network/outputs.tf @@ -62,19 +62,3 @@ output "private_route_table_ids" { description = "List of IDs of private route tables" value = module.vpc-eks.private_route_table_ids } - -# TODO: Deprecate this output -output "vpc_peering_id_apps_devstg_eks_demoapps_with_shared" { - description = "VPC peering ID with shared" - value = var.vpc_apps_devstg_eks_created == true ? join("", aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[*].id) : null -} - -output "vpc_peering_id_with_shared" { - description = "VPC peering ID with shared" - value = var.vpc_apps_devstg_eks_created == true ? join("", aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[*].id) : null -} - -output "vpc_peering_id_with_devstg" { - description = "VPC peering ID with devstg" - value = var.vpc_apps_devstg_eks_created == true ? join("", aws_vpc_peering_connection.apps_devstg_eks_vpc_with_devstg_vpc[*].id) : null -} diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/variables.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/variables.tf index d9d5f7c96..fdc2c4f43 100644 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/variables.tf +++ b/apps-devstg/us-east-1/k8s-eks-demoapps/network/variables.tf @@ -155,17 +155,20 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_endpoints" { - description = "VPC endpoints" - type = any - default = { - s3 = { - service = "s3" - service_type = "Gateway" - } - dynamodb = { - service = "dynamodb" - service_type = "Gateway" - } - } +variable "enable_kms_endpoint" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_kms_endpoint_private_dns" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_tgw" { + description = "Enable Transit Gateway Support" + type = bool + default = false } diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/vpc_peering_requester_with_devstg.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/vpc_peering_requester_with_devstg.tf deleted file mode 100644 index eebd08b44..000000000 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/vpc_peering_requester_with_devstg.tf +++ /dev/null @@ -1,37 +0,0 @@ -# -# Create a VPC Peering between (Apps DevStg) EKS VPC and Shared VPC -# -resource "aws_vpc_peering_connection" "apps_devstg_eks_vpc_with_devstg_vpc" { - count = var.vpc_apps_devstg_eks_created == true ? 1 : 0 - - peer_owner_id = var.appsdevstg_account_id - peer_vpc_id = data.terraform_remote_state.devstg-vpc.outputs.vpc_id - vpc_id = module.vpc-eks.vpc_id - auto_accept = false - - tags = merge(tomap({ "Name" = "requester-apps-devstg-eks-demoapps-to-devstg" }), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Keep in mind that this will allow both private and public subnets traffic to -# be routed through the VPC Peering. However Network ACLs rules will block -# traffic from public subnets so, in order to have network connectivity to the -# cluster, you will have to implement other options (e.g. load balancers). -# -resource "aws_route" "priv_route_table_1_apps_devstg_eks_vpc_to_devstg_vpc" { - count = var.vpc_apps_devstg_eks_created == true ? 1 : 0 - - route_table_id = element(module.vpc-eks.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.devstg-vpc.outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_devstg_vpc[0].id -} - -resource "aws_route" "pub_route_table_1_apps_devstg_eks_vpc_to_devstg_vpc" { - count = var.vpc_apps_devstg_eks_created == true ? 1 : 0 - - route_table_id = element(module.vpc-eks.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.devstg-vpc.outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_devstg_vpc[0].id -} diff --git a/apps-devstg/us-east-1/k8s-eks-demoapps/network/vpc_peering_requester_with_shared.tf b/apps-devstg/us-east-1/k8s-eks-demoapps/network/vpc_peering_requester_with_shared.tf deleted file mode 100644 index 8a6c71a5e..000000000 --- a/apps-devstg/us-east-1/k8s-eks-demoapps/network/vpc_peering_requester_with_shared.tf +++ /dev/null @@ -1,37 +0,0 @@ -# -# Create a VPC Peering between (Apps DevStg) EKS VPC and Shared VPC -# -resource "aws_vpc_peering_connection" "apps_devstg_eks_vpc_with_shared_vpc" { - count = var.vpc_apps_devstg_eks_created == true ? 1 : 0 - - peer_owner_id = var.shared_account_id - peer_vpc_id = data.terraform_remote_state.shared-vpc.outputs.vpc_id - vpc_id = module.vpc-eks.vpc_id - auto_accept = false - - tags = merge(tomap({ "Name" = "requester-apps-devstg-eks-demoapps-to-shared" }), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Keep in mind that this will allow both private and public subnets traffic to -# be routed through the VPC Peering. However Network ACLs rules will block -# traffic from public subnets so, in order to have network connectivity to the -# cluster, you will have to implement other options (e.g. load balancers). -# -resource "aws_route" "priv_route_table_1_apps_devstg_eks_vpc_to_shared_vpc" { - count = var.vpc_apps_devstg_eks_created == true ? 1 : 0 - - route_table_id = element(module.vpc-eks.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpc.outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[0].id -} - -resource "aws_route" "pub_route_table_1_apps_devstg_eks_vpc_to_shared_vpc" { - count = var.vpc_apps_devstg_eks_created == true ? 1 : 0 - - route_table_id = element(module.vpc-eks.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpc.outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[0].id -} diff --git a/apps-devstg/us-east-1/k8s-eks/network/locals.tf b/apps-devstg/us-east-1/k8s-eks/network/locals.tf index aea16fd33..61277247b 100644 --- a/apps-devstg/us-east-1/k8s-eks/network/locals.tf +++ b/apps-devstg/us-east-1/k8s-eks/network/locals.tf @@ -49,7 +49,6 @@ locals { } locals { - # private inbounds private_inbound = flatten([ for index, state in local.datasources-vpcs : [ @@ -121,6 +120,10 @@ locals { # Data source definitions # + ######### + # NACLs # + ######### + # shared shared-vpcs = { shared-base = { @@ -139,10 +142,46 @@ locals { bucket = "${var.project}-network-terraform-backend" key = "network/network/terraform.tfstate" } + network-firewall = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network-firewall/terraform.tfstate" + } } datasources-vpcs = merge( - data.terraform_remote_state.network-vpcs, # network - data.terraform_remote_state.shared-vpcs, # shared + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.shared-vpcs, # shared ) + + ################ + # VPC Peerings # + ################ + + # apps-devstg + apps-devstg-vpcs = { + apps-devstg-base = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/network/terraform.tfstate" + tgw = false + } + apps-devstg-k8s-eks = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/k8s-eks/network/terraform.tfstate" + tgw = false + } + apps-devstg-k8s-eks-demoapps = { + region = var.region + profile = "${var.project}-apps-devstg-devops" + bucket = "${var.project}-apps-devstg-terraform-backend" + key = "apps-devstg/k8s-eks-demoapps/network/terraform.tfstate" + tgw = false + } + } + } diff --git a/apps-devstg/us-east-1/k8s-eks/network/network.tf b/apps-devstg/us-east-1/k8s-eks/network/network.tf index 3bef7167f..e6b6994f0 100644 --- a/apps-devstg/us-east-1/k8s-eks/network/network.tf +++ b/apps-devstg/us-east-1/k8s-eks/network/network.tf @@ -2,7 +2,7 @@ # EKS VPC # module "vpc-eks" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -31,10 +31,34 @@ module "vpc-eks" { } # VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} module "vpc_endpoints" { - source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" - for_each = var.vpc_endpoints + for_each = local.vpc_endpoints vpc_id = module.vpc-eks.vpc_id @@ -48,3 +72,30 @@ module "vpc_endpoints" { tags = local.tags } + +# +# KMS VPC Endpoint: Security Group +# +resource "aws_security_group" "kms_vpce" { + count = var.enable_kms_endpoint ? 1 : 0 + name = "kms_vpce" + description = "Allow TLS inbound traffic" + vpc_id = module.vpc-eks.vpc_id + + ingress { + description = "TLS from VPC" + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [local.vpc_cidr_block] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = local.tags +} diff --git a/apps-devstg/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf b/apps-devstg/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf index 89d28bd7b..23c5ba175 100644 --- a/apps-devstg/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf +++ b/apps-devstg/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf @@ -7,7 +7,7 @@ resource "aws_vpc_peering_connection_accepter" "with_vault_hvn" { vpc_peering_connection_id = var.vpc_vault_hvn_peering_connection_id auto_accept = true - tags = merge(map("Name", "accepter-shared-from-vault-hvn"), local.tags) + tags = merge({ Name = "accepter-shared-from-vault-hvn" }, local.tags) } # diff --git a/apps-devstg/us-east-1/k8s-eks/network/outputs.tf b/apps-devstg/us-east-1/k8s-eks/network/outputs.tf index dcf696ddc..a80977b32 100644 --- a/apps-devstg/us-east-1/k8s-eks/network/outputs.tf +++ b/apps-devstg/us-east-1/k8s-eks/network/outputs.tf @@ -62,8 +62,3 @@ output "private_route_table_ids" { description = "List of IDs of private route tables" value = module.vpc-eks.private_route_table_ids } - -output "vpc_peering_id_with_shared" { - description = "VPC peering ID with shared" - value = join("", try(aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[*].id, null)) -} diff --git a/apps-devstg/us-east-1/k8s-eks/network/variables.tf b/apps-devstg/us-east-1/k8s-eks/network/variables.tf index 8758cae2c..845c5d5e5 100644 --- a/apps-devstg/us-east-1/k8s-eks/network/variables.tf +++ b/apps-devstg/us-east-1/k8s-eks/network/variables.tf @@ -155,17 +155,20 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_endpoints" { - description = "VPC endpoints" - type = any - default = { - s3 = { - service = "s3" - service_type = "Gateway" - } - dynamodb = { - service = "dynamodb" - service_type = "Gateway" - } - } +variable "enable_kms_endpoint" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_kms_endpoint_private_dns" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_tgw" { + description = "Enable Transit Gateway Support" + type = bool + default = false } diff --git a/apps-devstg/us-east-1/k8s-eks/network/vpc_peering_requester_with_shared.tf b/apps-devstg/us-east-1/k8s-eks/network/vpc_peering_requester_with_shared.tf deleted file mode 100644 index 3390a8335..000000000 --- a/apps-devstg/us-east-1/k8s-eks/network/vpc_peering_requester_with_shared.tf +++ /dev/null @@ -1,37 +0,0 @@ -# -# Create a VPC Peering between (Apps DevStg) EKS VPC and Shared VPC -# -resource "aws_vpc_peering_connection" "apps_devstg_eks_vpc_with_shared_vpc" { - count = var.vpc_shared_created && !data.terraform_remote_state.network-vpcs["network-base"].outputs.enable_tgw ? 1 : 0 - - peer_owner_id = var.shared_account_id - peer_vpc_id = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_id - vpc_id = module.vpc-eks.vpc_id - auto_accept = false - - tags = merge(map("Name", "requester-apps-devstg-eks-to-shared"), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Keep in mind that this will allow both private and public subnets traffic to -# be routed through the VPC Peering. However Network ACLs rules will block -# traffic from public subnets so, in order to have network connectivity to the -# cluster, you will have to implement other options (e.g. load balancers). -# -resource "aws_route" "priv_route_table_1_apps_devstg_eks_vpc_to_shared_vpc" { - count = var.vpc_shared_created && !data.terraform_remote_state.network-vpcs["network-base"].outputs.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc-eks.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[0].id -} - -resource "aws_route" "pub_route_table_1_apps_devstg_eks_vpc_to_shared_vpc" { - count = var.vpc_shared_created && !data.terraform_remote_state.network-vpcs["network-base"].outputs.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc-eks.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[0].id -} diff --git a/apps-devstg/us-east-2/k8s-eks/network/locals.tf b/apps-devstg/us-east-2/k8s-eks/network/locals.tf index 3222a1f16..158db4c9e 100644 --- a/apps-devstg/us-east-2/k8s-eks/network/locals.tf +++ b/apps-devstg/us-east-2/k8s-eks/network/locals.tf @@ -149,7 +149,7 @@ locals { # Data Sources # datasources-vpcs = merge( - data.terraform_remote_state.network-vpcs, # network - data.terraform_remote_state.shared-vpcs, # shared + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.shared-vpcs, # shared ) } diff --git a/apps-devstg/us-east-2/k8s-eks/network/network.tf b/apps-devstg/us-east-2/k8s-eks/network/network.tf index 9857d23db..38a3eb038 100644 --- a/apps-devstg/us-east-2/k8s-eks/network/network.tf +++ b/apps-devstg/us-east-2/k8s-eks/network/network.tf @@ -2,7 +2,7 @@ # EKS VPC # module "vpc-eks" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.7.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -30,11 +30,37 @@ module "vpc-eks" { tags = local.tags } +# VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} + # VPC Endpoints module "vpc_endpoints" { - source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" - for_each = var.vpc_endpoints + for_each = local.vpc_endpoints vpc_id = module.vpc-eks.vpc_id @@ -48,3 +74,30 @@ module "vpc_endpoints" { tags = local.tags } + +# +# KMS VPC Endpoint: Security Group +# +resource "aws_security_group" "kms_vpce" { + count = var.enable_kms_endpoint ? 1 : 0 + name = "kms_vpce" + description = "Allow TLS inbound traffic" + vpc_id = module.vpc-eks.vpc_id + + ingress { + description = "TLS from VPC" + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [local.vpc_cidr_block] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = local.tags +} diff --git a/apps-devstg/us-east-2/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf b/apps-devstg/us-east-2/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf index 89d28bd7b..23c5ba175 100644 --- a/apps-devstg/us-east-2/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf +++ b/apps-devstg/us-east-2/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf @@ -7,7 +7,7 @@ resource "aws_vpc_peering_connection_accepter" "with_vault_hvn" { vpc_peering_connection_id = var.vpc_vault_hvn_peering_connection_id auto_accept = true - tags = merge(map("Name", "accepter-shared-from-vault-hvn"), local.tags) + tags = merge({ Name = "accepter-shared-from-vault-hvn" }, local.tags) } # diff --git a/apps-devstg/us-east-2/k8s-eks/network/outputs.tf b/apps-devstg/us-east-2/k8s-eks/network/outputs.tf index dcf696ddc..a80977b32 100644 --- a/apps-devstg/us-east-2/k8s-eks/network/outputs.tf +++ b/apps-devstg/us-east-2/k8s-eks/network/outputs.tf @@ -62,8 +62,3 @@ output "private_route_table_ids" { description = "List of IDs of private route tables" value = module.vpc-eks.private_route_table_ids } - -output "vpc_peering_id_with_shared" { - description = "VPC peering ID with shared" - value = join("", try(aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[*].id, null)) -} diff --git a/apps-devstg/us-east-2/k8s-eks/network/variables.tf b/apps-devstg/us-east-2/k8s-eks/network/variables.tf index 496cf97a3..42dcaef2b 100644 --- a/apps-devstg/us-east-2/k8s-eks/network/variables.tf +++ b/apps-devstg/us-east-2/k8s-eks/network/variables.tf @@ -155,17 +155,20 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_endpoints" { - description = "VPC endpoints" - type = any - default = { - s3 = { - service = "s3" - service_type = "Gateway" - } - dynamodb = { - service = "dynamodb" - service_type = "Gateway" - } - } +variable "enable_kms_endpoint" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_kms_endpoint_private_dns" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_tgw" { + description = "Enable Transit Gateway Support" + type = bool + default = false } diff --git a/apps-devstg/us-east-2/k8s-eks/network/vpc_peering_requester_with_shared.tf b/apps-devstg/us-east-2/k8s-eks/network/vpc_peering_requester_with_shared.tf deleted file mode 100644 index 032a9927f..000000000 --- a/apps-devstg/us-east-2/k8s-eks/network/vpc_peering_requester_with_shared.tf +++ /dev/null @@ -1,39 +0,0 @@ -# -# Create a VPC Peering between (Apps DevStg) EKS VPC and Shared VPC -# -resource "aws_vpc_peering_connection" "apps_devstg_eks_vpc_with_shared_vpc" { - count = var.vpc_shared_created && !data.terraform_remote_state.network-vpcs["network-base"].outputs.enable_tgw ? 1 : 0 - - peer_owner_id = var.shared_account_id - peer_vpc_id = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_id - peer_region = var.region - - vpc_id = module.vpc-eks.vpc_id - auto_accept = false - - tags = merge(map("Name", "requester-apps-devstg-eks-dr-to-shared"), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Keep in mind that this will allow both private and public subnets traffic to -# be routed through the VPC Peering. However Network ACLs rules will block -# traffic from public subnets so, in order to have network connectivity to the -# cluster, you will have to implement other options (e.g. load balancers). -# -resource "aws_route" "private_subnets_to_shared_vpc" { - count = var.vpc_shared_created && !data.terraform_remote_state.network-vpcs["network-base"].outputs.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc-eks.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[0].id -} - -resource "aws_route" "public_subnets_to_shared_vpc" { - count = var.vpc_shared_created && !data.terraform_remote_state.network-vpcs["network-base"].outputs.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc-eks.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_devstg_eks_vpc_with_shared_vpc[0].id -} diff --git a/apps-prd/us-east-1/base-network/config.tf b/apps-prd/us-east-1/base-network/config.tf index 6603a595d..4ccc19865 100644 --- a/apps-prd/us-east-1/base-network/config.tf +++ b/apps-prd/us-east-1/base-network/config.tf @@ -83,3 +83,21 @@ data "terraform_remote_state" "shared-vpcs" { key = lookup(each.value, "key") } } + +# VPC remote states for apps-prd +data "terraform_remote_state" "apps-prd-vpcs" { + + for_each = { + for k, v in local.apps-prd-vpcs : + k => v if !v["tgw"] + } + + backend = "s3" + + config = { + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") + } +} diff --git a/apps-prd/us-east-1/base-network/locals.tf b/apps-prd/us-east-1/base-network/locals.tf index 9bfa7db00..0dd894073 100644 --- a/apps-prd/us-east-1/base-network/locals.tf +++ b/apps-prd/us-east-1/base-network/locals.tf @@ -126,6 +126,10 @@ locals { # Data source definitions # + ######### + # NACLs # + ######### + # shared shared-vpcs = { shared-base = { @@ -153,7 +157,29 @@ locals { } datasources-vpcs = merge( - data.terraform_remote_state.network-vpcs, # network - data.terraform_remote_state.shared-vpcs, # shared + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.shared-vpcs, # shared ) + + ################ + # VPC Peerings # + ################ + + # apps-prd + apps-prd-vpcs = { + apps-prd-base = { + region = var.region + profile = "${var.project}-apps-prd-devops" + bucket = "${var.project}-apps-prd-terraform-backend" + key = "apps-prd/network/terraform.tfstate" + tgw = false + } + apps-prd-k8s-eks = { + region = var.region + profile = "${var.project}-apps-prd-devops" + bucket = "${var.project}-apps-prd-terraform-backend" + key = "apps-prd/k8s-eks/network/terraform.tfstate" + tgw = false + } + } } diff --git a/apps-prd/us-east-1/base-network/network.tf b/apps-prd/us-east-1/base-network/network.tf index 529d38b74..64aaa54f9 100644 --- a/apps-prd/us-east-1/base-network/network.tf +++ b/apps-prd/us-east-1/base-network/network.tf @@ -1,8 +1,8 @@ # -# Network Resources +# EKS VPC # module "vpc" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v2.78.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -11,20 +11,15 @@ module "vpc" { private_subnets = local.private_subnets public_subnets = local.public_subnets - enable_nat_gateway = var.vpc_enable_nat_gateway - single_nat_gateway = var.vpc_single_nat_gateway - enable_dns_hostnames = var.vpc_enable_dns_hostnames - enable_vpn_gateway = var.vpc_enable_vpn_gateway - enable_s3_endpoint = var.vpc_enable_s3_endpoint - enable_dynamodb_endpoint = var.vpc_enable_dynamodb_endpoint + enable_nat_gateway = var.vpc_enable_nat_gateway + single_nat_gateway = var.vpc_single_nat_gateway + enable_dns_hostnames = var.vpc_enable_dns_hostnames + enable_vpn_gateway = var.vpc_enable_vpn_gateway - enable_kms_endpoint = var.enable_kms_endpoint - kms_endpoint_private_dns_enabled = var.enable_kms_endpoint_private_dns - kms_endpoint_security_group_ids = var.enable_kms_endpoint ? [aws_security_group.kms_vpce[0].id] : [] - - manage_default_network_acl = var.manage_default_network_acl - public_dedicated_network_acl = var.public_dedicated_network_acl // use dedicated network ACL for the public subnets. - private_dedicated_network_acl = var.private_dedicated_network_acl // use dedicated network ACL for the private subnets. + # Use a custom network ACL rules for private and public subnets + manage_default_network_acl = false + public_dedicated_network_acl = true + private_dedicated_network_acl = true private_inbound_acl_rules = concat( local.network_acls["default_inbound"], local.network_acls["private_inbound"], @@ -35,6 +30,49 @@ module "vpc" { tags = local.tags } +# VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} +module "vpc_endpoints" { + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" + + for_each = local.vpc_endpoints + + vpc_id = module.vpc.vpc_id + + endpoints = { + endpoint = merge(each.value, + { + route_table_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + } + ) + } + + tags = local.tags +} + # # KMS VPC Endpoint: Security Group # diff --git a/apps-prd/us-east-1/base-network/network_vpc_peering_requester_apps_prd_to_shared.tf b/apps-prd/us-east-1/base-network/network_vpc_peering_requester_apps_prd_to_shared.tf deleted file mode 100644 index 89790adfa..000000000 --- a/apps-prd/us-east-1/base-network/network_vpc_peering_requester_apps_prd_to_shared.tf +++ /dev/null @@ -1,44 +0,0 @@ -# -# VPC Peering Connection with Share: Requester Side -# -# Consider 'destination_cidr_block' parameter will be the CIDR of the remote VPC/Subnets (originator of the VPC -# peering request) and 'route_table_id' the route table ID to add the destination route to. -# - -# -# VPC Apps Prd w/ Shared -# -resource "aws_vpc_peering_connection" "apps_prd_vpc_with_shared_vpc" { - count = var.vpc_shared_created && !var.enable_tgw ? 1 : 0 - - peer_owner_id = var.shared_account_id - peer_vpc_id = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_id - vpc_id = module.vpc.vpc_id - auto_accept = false - - tags = merge(map("Name", "requester-apps-prd-to-shared"), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Both private and public subnets traffic will be routed and permitted through VPC Peerings (filtered by Private Inbound NACLs) -# If stryctly needed private subnets must be exposed via Load Balancers (NLBs || ALBs) -# reducing public IPs exposure whenever possible. -# read more: https://github.com/binbashar/le-tf-infra-aws/issues/49 -# -resource "aws_route" "priv_route_table_1_apps_prd_vpc_to_shared_vpc" { - count = var.vpc_shared_created && !var.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_prd_vpc_with_shared_vpc[0].id -} - -resource "aws_route" "pub_route_table_1_apps_prd_vpc_to_shared_vpc" { - count = var.vpc_shared_created && !var.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_prd_vpc_with_shared_vpc[0].id -} diff --git a/apps-prd/us-east-1/base-network/outputs.tf b/apps-prd/us-east-1/base-network/outputs.tf index 01107469b..e4a2e15ce 100644 --- a/apps-prd/us-east-1/base-network/outputs.tf +++ b/apps-prd/us-east-1/base-network/outputs.tf @@ -54,8 +54,3 @@ output "private_route_table_ids" { description = "List of IDs of private route tables" value = module.vpc.private_route_table_ids } - -output "vpc_peering_id_with_shared" { - description = "VPC peering ID with shared" - value = join("", try(aws_vpc_peering_connection.apps_prd_vpc_with_shared_vpc[*].id, null)) -} diff --git a/apps-prd/us-east-1/base-network/variables.tf b/apps-prd/us-east-1/base-network/variables.tf index 79e24f938..f4819ea47 100644 --- a/apps-prd/us-east-1/base-network/variables.tf +++ b/apps-prd/us-east-1/base-network/variables.tf @@ -124,18 +124,6 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_enable_s3_endpoint" { - description = "Enable S3 endpoint" - type = bool - default = true -} - -variable "vpc_enable_dynamodb_endpoint" { - description = "Enable DynamoDB endpoint" - type = bool - default = true -} - variable "enable_kms_endpoint" { description = "Enable KMS endpoint" type = bool diff --git a/apps-prd/us-east-1/base-network/vpc_peerings.tf b/apps-prd/us-east-1/base-network/vpc_peerings.tf new file mode 100644 index 000000000..423d2686c --- /dev/null +++ b/apps-prd/us-east-1/base-network/vpc_peerings.tf @@ -0,0 +1,32 @@ +# +# VPC Peering: apps-prd base VPC => eks clusters VPC +module "vpc_peering_apps_prd_to_eks_clusters" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.apps-prd-vpcs : + k => v if !v["tgw"] && k != "apps-prd-base" # No peerings when TGW enabled or against the base network + } + + providers = { + aws.this = aws + aws.peer = aws + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "apps-prd-to-${each.key}", + "PeeringRequester" = each.key, + "PeeringAccepter" = "apps-prd" + }) +} diff --git a/apps-prd/us-east-1/k8s-eks/network/build.env b/apps-prd/us-east-1/k8s-eks/network/build.env deleted file mode 100644 index ae2f5ed7a..000000000 --- a/apps-prd/us-east-1/k8s-eks/network/build.env +++ /dev/null @@ -1 +0,0 @@ -TERRAFORM_IMAGE_TAG=0.14.11 diff --git a/apps-prd/us-east-1/k8s-eks/network/locals.tf b/apps-prd/us-east-1/k8s-eks/network/locals.tf index 1d17decd8..1b0a82b5e 100644 --- a/apps-prd/us-east-1/k8s-eks/network/locals.tf +++ b/apps-prd/us-east-1/k8s-eks/network/locals.tf @@ -140,13 +140,13 @@ locals { # network network-vpcs = { - network-base = { - region = var.region - profile = "${var.project}-network-devops" - bucket = "${var.project}-network-terraform-backend" - key = "network/network/terraform.tfstate" - } network-firewall = { + network-base = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network/terraform.tfstate" + } region = var.region profile = "${var.project}-network-devops" bucket = "${var.project}-network-terraform-backend" @@ -155,7 +155,7 @@ locals { } datasources-vpcs = merge( - data.terraform_remote_state.network-vpcs, # network - data.terraform_remote_state.shared-vpcs, # shared + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.shared-vpcs, # shared ) } diff --git a/apps-prd/us-east-1/k8s-eks/network/network.tf b/apps-prd/us-east-1/k8s-eks/network/network.tf index 3bef7167f..e6b6994f0 100644 --- a/apps-prd/us-east-1/k8s-eks/network/network.tf +++ b/apps-prd/us-east-1/k8s-eks/network/network.tf @@ -2,7 +2,7 @@ # EKS VPC # module "vpc-eks" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -31,10 +31,34 @@ module "vpc-eks" { } # VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} module "vpc_endpoints" { - source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.1.0" + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" - for_each = var.vpc_endpoints + for_each = local.vpc_endpoints vpc_id = module.vpc-eks.vpc_id @@ -48,3 +72,30 @@ module "vpc_endpoints" { tags = local.tags } + +# +# KMS VPC Endpoint: Security Group +# +resource "aws_security_group" "kms_vpce" { + count = var.enable_kms_endpoint ? 1 : 0 + name = "kms_vpce" + description = "Allow TLS inbound traffic" + vpc_id = module.vpc-eks.vpc_id + + ingress { + description = "TLS from VPC" + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [local.vpc_cidr_block] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = local.tags +} diff --git a/apps-prd/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf b/apps-prd/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf index dcfa8e5bc..89f7c95aa 100644 --- a/apps-prd/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf +++ b/apps-prd/us-east-1/k8s-eks/network/network_vpc_peering_accepter_vault_hvn.tf @@ -7,7 +7,7 @@ resource "aws_vpc_peering_connection_accepter" "with_vault_hvn" { vpc_peering_connection_id = var.vpc_vault_hvn_peering_connection_id auto_accept = true - tags = merge(map("Name", "accepter-shared-from-vault-hvn"), local.tags) + tags = merge({ Name = "accepter-shared-from-vault-hvn" }, local.tags) } # diff --git a/apps-prd/us-east-1/k8s-eks/network/outputs.tf b/apps-prd/us-east-1/k8s-eks/network/outputs.tf index 51f0f045a..fb89a3c1d 100644 --- a/apps-prd/us-east-1/k8s-eks/network/outputs.tf +++ b/apps-prd/us-east-1/k8s-eks/network/outputs.tf @@ -62,8 +62,3 @@ output "private_route_table_ids" { description = "List of IDs of private route tables" value = module.vpc-eks.private_route_table_ids } - -output "vpc_peering_id_with_shared" { - description = "VPC peering ID with shared" - value = join("", try(aws_vpc_peering_connection.apps_prd_eks_vpc_with_shared_vpc[*].id, null)) -} diff --git a/apps-prd/us-east-1/k8s-eks/network/variables.tf b/apps-prd/us-east-1/k8s-eks/network/variables.tf index ac11d3091..0ee51ac6b 100644 --- a/apps-prd/us-east-1/k8s-eks/network/variables.tf +++ b/apps-prd/us-east-1/k8s-eks/network/variables.tf @@ -144,19 +144,16 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_endpoints" { - description = "VPC endpoints" - type = any - default = { - s3 = { - service = "s3" - service_type = "Gateway" - } - dynamodb = { - service = "dynamodb" - service_type = "Gateway" - } - } +variable "enable_kms_endpoint" { + description = "Enable KMS endpoint" + type = bool + default = false +} + +variable "enable_kms_endpoint_private_dns" { + description = "Enable KMS endpoint" + type = bool + default = false } variable "enable_tgw" { diff --git a/apps-prd/us-east-1/k8s-eks/network/vpc_peering_requester_with_shared.tf b/apps-prd/us-east-1/k8s-eks/network/vpc_peering_requester_with_shared.tf deleted file mode 100644 index 958e8895e..000000000 --- a/apps-prd/us-east-1/k8s-eks/network/vpc_peering_requester_with_shared.tf +++ /dev/null @@ -1,37 +0,0 @@ -# -# Create a VPC Peering between (Apps DevStg) EKS VPC and Shared VPC -# -resource "aws_vpc_peering_connection" "apps_prd_eks_vpc_with_shared_vpc" { - count = var.vpc_shared_created && !var.enable_tgw ? 1 : 0 - - peer_owner_id = var.shared_account_id - peer_vpc_id = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_id - vpc_id = module.vpc-eks.vpc_id - auto_accept = false - - tags = merge(map("Name", "requester-apps-prd-eks-to-shared"), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Keep in mind that this will allow both private and public subnets traffic to -# be routed through the VPC Peering. However Network ACLs rules will block -# traffic from public subnets so, in order to have network connectivity to the -# cluster, you will have to implement other options (e.g. load balancers). -# -resource "aws_route" "priv_route_table_1_apps_prd_eks_vpc_to_shared_vpc" { - count = var.vpc_shared_created && !var.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc-eks.private_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_prd_eks_vpc_with_shared_vpc[0].id -} - -resource "aws_route" "pub_route_table_1_apps_prd_eks_vpc_to_shared_vpc" { - count = var.vpc_shared_created && !var.enable_tgw ? 1 : 0 - - route_table_id = element(module.vpc-eks.public_route_table_ids, 0) - destination_cidr_block = data.terraform_remote_state.shared-vpcs["shared-base"].outputs.vpc_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.apps_prd_eks_vpc_with_shared_vpc[0].id -} diff --git a/network/network-firewall/README.md b/network/network-firewall/README.md new file mode 100644 index 000000000..e2bfc75a9 --- /dev/null +++ b/network/network-firewall/README.md @@ -0,0 +1,52 @@ +# Network firewall & Transit Gateway + +You can deploy AWS Network Firewall with and without a Transit Gateway. + +In case you are using AWS Transit Gateway, you need to enable the Network Firewall support in the `transit_gateway' layer`. This will create the necessary TGW route tables and associations to the inspection VPC. Also take into account the TGW layer implements centralized NAT Gateways for all private subnets, therefore you will need first to enable the NAT Gateways in the `network` account. + +In order to enable Network Firewall using a Transit Gateway perform the following order: + + +1. Enable NAT Gateway in the `network` account. Edit the `../network/us-east-1/base-network/network.auto.tfvars' file: + +``` +# NAT GW +vpc_enable_nat_gateway = true +vpc_single_nat_gateway = true + +# VPN Gateways +vpc_enable_vpn_gateway = false +``` + +Apply the changes. + + +2. Enable the Network Firewall support in the Transit Gateway layer by editing the `../network/us-east-1/transit-gateway/tgw.auto.tfvars` file: +``` +# Transit Gateway +# enable_tgw = false # Set this value in the ../config/common.tfvars + +# TGW VPC Attahcments +enable_vpc_attach = { + network = true + shared = true + apps-devstg = true + apps-prd = true +} + +# Network Firewall +enable_network_firewall = true +``` + +3 Enable the transit gateway by adding the following lines in the `../config/common.tfvars` file: + +``` +# Networking + +# Enable TGW +enable_tgw = true + +``` +Then apply the changes in the Transit Gateway layer. + +4. Finally edit the `network-firewall` layer according to your needs and apply the changes. diff --git a/network/us-east-1/transit-gateway/tgw.auto.tfvars b/network/us-east-1/transit-gateway/tgw.auto.tfvars index a91153d82..50982de18 100644 --- a/network/us-east-1/transit-gateway/tgw.auto.tfvars +++ b/network/us-east-1/transit-gateway/tgw.auto.tfvars @@ -1,5 +1,5 @@ # Transit Gateway -# enable_tgw = false # Set this value in the ./config +# enable_tgw = false # Set this value in the `config/common.tfvars` # TGW VPC Attahcments enable_vpc_attach = { diff --git a/shared/us-east-1/base-network/config.tf b/shared/us-east-1/base-network/config.tf index 8ff71ca66..0cfb3b6b9 100644 --- a/shared/us-east-1/base-network/config.tf +++ b/shared/us-east-1/base-network/config.tf @@ -7,6 +7,41 @@ provider "aws" { shared_credentials_file = "~/.aws/${var.project}/config" } +provider "aws" { + alias = "apps-devstg" + region = var.region + profile = "${var.project}-apps-devstg-devops" + shared_credentials_file = "~/.aws/${var.project}/config" +} + +provider "aws" { + alias = "apps-devstg-dr" + region = var.region_secondary + profile = "${var.project}-apps-devstg-devops" + shared_credentials_file = "~/.aws/${var.project}/config" +} + +provider "aws" { + alias = "apps-prd" + region = var.region + profile = "${var.project}-apps-prd-devops" + shared_credentials_file = "~/.aws/${var.project}/config" +} + +provider "aws" { + alias = "apps-prd-dr" + region = var.region_secondary + profile = "${var.project}-apps-prd-devops" + shared_credentials_file = "~/.aws/${var.project}/config" +} + +provider "aws" { + alias = "shared-dr" + region = var.region_secondary + profile = "${var.project}-shared-devops" + shared_credentials_file = "~/.aws/${var.project}/config" +} + #=============================# # Backend Config (partial) # #=============================# @@ -72,6 +107,24 @@ data "terraform_remote_state" "apps-devstg-vpcs" { } } +# VPC remote states for apps-devstg-dr +data "terraform_remote_state" "apps-devstg-dr-vpcs" { + + for_each = { + for k, v in local.apps-devstg-dr-vpcs : + k => v if !v["tgw"] + } + + backend = "s3" + + config = { + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") + } +} + # VPC remote states for apps-prd data "terraform_remote_state" "apps-prd-vpcs" { @@ -89,3 +142,39 @@ data "terraform_remote_state" "apps-prd-vpcs" { key = lookup(each.value, "key") } } + +# VPC remote states for apps-prd-dr +data "terraform_remote_state" "apps-prd-dr-vpcs" { + + for_each = { + for k, v in local.apps-prd-dr-vpcs : + k => v if !v["tgw"] + } + + backend = "s3" + + config = { + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") + } +} + +# VPC remote states for apps-devstg-dr +data "terraform_remote_state" "shared-dr-vpcs" { + + for_each = { + for k, v in local.shared-dr-vpcs : + k => v if !v["tgw"] + } + + backend = "s3" + + config = { + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") + } +} diff --git a/shared/us-east-1/base-network/locals.tf b/shared/us-east-1/base-network/locals.tf index a004de780..e40b5b501 100644 --- a/shared/us-east-1/base-network/locals.tf +++ b/shared/us-east-1/base-network/locals.tf @@ -144,6 +144,10 @@ locals { key = "apps-devstg/k8s-eks-demoapps/network/terraform.tfstate" tgw = false } + } + + # apps-devstg-dr + apps-devstg-dr-vpcs = { apps-devstg-k8s-eks-dr = { region = var.region profile = "${var.project}-apps-devstg-devops" @@ -171,8 +175,25 @@ locals { } } + # apps-prd-dr + apps-prd-dr-vpcs = {} + + # shared-dr + shared-dr-vpcs = { + shared-dr-base = { + region = var.region + profile = var.profile + bucket = "${var.project}-shared-terraform-backend" + key = "shared/network-dr/terraform.tfstate" + tgw = false + } + } + datasources-vpcs = merge( - data.terraform_remote_state.apps-devstg-vpcs, # apps-devstg-vpcs - data.terraform_remote_state.apps-prd-vpcs, # apps-prd-vpcs + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.apps-devstg-vpcs, # apps-devstg-vpcs + data.terraform_remote_state.apps-devstg-dr-vpcs, # apps-devstg-dr-vpcs + data.terraform_remote_state.apps-prd-vpcs, # apps-prd-vpcs + data.terraform_remote_state.apps-prd-dr-vpcs, # apps-prd-dr-vpcs ) } diff --git a/shared/us-east-1/base-network/network.tf b/shared/us-east-1/base-network/network.tf index e35b259bb..6b9b49034 100644 --- a/shared/us-east-1/base-network/network.tf +++ b/shared/us-east-1/base-network/network.tf @@ -2,7 +2,7 @@ # Network Resources # module "vpc" { - source = "github.com/binbashar/terraform-aws-vpc.git?ref=v2.78.0" + source = "github.com/binbashar/terraform-aws-vpc.git?ref=v3.11.0" name = local.vpc_name cidr = local.vpc_cidr_block @@ -11,17 +11,12 @@ module "vpc" { private_subnets = local.private_subnets public_subnets = local.public_subnets - enable_nat_gateway = var.vpc_enable_nat_gateway - single_nat_gateway = var.vpc_single_nat_gateway - enable_dns_hostnames = var.vpc_enable_dns_hostnames - enable_vpn_gateway = var.vpc_enable_vpn_gateway - enable_s3_endpoint = var.vpc_enable_s3_endpoint - enable_dynamodb_endpoint = var.vpc_enable_dynamodb_endpoint - - enable_kms_endpoint = var.enable_kms_endpoint - kms_endpoint_private_dns_enabled = var.enable_kms_endpoint_private_dns - kms_endpoint_security_group_ids = var.enable_kms_endpoint ? [aws_security_group.kms_vpce[0].id] : [] + enable_nat_gateway = var.vpc_enable_nat_gateway + single_nat_gateway = var.vpc_single_nat_gateway + enable_dns_hostnames = var.vpc_enable_dns_hostnames + enable_vpn_gateway = var.vpc_enable_vpn_gateway + # Use a custom network ACL rules for private and public subnets manage_default_network_acl = var.manage_default_network_acl public_dedicated_network_acl = var.public_dedicated_network_acl // use dedicated network ACL for the public subnets. private_dedicated_network_acl = var.private_dedicated_network_acl // use dedicated network ACL for the private subnets. @@ -33,6 +28,50 @@ module "vpc" { tags = local.tags } +# VPC Endpoints +locals { + vpc_endpoints = merge({ + # S3 + s3 = { + service = "s3" + service_type = "Gateway" + } + # DynamamoDB + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + } + }, + # KMS + { for k, v in { kms = "Interface" } : + k => { + service = k + service_type = v + security_group_ids = aws_security_group.kms_vpce[0].id + private_dns_enabled = var.enable_kms_endpoint_private_dns + } if var.enable_kms_endpoint + } + ) +} + +module "vpc_endpoints" { + source = "github.com/binbashar/terraform-aws-vpc.git//modules/vpc-endpoints?ref=v3.11.0" + + for_each = local.vpc_endpoints + + vpc_id = module.vpc.vpc_id + + endpoints = { + endpoint = merge(each.value, + { + route_table_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + } + ) + } + + tags = local.tags +} + # # KMS VPC Endpoint: Security Group # diff --git a/shared/us-east-1/base-network/variables.tf b/shared/us-east-1/base-network/variables.tf index 59348214a..7d449596a 100644 --- a/shared/us-east-1/base-network/variables.tf +++ b/shared/us-east-1/base-network/variables.tf @@ -164,18 +164,6 @@ variable "vpc_enable_vpn_gateway" { default = false } -variable "vpc_enable_s3_endpoint" { - description = "Enable S3 endpoint" - type = bool - default = true -} - -variable "vpc_enable_dynamodb_endpoint" { - description = "Enable DynamoDB endpoint" - type = bool - default = true -} - variable "enable_kms_endpoint" { description = "Enable KMS endpoint" type = bool diff --git a/shared/us-east-1/base-network/vpc_peering_accepters.tf b/shared/us-east-1/base-network/vpc_peering_accepters.tf deleted file mode 100644 index a9a0349a9..000000000 --- a/shared/us-east-1/base-network/vpc_peering_accepters.tf +++ /dev/null @@ -1,44 +0,0 @@ -# -# VPC Peering Connection - Accepter Side -# -resource "aws_vpc_peering_connection_accepter" "shared_accepters" { - - for_each = { for k, v in local.datasources-vpcs : - k => v if !var.enable_tgw - } - - vpc_peering_connection_id = each.value.outputs.vpc_peering_id_with_shared - auto_accept = true - - tags = merge(tomap({ "Name" = "accepter-shared-from-${each.value.outputs.vpc_name}" }), local.tags) -} - -# -# Update Route Tables to go through the VPC Peering Connection -# --- -# Both private and public subnets traffic will be routed and permitted through VPC Peerings (filtered by Private Inbound NACLs) -# If stryctly needed private subnets must be exposed via Load Balancers (NLBs || ALBs) -# reducing public IPs exposure whenever possible. -# read more: https://github.com/binbashar/le-tf-infra-aws/issues/49 -# -resource "aws_route" "priv_route_table_to_apps_vpc" { - - for_each = { for k, v in local.datasources-vpcs : - k => v if !var.enable_tgw - } - - route_table_id = element(module.vpc.private_route_table_ids, 0) - destination_cidr_block = each.value.outputs.vpc_cidr_block - vpc_peering_connection_id = each.value.outputs.vpc_peering_id_with_shared -} - -resource "aws_route" "pub_route_table_to_apps_vpc" { - - for_each = { for k, v in local.datasources-vpcs : - k => v if !var.enable_tgw - } - - route_table_id = element(module.vpc.public_route_table_ids, 0) - destination_cidr_block = each.value.outputs.vpc_cidr_block - vpc_peering_connection_id = each.value.outputs.vpc_peering_id_with_shared -} diff --git a/shared/us-east-1/base-network/vpc_peerings.tf b/shared/us-east-1/base-network/vpc_peerings.tf new file mode 100644 index 000000000..4fb77a0ba --- /dev/null +++ b/shared/us-east-1/base-network/vpc_peerings.tf @@ -0,0 +1,169 @@ +# +# VPC Peering: apps-devstg VPC <=> Shared VPC +# +module "vpc_peering_apps_devstg_to_shared" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.apps-devstg-vpcs : + k => v if !v["tgw"] + } + + providers = { + aws.this = aws + aws.peer = aws.apps-devstg + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-devstg-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.apps-devstg-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-devstg-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "${each.key}-to-shared", + "PeeringRequester" = each.key, + "PeeringAccepter" = "shared" + }) +} + +# +# VPC Peering: apps-devstg-dr VPC <=> Shared VPC +# +module "vpc_peering_apps_devstg_dr_to_shared" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.apps-devstg-dr-vpcs : + k => v if !v["tgw"] + } + + providers = { + aws.this = aws + aws.peer = aws.apps-devstg-dr + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-devstg-dr-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.apps-devstg-dr-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-devstg-dr-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "${each.key}-to-shared", + "PeeringRequester" = each.key, + "PeeringAccepter" = "shared" + }) +} + +# +# VPC Peering: apps-prd VPC <=> Shared VPC +# +module "vpc_peering_apps_prd_to_shared" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.apps-prd-vpcs : + k => v if !v["tgw"] + } + + providers = { + aws.this = aws + aws.peer = aws.apps-prd + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "${each.key}-to-shared", + "PeeringRequester" = each.key, + "PeeringAccepter" = "shared" + }) +} + +# +# VPC Peering: apps-prd-dr VPC <=> Shared VPC +# +module "vpc_peering_apps_prd_dr_to_shared" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.apps-prd-dr-vpcs : + k => v if !v["tgw"] + } + + providers = { + aws.this = aws + aws.peer = aws.apps-prd-dr + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-prd-dr-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.apps-prd-dr-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-prd-dr-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "${each.key}-to-shared", + "PeeringRequester" = each.key, + "PeeringAccepter" = "shared" + }) +} + +# +# VPC Peering: Shared DR <=> Shared VPC +# +module "vpc_peering_shared_dr_to_shared" { + source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" + + for_each = { + for k, v in local.shared-dr-vpcs : + k => v if !v["tgw"] + } + + providers = { + aws.this = aws + aws.peer = aws.shared-dr + } + + this_vpc_id = module.vpc.vpc_id + peer_vpc_id = data.terraform_remote_state.shared-dr-vpcs[each.key].outputs.vpc_id + + this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) + peer_rts_ids = concat( + data.terraform_remote_state.shared-dr-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.shared-dr-vpcs[each.key].outputs.private_route_table_ids + ) + + auto_accept_peering = true + + tags = merge(local.tags, { + "Name" = "${each.key}-to-shared", + "PeeringRequester" = each.key, + "PeeringAccepter" = "shared" + }) +} diff --git a/shared/us-east-2/base-network/config.tf b/shared/us-east-2/base-network/config.tf index 12cc26f7f..8370a7de8 100644 --- a/shared/us-east-2/base-network/config.tf +++ b/shared/us-east-2/base-network/config.tf @@ -8,14 +8,21 @@ provider "aws" { } provider "aws" { - alias = "devstg_eks_dr" + alias = "apps-devstg-dr" region = var.region_secondary profile = "${var.project}-apps-devstg-devops" shared_credentials_file = "~/.aws/${var.project}/config" } provider "aws" { - alias = "shared_main" + alias = "apps-prd-dr" + region = var.region_secondary + profile = "${var.project}-apps-prd-devops" + shared_credentials_file = "~/.aws/${var.project}/config" +} + +provider "aws" { + alias = "shared-primary" region = var.region profile = var.profile shared_credentials_file = "~/.aws/${var.project}/config" @@ -51,6 +58,20 @@ data "terraform_remote_state" "tools-vpn-server" { } } +# VPC remote states for network +data "terraform_remote_state" "network-vpcs" { + for_each = local.network-vpcs + + backend = "s3" + + config = { + region = lookup(each.value, "region") + profile = lookup(each.value, "profile") + bucket = lookup(each.value, "bucket") + key = lookup(each.value, "key") + } +} + # VPC remote states for shared data "terraform_remote_state" "shared-vpcs" { for_each = { @@ -68,11 +89,11 @@ data "terraform_remote_state" "shared-vpcs" { } } -# VPC remote states for apps-devstg -data "terraform_remote_state" "apps-devstg-vpcs" { +# VPC remote states for apps-devstg-dr +data "terraform_remote_state" "apps-devstg-dr-vpcs" { for_each = { - for k, v in local.apps-devstg-vpcs : + for k, v in local.apps-devstg-dr-vpcs : k => v if !v["tgw"] } @@ -86,11 +107,11 @@ data "terraform_remote_state" "apps-devstg-vpcs" { } } -# VPC remote states for apps-prd -data "terraform_remote_state" "apps-prd-vpcs" { +# VPC remote states for apps-prd-dr +data "terraform_remote_state" "apps-prd-dr-vpcs" { for_each = { - for k, v in local.apps-prd-vpcs : + for k, v in local.apps-prd-dr-vpcs : k => v if !v["tgw"] } diff --git a/shared/us-east-2/base-network/locals.tf b/shared/us-east-2/base-network/locals.tf index ac393ea4e..1209d20a0 100644 --- a/shared/us-east-2/base-network/locals.tf +++ b/shared/us-east-2/base-network/locals.tf @@ -115,7 +115,30 @@ locals { # # Data source definitions # - apps-devstg-vpcs = { + + # network + network-vpcs = { + network-base = { + region = var.region + profile = "${var.project}-network-devops" + bucket = "${var.project}-network-terraform-backend" + key = "network/network/terraform.tfstate" + } + } + + # shared + shared-vpcs = { + shared-base = { + region = var.region + profile = "${var.project}-shared-devops" + bucket = "${var.project}-shared-terraform-backend" + key = "shared/network/terraform.tfstate" + tgw = false + } + } + + # apps-devstg-dr + apps-devstg-dr-vpcs = { apps-devstg-k8s-eks-dr = { region = var.region profile = "${var.project}-apps-devstg-devops" @@ -124,19 +147,24 @@ locals { tgw = false } } - apps-prd-vpcs = {} - shared-vpcs = { - shared-vpc = { + # apps-prd-dr + apps-prd-dr-vpcs = {} + + + # shared-dr + shared-dr-vpcs = { + shared-dr-base = { region = var.region profile = var.profile - bucket = var.bucket - key = "${var.environment}/network/terraform.tfstate" + bucket = "${var.project}-shared-terraform-backend" + key = "shared/network-dr/terraform.tfstate" tgw = false } } datasources-vpcs = merge( - data.terraform_remote_state.apps-devstg-vpcs, - data.terraform_remote_state.apps-prd-vpcs, + var.enable_tgw ? data.terraform_remote_state.network-vpcs : null, # network + data.terraform_remote_state.apps-devstg-dr-vpcs, # devstg-dr + data.terraform_remote_state.apps-prd-dr-vpcs, # apps-prd-dr ) } diff --git a/shared/us-east-2/base-network/vpc_peerings.tf b/shared/us-east-2/base-network/vpc_peerings.tf index 76e0616d4..4d8c8df97 100644 --- a/shared/us-east-2/base-network/vpc_peerings.tf +++ b/shared/us-east-2/base-network/vpc_peerings.tf @@ -1,61 +1,33 @@ # -# VPC Peering: Shared DR VPC => AppsDevStg EKS DR VPC +# VPC Peering: apps-devstg-dr VPC => Shared DR VPC # -module "vpc_peering_shared_dr_to_devstg_eks_dr" { +module "vpc_peering_apps_devstg_dr_to_shared_dr" { source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" - # Pass both providers so that both sides (requester and accepter) can be managed - providers = { - aws.this = aws - aws.peer = aws.devstg_eks_dr + for_each = { + for k, v in local.apps-devstg-dr-vpcs : + k => v if !v["tgw"] } - # Requester is referred to as "this", whereas accepter is the "peer" - this_vpc_id = module.vpc.vpc_id - peer_vpc_id = data.terraform_remote_state.apps-devstg-vpcs["apps-devstg-k8s-eks-dr"].outputs.vpc_id - - # Specify which route tables should be updated - this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) - peer_rts_ids = concat( - data.terraform_remote_state.apps-devstg-vpcs["apps-devstg-k8s-eks-dr"].outputs.public_route_table_ids, - data.terraform_remote_state.apps-devstg-vpcs["apps-devstg-k8s-eks-dr"].outputs.private_route_table_ids - ) - - # Automatically accept the peering request on the accepter side - auto_accept_peering = true - - tags = merge(local.tags, { - "Name" = "shared-dr-to-devstg-eks-dr", - "PeeringRequester" = "shared-dr", - "PeeringAccepter" = "devstg-eks-dr" - }) -} - -# -# VPC Peering: Shared DR VPC => Shared VPC -# -module "vpc_peering_shared_dr_to_shared" { - source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v4.0.1" - providers = { aws.this = aws - aws.peer = aws.shared_main + aws.peer = aws.apps-devstg-dr } this_vpc_id = module.vpc.vpc_id - peer_vpc_id = data.terraform_remote_state.shared-vpcs["shared-vpc"].outputs.vpc_id + peer_vpc_id = data.terraform_remote_state.apps-devstg-dr-vpcs[each.key].outputs.vpc_id this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) peer_rts_ids = concat( - data.terraform_remote_state.shared-vpcs["shared-vpc"].outputs.public_route_table_ids, - data.terraform_remote_state.shared-vpcs["shared-vpc"].outputs.private_route_table_ids + data.terraform_remote_state.apps-devstg-dr-vpcs[each.key].outputs.public_route_table_ids, + data.terraform_remote_state.apps-devstg-dr-vpcs[each.key].outputs.private_route_table_ids ) auto_accept_peering = true tags = merge(local.tags, { - "Name" = "shared-dr-to-shared", - "PeeringRequester" = "shared-dr", - "PeeringAccepter" = "shared" + "Name" = "${each.key}-to-shared-dr", + "PeeringRequester" = each.key, + "PeeringAccepter" = "shared-dr" }) }