Files
Greg Hendrickson 6136cde9bb feat: Terraform Foundation - AWS Landing Zone
Enterprise-grade multi-tenant AWS cloud foundation.

Modules:
- GitHub OIDC for keyless CI/CD authentication
- IAM account settings and security baseline
- AWS Config Rules for compliance
- ABAC (Attribute-Based Access Control)
- SCPs (Service Control Policies)

Features:
- Multi-account architecture
- Cost optimization patterns
- Security best practices
- Comprehensive documentation

Tech: Terraform, AWS Organizations, IAM Identity Center
2026-02-02 02:57:23 +00:00

335 lines
10 KiB
HCL

################################################################################
# VPC Endpoints Module
#
# Provides private connectivity to AWS services without NAT Gateway:
# - Gateway endpoints (S3, DynamoDB) - FREE
# - Interface endpoints (ECR, Secrets Manager, etc.) - ~$7/mo each
#
# Cost/Security tradeoff:
# - Gateway endpoints: Always enable (free, faster)
# - Interface endpoints: Enable for high-traffic services or security requirements
################################################################################
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
variable "vpc_id" {
type = string
}
variable "private_subnet_ids" {
type = list(string)
}
variable "private_route_table_ids" {
type = list(string)
}
variable "region" {
type = string
}
variable "name_prefix" {
type = string
default = "shared"
}
# Gateway endpoints (FREE - always enable)
variable "enable_s3_endpoint" {
type = bool
default = true
}
variable "enable_dynamodb_endpoint" {
type = bool
default = true
}
# Interface endpoints (~$7/mo each + data transfer)
variable "enable_ecr_endpoints" {
type = bool
default = false
description = "ECR API + DKR endpoints for container pulls without NAT"
}
variable "enable_secrets_manager_endpoint" {
type = bool
default = false
description = "Secrets Manager endpoint for secret retrieval without NAT"
}
variable "enable_ssm_endpoints" {
type = bool
default = false
description = "SSM, SSM Messages, EC2 Messages for Session Manager"
}
variable "enable_logs_endpoint" {
type = bool
default = false
description = "CloudWatch Logs endpoint"
}
variable "enable_kms_endpoint" {
type = bool
default = false
description = "KMS endpoint for encryption operations"
}
variable "enable_sts_endpoint" {
type = bool
default = false
description = "STS endpoint for IAM role assumption"
}
variable "enable_eks_endpoint" {
type = bool
default = false
description = "EKS endpoint for kubectl without public access"
}
################################################################################
# Security Group for Interface Endpoints
################################################################################
resource "aws_security_group" "endpoints" {
count = local.any_interface_endpoint ? 1 : 0
name = "${var.name_prefix}-vpc-endpoints"
description = "VPC Interface Endpoints"
vpc_id = var.vpc_id
ingress {
description = "HTTPS from VPC"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [data.aws_vpc.main.cidr_block]
}
tags = { Name = "${var.name_prefix}-vpc-endpoints" }
}
data "aws_vpc" "main" {
id = var.vpc_id
}
locals {
any_interface_endpoint = (
var.enable_ecr_endpoints ||
var.enable_secrets_manager_endpoint ||
var.enable_ssm_endpoints ||
var.enable_logs_endpoint ||
var.enable_kms_endpoint ||
var.enable_sts_endpoint ||
var.enable_eks_endpoint
)
}
################################################################################
# Gateway Endpoints (FREE)
################################################################################
resource "aws_vpc_endpoint" "s3" {
count = var.enable_s3_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = var.private_route_table_ids
tags = { Name = "${var.name_prefix}-s3" }
}
resource "aws_vpc_endpoint" "dynamodb" {
count = var.enable_dynamodb_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.dynamodb"
vpc_endpoint_type = "Gateway"
route_table_ids = var.private_route_table_ids
tags = { Name = "${var.name_prefix}-dynamodb" }
}
################################################################################
# ECR Endpoints (for container pulls without NAT)
################################################################################
resource "aws_vpc_endpoint" "ecr_api" {
count = var.enable_ecr_endpoints ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ecr.api"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-ecr-api" }
}
resource "aws_vpc_endpoint" "ecr_dkr" {
count = var.enable_ecr_endpoints ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ecr.dkr"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-ecr-dkr" }
}
################################################################################
# Secrets Manager Endpoint
################################################################################
resource "aws_vpc_endpoint" "secretsmanager" {
count = var.enable_secrets_manager_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.secretsmanager"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-secretsmanager" }
}
################################################################################
# SSM Endpoints (for Session Manager)
################################################################################
resource "aws_vpc_endpoint" "ssm" {
count = var.enable_ssm_endpoints ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ssm"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-ssm" }
}
resource "aws_vpc_endpoint" "ssmmessages" {
count = var.enable_ssm_endpoints ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ssmmessages"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-ssmmessages" }
}
resource "aws_vpc_endpoint" "ec2messages" {
count = var.enable_ssm_endpoints ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ec2messages"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-ec2messages" }
}
################################################################################
# CloudWatch Logs Endpoint
################################################################################
resource "aws_vpc_endpoint" "logs" {
count = var.enable_logs_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.logs"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-logs" }
}
################################################################################
# KMS Endpoint
################################################################################
resource "aws_vpc_endpoint" "kms" {
count = var.enable_kms_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.kms"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-kms" }
}
################################################################################
# STS Endpoint
################################################################################
resource "aws_vpc_endpoint" "sts" {
count = var.enable_sts_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.sts"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-sts" }
}
################################################################################
# EKS Endpoint
################################################################################
resource "aws_vpc_endpoint" "eks" {
count = var.enable_eks_endpoint ? 1 : 0
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.eks"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.endpoints[0].id]
private_dns_enabled = true
tags = { Name = "${var.name_prefix}-eks" }
}
################################################################################
# Outputs
################################################################################
output "s3_endpoint_id" {
value = var.enable_s3_endpoint ? aws_vpc_endpoint.s3[0].id : null
}
output "dynamodb_endpoint_id" {
value = var.enable_dynamodb_endpoint ? aws_vpc_endpoint.dynamodb[0].id : null
}
output "endpoints_security_group_id" {
value = local.any_interface_endpoint ? aws_security_group.endpoints[0].id : null
}
output "enabled_endpoints" {
value = {
s3 = var.enable_s3_endpoint
dynamodb = var.enable_dynamodb_endpoint
ecr = var.enable_ecr_endpoints
secrets_manager = var.enable_secrets_manager_endpoint
ssm = var.enable_ssm_endpoints
logs = var.enable_logs_endpoint
kms = var.enable_kms_endpoint
sts = var.enable_sts_endpoint
eks = var.enable_eks_endpoint
}
}