- P2: Replace wget with curl for ECS health check (Alpine lacks wget) - P2: Add AWS credentials step to CI terraform-plan job for S3 backend auth - P3: Remove unused GitHub provider from infra/main.tf Co-Authored-By: Paperclip <noreply@paperclip.ing>
339 lines
7.4 KiB
HCL
339 lines
7.4 KiB
HCL
variable "environment" {
|
|
description = "Deployment environment"
|
|
type = string
|
|
}
|
|
|
|
variable "vpc_cidr" {
|
|
description = "CIDR block for VPC"
|
|
type = string
|
|
}
|
|
|
|
variable "az_count" {
|
|
description = "Number of availability zones"
|
|
type = number
|
|
}
|
|
|
|
variable "project_name" {
|
|
description = "Project name"
|
|
type = string
|
|
}
|
|
|
|
variable "kms_key_arn" {
|
|
description = "KMS key ARN for log encryption"
|
|
type = string
|
|
default = ""
|
|
}
|
|
|
|
resource "aws_vpc" "main" {
|
|
cidr_block = var.vpc_cidr
|
|
enable_dns_support = true
|
|
enable_dns_hostnames = true
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-vpc"
|
|
}
|
|
}
|
|
|
|
data "aws_availability_zones" "available" {
|
|
state = "available"
|
|
}
|
|
|
|
resource "aws_subnet" "public" {
|
|
count = var.az_count
|
|
|
|
vpc_id = aws_vpc.main.id
|
|
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
|
|
availability_zone = data.aws_availability_zones.available.names[count.index]
|
|
map_public_ip_on_launch = false
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-public-${data.aws_availability_zones.available.names[count.index]}"
|
|
"kubernetes.io/role/elb" = "1"
|
|
}
|
|
}
|
|
|
|
resource "aws_subnet" "private" {
|
|
count = var.az_count
|
|
|
|
vpc_id = aws_vpc.main.id
|
|
cidr_block = cidrsubnet(var.vpc_cidr, 8, var.az_count + count.index)
|
|
availability_zone = data.aws_availability_zones.available.names[count.index]
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-private-${data.aws_availability_zones.available.names[count.index]}"
|
|
"kubernetes.io/role/internal-elb" = "1"
|
|
}
|
|
}
|
|
|
|
resource "aws_internet_gateway" "main" {
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-igw"
|
|
}
|
|
}
|
|
|
|
resource "aws_eip" "nat" {
|
|
count = var.az_count
|
|
|
|
domain = "vpc"
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-nat-${count.index}"
|
|
}
|
|
}
|
|
|
|
resource "aws_nat_gateway" "main" {
|
|
count = var.az_count
|
|
|
|
allocation_id = aws_eip.nat[count.index].id
|
|
subnet_id = aws_subnet.public[count.index].id
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-nat-${count.index}"
|
|
}
|
|
|
|
depends_on = [aws_internet_gateway.main]
|
|
}
|
|
|
|
resource "aws_route_table" "public" {
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
route {
|
|
cidr_block = "0.0.0.0/0"
|
|
gateway_id = aws_internet_gateway.main.id
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-public-rt"
|
|
}
|
|
}
|
|
|
|
resource "aws_route_table" "private" {
|
|
count = var.az_count
|
|
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
route {
|
|
cidr_block = "0.0.0.0/0"
|
|
nat_gateway_id = aws_nat_gateway.main[count.index].id
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-private-rt-${count.index}"
|
|
}
|
|
}
|
|
|
|
resource "aws_route_table_association" "public" {
|
|
count = var.az_count
|
|
|
|
subnet_id = aws_subnet.public[count.index].id
|
|
route_table_id = aws_route_table.public.id
|
|
}
|
|
|
|
resource "aws_route_table_association" "private" {
|
|
count = var.az_count
|
|
|
|
subnet_id = aws_subnet.private[count.index].id
|
|
route_table_id = aws_route_table.private[count.index].id
|
|
}
|
|
|
|
resource "aws_security_group" "alb" {
|
|
name_prefix = "${var.project_name}-${var.environment}-alb"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 443
|
|
to_port = 443
|
|
protocol = "tcp"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
description = "HTTPS from internet"
|
|
}
|
|
|
|
ingress {
|
|
from_port = 80
|
|
to_port = 80
|
|
protocol = "tcp"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
description = "HTTP from internet (redirect)"
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-alb-sg"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "ecs" {
|
|
name_prefix = "${var.project_name}-${var.environment}-ecs"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 3000
|
|
to_port = 3003
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.alb.id]
|
|
description = "Service ports from ALB only"
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-ecs-sg"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "rds" {
|
|
name_prefix = "${var.project_name}-${var.environment}-rds"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 5432
|
|
to_port = 5432
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.ecs.id]
|
|
description = "PostgreSQL from ECS"
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-rds-sg"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "elasticache" {
|
|
name_prefix = "${var.project_name}-${var.environment}-elasticache"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 6379
|
|
to_port = 6379
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.ecs.id]
|
|
description = "Redis from ECS"
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-elasticache-sg"
|
|
}
|
|
}
|
|
|
|
resource "aws_flow_log" "main" {
|
|
iam_role_arn = aws_iam_role.flow_log.arn
|
|
log_destination = aws_cloudwatch_log_group.flow_log.arn
|
|
vpc_id = aws_vpc.main.id
|
|
traffic_type = "ALL"
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-flow-log"
|
|
}
|
|
}
|
|
|
|
resource "aws_iam_role" "flow_log" {
|
|
name = "${var.project_name}-${var.environment}-flow-log-role"
|
|
|
|
assume_role_policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Action = "sts:AssumeRole"
|
|
Effect = "Allow"
|
|
Principal = {
|
|
Service = "vpc-flow-logs.amazonaws.com"
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
resource "aws_iam_role_policy" "flow_log" {
|
|
name = "${var.project_name}-${var.environment}-flow-log-policy"
|
|
role = aws_iam_role.flow_log.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Action = [
|
|
"logs:CreateLogGroup",
|
|
"logs:CreateLogStream",
|
|
"logs:PutLogEvents",
|
|
"logs:DescribeLogGroups",
|
|
"logs:DescribeLogStreams"
|
|
]
|
|
Effect = "Allow"
|
|
Resource = [aws_cloudwatch_log_group.flow_log.arn]
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
resource "aws_cloudwatch_log_group" "flow_log" {
|
|
name = "/${var.project_name}/${var.environment}/vpc-flow-log"
|
|
retention_in_days = var.environment == "production" ? 30 : 7
|
|
kms_key_id = var.kms_key_arn != "" ? var.kms_key_arn : null
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-${var.environment}-flow-log"
|
|
}
|
|
}
|
|
|
|
output "vpc_id" {
|
|
description = "VPC ID"
|
|
value = aws_vpc.main.id
|
|
}
|
|
|
|
output "private_subnet_ids" {
|
|
description = "Private subnet IDs"
|
|
value = aws_subnet.private[*].id
|
|
}
|
|
|
|
output "public_subnet_ids" {
|
|
description = "Public subnet IDs"
|
|
value = aws_subnet.public[*].id
|
|
}
|
|
|
|
output "alb_security_group_id" {
|
|
description = "ALB security group ID"
|
|
value = aws_security_group.alb.id
|
|
}
|
|
|
|
output "ecs_security_group_id" {
|
|
description = "ECS security group ID"
|
|
value = aws_security_group.ecs.id
|
|
}
|
|
|
|
output "rds_security_group_id" {
|
|
description = "RDS security group ID"
|
|
value = aws_security_group.rds.id
|
|
}
|
|
|
|
output "elasticache_security_group_id" {
|
|
description = "ElastiCache security group ID"
|
|
value = aws_security_group.elasticache.id
|
|
}
|