mirror of
https://github.com/ghndrx/terraform-foundation.git
synced 2026-02-10 14:54:56 +00:00
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
This commit is contained in:
34
terraform/modules/security-groups/README.md
Normal file
34
terraform/modules/security-groups/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# security-groups
|
||||
|
||||
Terraform module for AWS landing zone pattern.
|
||||
|
||||
Create common security group patterns for multi-tier architectures.
|
||||
|
||||
## Planned Features
|
||||
|
||||
- [ ] Web tier (HTTP/HTTPS from ALB)
|
||||
- [ ] App tier (from web tier only)
|
||||
- [ ] Database tier (from app tier only)
|
||||
- [ ] Bastion host (SSH from allowed CIDRs)
|
||||
- [ ] VPC endpoints (HTTPS from VPC)
|
||||
- [ ] EKS patterns (cluster, nodes, pods)
|
||||
|
||||
## Planned Usage
|
||||
|
||||
```hcl
|
||||
module "security_groups" {
|
||||
source = "../modules/security-groups"
|
||||
|
||||
vpc_id = module.vpc.vpc_id
|
||||
name_prefix = "myapp"
|
||||
|
||||
create_web_tier = true
|
||||
create_app_tier = true
|
||||
create_db_tier = true
|
||||
create_bastion = true
|
||||
|
||||
allowed_ssh_cidrs = ["10.0.0.0/8"]
|
||||
|
||||
tags = local.tags
|
||||
}
|
||||
```
|
||||
395
terraform/modules/security-groups/main.tf
Normal file
395
terraform/modules/security-groups/main.tf
Normal file
@@ -0,0 +1,395 @@
|
||||
################################################################################
|
||||
# Security Groups Module
|
||||
#
|
||||
# Creates common security group patterns for multi-tier architectures:
|
||||
# - Web tier (HTTP/HTTPS from ALB or internet)
|
||||
# - App tier (from web tier only)
|
||||
# - Database tier (from app tier only)
|
||||
# - Bastion host (SSH from allowed CIDRs)
|
||||
# - VPC endpoints (HTTPS from VPC)
|
||||
# - EKS patterns (cluster, nodes)
|
||||
################################################################################
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = ">= 5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_vpc" "selected" {
|
||||
id = var.vpc_id
|
||||
}
|
||||
|
||||
locals {
|
||||
vpc_cidr = data.aws_vpc.selected.cidr_block
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Web Tier Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "web" {
|
||||
count = var.create_web_tier ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-web-"
|
||||
description = "Web tier - HTTP/HTTPS access"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-web"
|
||||
Tier = "web"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "web_http" {
|
||||
count = var.create_web_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.web[0].id
|
||||
description = "HTTP from allowed sources"
|
||||
from_port = 80
|
||||
to_port = 80
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = var.web_ingress_cidr
|
||||
|
||||
tags = { Name = "http-ingress" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "web_https" {
|
||||
count = var.create_web_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.web[0].id
|
||||
description = "HTTPS from allowed sources"
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = var.web_ingress_cidr
|
||||
|
||||
tags = { Name = "https-ingress" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "web_all" {
|
||||
count = var.create_web_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.web[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# App Tier Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "app" {
|
||||
count = var.create_app_tier ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-app-"
|
||||
description = "App tier - access from web tier"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-app"
|
||||
Tier = "app"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "app_from_web" {
|
||||
count = var.create_app_tier && var.create_web_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.app[0].id
|
||||
description = "App port from web tier"
|
||||
from_port = var.app_port
|
||||
to_port = var.app_port
|
||||
ip_protocol = "tcp"
|
||||
referenced_security_group_id = aws_security_group.web[0].id
|
||||
|
||||
tags = { Name = "from-web-tier" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "app_from_cidr" {
|
||||
count = var.create_app_tier && !var.create_web_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.app[0].id
|
||||
description = "App port from VPC"
|
||||
from_port = var.app_port
|
||||
to_port = var.app_port
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = local.vpc_cidr
|
||||
|
||||
tags = { Name = "from-vpc" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "app_all" {
|
||||
count = var.create_app_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.app[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Database Tier Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "db" {
|
||||
count = var.create_db_tier ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-db-"
|
||||
description = "Database tier - access from app tier"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-db"
|
||||
Tier = "database"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "db_from_app" {
|
||||
count = var.create_db_tier && var.create_app_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.db[0].id
|
||||
description = "Database port from app tier"
|
||||
from_port = var.db_port
|
||||
to_port = var.db_port
|
||||
ip_protocol = "tcp"
|
||||
referenced_security_group_id = aws_security_group.app[0].id
|
||||
|
||||
tags = { Name = "from-app-tier" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "db_from_cidr" {
|
||||
count = var.create_db_tier && !var.create_app_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.db[0].id
|
||||
description = "Database port from VPC"
|
||||
from_port = var.db_port
|
||||
to_port = var.db_port
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = local.vpc_cidr
|
||||
|
||||
tags = { Name = "from-vpc" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "db_all" {
|
||||
count = var.create_db_tier ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.db[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Bastion Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "bastion" {
|
||||
count = var.create_bastion ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-bastion-"
|
||||
description = "Bastion host - SSH from allowed CIDRs"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-bastion"
|
||||
Tier = "bastion"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "bastion_ssh" {
|
||||
for_each = var.create_bastion ? toset(var.allowed_ssh_cidrs) : []
|
||||
|
||||
security_group_id = aws_security_group.bastion[0].id
|
||||
description = "SSH from ${each.value}"
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = each.value
|
||||
|
||||
tags = { Name = "ssh-from-${replace(each.value, "/", "-")}" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "bastion_all" {
|
||||
count = var.create_bastion ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.bastion[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# VPC Endpoints Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "endpoints" {
|
||||
count = var.create_endpoints ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-endpoints-"
|
||||
description = "VPC Endpoints - HTTPS from VPC"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-endpoints"
|
||||
Tier = "endpoints"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "endpoints_https" {
|
||||
count = var.create_endpoints ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.endpoints[0].id
|
||||
description = "HTTPS from VPC"
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = local.vpc_cidr
|
||||
|
||||
tags = { Name = "https-from-vpc" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "endpoints_all" {
|
||||
count = var.create_endpoints ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.endpoints[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# EKS Cluster Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "eks_cluster" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-eks-cluster-"
|
||||
description = "EKS cluster control plane"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-eks-cluster"
|
||||
Tier = "eks"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "eks_cluster_https" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.eks_cluster[0].id
|
||||
description = "HTTPS from VPC (kubectl)"
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
ip_protocol = "tcp"
|
||||
cidr_ipv4 = local.vpc_cidr
|
||||
|
||||
tags = { Name = "https-from-vpc" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "eks_cluster_all" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.eks_cluster[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# EKS Nodes Security Group
|
||||
################################################################################
|
||||
|
||||
resource "aws_security_group" "eks_nodes" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
name_prefix = "${var.name_prefix}-eks-nodes-"
|
||||
description = "EKS worker nodes"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
tags = merge(var.tags, {
|
||||
Name = "${var.name_prefix}-eks-nodes"
|
||||
Tier = "eks"
|
||||
"kubernetes.io/cluster/${var.name_prefix}" = "owned"
|
||||
})
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "eks_nodes_self" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.eks_nodes[0].id
|
||||
description = "Node to node communication"
|
||||
ip_protocol = "-1"
|
||||
referenced_security_group_id = aws_security_group.eks_nodes[0].id
|
||||
|
||||
tags = { Name = "node-to-node" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_ingress_rule" "eks_nodes_cluster" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.eks_nodes[0].id
|
||||
description = "From cluster control plane"
|
||||
from_port = 1025
|
||||
to_port = 65535
|
||||
ip_protocol = "tcp"
|
||||
referenced_security_group_id = aws_security_group.eks_cluster[0].id
|
||||
|
||||
tags = { Name = "from-cluster" }
|
||||
}
|
||||
|
||||
resource "aws_vpc_security_group_egress_rule" "eks_nodes_all" {
|
||||
count = var.create_eks ? 1 : 0
|
||||
|
||||
security_group_id = aws_security_group.eks_nodes[0].id
|
||||
description = "Allow all outbound"
|
||||
ip_protocol = "-1"
|
||||
cidr_ipv4 = "0.0.0.0/0"
|
||||
|
||||
tags = { Name = "all-egress" }
|
||||
}
|
||||
51
terraform/modules/security-groups/outputs.tf
Normal file
51
terraform/modules/security-groups/outputs.tf
Normal file
@@ -0,0 +1,51 @@
|
||||
################################################################################
|
||||
# Security Groups - Outputs
|
||||
################################################################################
|
||||
|
||||
output "web_tier_sg_id" {
|
||||
value = try(aws_security_group.web[0].id, null)
|
||||
description = "Web tier security group ID"
|
||||
}
|
||||
|
||||
output "app_tier_sg_id" {
|
||||
value = try(aws_security_group.app[0].id, null)
|
||||
description = "App tier security group ID"
|
||||
}
|
||||
|
||||
output "db_tier_sg_id" {
|
||||
value = try(aws_security_group.db[0].id, null)
|
||||
description = "Database tier security group ID"
|
||||
}
|
||||
|
||||
output "bastion_sg_id" {
|
||||
value = try(aws_security_group.bastion[0].id, null)
|
||||
description = "Bastion security group ID"
|
||||
}
|
||||
|
||||
output "endpoints_sg_id" {
|
||||
value = try(aws_security_group.endpoints[0].id, null)
|
||||
description = "VPC endpoints security group ID"
|
||||
}
|
||||
|
||||
output "eks_cluster_sg_id" {
|
||||
value = try(aws_security_group.eks_cluster[0].id, null)
|
||||
description = "EKS cluster security group ID"
|
||||
}
|
||||
|
||||
output "eks_nodes_sg_id" {
|
||||
value = try(aws_security_group.eks_nodes[0].id, null)
|
||||
description = "EKS nodes security group ID"
|
||||
}
|
||||
|
||||
output "all_sg_ids" {
|
||||
value = {
|
||||
web = try(aws_security_group.web[0].id, null)
|
||||
app = try(aws_security_group.app[0].id, null)
|
||||
db = try(aws_security_group.db[0].id, null)
|
||||
bastion = try(aws_security_group.bastion[0].id, null)
|
||||
endpoints = try(aws_security_group.endpoints[0].id, null)
|
||||
eks_cluster = try(aws_security_group.eks_cluster[0].id, null)
|
||||
eks_nodes = try(aws_security_group.eks_nodes[0].id, null)
|
||||
}
|
||||
description = "Map of all security group IDs"
|
||||
}
|
||||
79
terraform/modules/security-groups/variables.tf
Normal file
79
terraform/modules/security-groups/variables.tf
Normal file
@@ -0,0 +1,79 @@
|
||||
################################################################################
|
||||
# Security Groups - Input Variables
|
||||
################################################################################
|
||||
|
||||
variable "vpc_id" {
|
||||
type = string
|
||||
description = "VPC ID to create security groups in"
|
||||
}
|
||||
|
||||
variable "name_prefix" {
|
||||
type = string
|
||||
description = "Prefix for security group names"
|
||||
}
|
||||
|
||||
variable "create_web_tier" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Create web tier security group"
|
||||
}
|
||||
|
||||
variable "create_app_tier" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Create application tier security group"
|
||||
}
|
||||
|
||||
variable "create_db_tier" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Create database tier security group"
|
||||
}
|
||||
|
||||
variable "create_bastion" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Create bastion host security group"
|
||||
}
|
||||
|
||||
variable "create_endpoints" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Create VPC endpoints security group"
|
||||
}
|
||||
|
||||
variable "create_eks" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Create EKS cluster and node security groups"
|
||||
}
|
||||
|
||||
variable "web_ingress_cidr" {
|
||||
type = string
|
||||
default = "0.0.0.0/0"
|
||||
description = "CIDR for web tier ingress (use ALB SG for production)"
|
||||
}
|
||||
|
||||
variable "app_port" {
|
||||
type = number
|
||||
default = 8080
|
||||
description = "Application port for app tier"
|
||||
}
|
||||
|
||||
variable "db_port" {
|
||||
type = number
|
||||
default = 5432
|
||||
description = "Database port (5432=PostgreSQL, 3306=MySQL)"
|
||||
}
|
||||
|
||||
variable "allowed_ssh_cidrs" {
|
||||
type = list(string)
|
||||
default = []
|
||||
description = "CIDRs allowed SSH access to bastion"
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
type = map(string)
|
||||
default = {}
|
||||
description = "Tags to apply to security groups"
|
||||
}
|
||||
Reference in New Issue
Block a user