# VPC Endpoint ================================================================= # Security Group --------------------------------------------------------------- # Created only when Interface endpoints are defined. # Owned by this module rather than passed in, matching how the vpc module # owns its own IAM role/policy for flow logs rather than accepting one externally. resource "aws_security_group" "interface_endpoints" { for_each = length(local.interface_endpoints) > 0 ? { sg = true } : {} name = "${var.name_prefix}-${local.region_abbr}-vpce-sg" description = "Allow HTTPS from VPC CIDR to interface VPC endpoints" vpc_id = var.vpc_id tags = merge(var.tags, local.module_tags, { Name = "${var.name_prefix}-${local.region_abbr}-vpce-sg" resource-type = "security-group" }) lifecycle { precondition { condition = length("${var.name_prefix}-${local.region_abbr}-vpce-sg") <= 255 error_message = "Assembled security group name exceeds AWS's 255-character limit" } } } resource "aws_vpc_security_group_ingress_rule" "interface_endpoints_https" { for_each = length(local.interface_endpoints) > 0 ? { sg = true } : {} security_group_id = aws_security_group.interface_endpoints["sg"].id description = "HTTPS from VPC CIDR" cidr_ipv4 = var.vpc_cidr_block from_port = 443 to_port = 443 ip_protocol = "tcp" tags = merge(var.tags, local.module_tags, { Name = "${var.name_prefix}-${local.region_abbr}-vpce-sg-ingress-https" resource-type = "security-group-rule" }) } resource "aws_vpc_security_group_egress_rule" "interface_endpoints_all" { for_each = length(local.interface_endpoints) > 0 ? { sg = true } : {} security_group_id = aws_security_group.interface_endpoints["sg"].id description = "All outbound" cidr_ipv4 = "0.0.0.0/0" ip_protocol = "-1" tags = merge(var.tags, local.module_tags, { Name = "${var.name_prefix}-${local.region_abbr}-vpce-sg-egress-all" resource-type = "security-group-rule" }) } # Gateway Endpoints ------------------------------------------------------------ # Route-table-based, no ENI, no cost. S3 and DynamoDB are the only AWS # services that currently support the Gateway type. resource "aws_vpc_endpoint" "gateway" { for_each = local.gateway_endpoints vpc_id = var.vpc_id service_name = "com.amazonaws.${var.aws_region}.${each.value.service_name}" vpc_endpoint_type = "Gateway" route_table_ids = var.route_table_ids policy = each.value.policy tags = merge(var.tags, local.module_tags, { Name = "${var.name_prefix}-${local.region_abbr}-vpce-${each.key}" resource-type = "vpc-endpoint" }) } # Interface Endpoints ---------------------------------------------------------- # ENI-based, placed in the given subnets, DNS-resolved in-VPC when enabled. resource "aws_vpc_endpoint" "interface" { for_each = local.interface_endpoints vpc_id = var.vpc_id service_name = "com.amazonaws.${var.aws_region}.${each.value.service_name}" vpc_endpoint_type = "Interface" subnet_ids = var.subnet_ids security_group_ids = [aws_security_group.interface_endpoints["sg"].id] private_dns_enabled = each.value.private_dns_enabled policy = each.value.policy tags = merge(var.tags, local.module_tags, { Name = "${var.name_prefix}-${local.region_abbr}-vpce-${each.key}" resource-type = "vpc-endpoint" }) }