updates
This commit is contained in:
784
terraform/main.tf
Normal file
784
terraform/main.tf
Normal file
@@ -0,0 +1,784 @@
|
||||
# WiFi-DensePose AWS Infrastructure
|
||||
# This Terraform configuration provisions the AWS infrastructure for WiFi-DensePose
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.0"
|
||||
}
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.20"
|
||||
}
|
||||
helm = {
|
||||
source = "hashicorp/helm"
|
||||
version = "~> 2.10"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "~> 3.1"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {
|
||||
bucket = "wifi-densepose-terraform-state"
|
||||
key = "infrastructure/terraform.tfstate"
|
||||
region = "us-west-2"
|
||||
encrypt = true
|
||||
dynamodb_table = "wifi-densepose-terraform-locks"
|
||||
}
|
||||
}
|
||||
|
||||
# Configure AWS Provider
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
|
||||
default_tags {
|
||||
tags = {
|
||||
Project = "WiFi-DensePose"
|
||||
Environment = var.environment
|
||||
ManagedBy = "Terraform"
|
||||
Owner = var.owner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Data sources
|
||||
data "aws_availability_zones" "available" {
|
||||
state = "available"
|
||||
}
|
||||
|
||||
data "aws_caller_identity" "current" {}
|
||||
|
||||
# Random password for database
|
||||
resource "random_password" "db_password" {
|
||||
length = 32
|
||||
special = true
|
||||
}
|
||||
|
||||
# VPC Configuration
|
||||
resource "aws_vpc" "main" {
|
||||
cidr_block = var.vpc_cidr
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-vpc"
|
||||
}
|
||||
}
|
||||
|
||||
# Internet Gateway
|
||||
resource "aws_internet_gateway" "main" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-igw"
|
||||
}
|
||||
}
|
||||
|
||||
# Public Subnets
|
||||
resource "aws_subnet" "public" {
|
||||
count = length(var.public_subnet_cidrs)
|
||||
|
||||
vpc_id = aws_vpc.main.id
|
||||
cidr_block = var.public_subnet_cidrs[count.index]
|
||||
availability_zone = data.aws_availability_zones.available.names[count.index]
|
||||
map_public_ip_on_launch = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-public-subnet-${count.index + 1}"
|
||||
Type = "Public"
|
||||
}
|
||||
}
|
||||
|
||||
# Private Subnets
|
||||
resource "aws_subnet" "private" {
|
||||
count = length(var.private_subnet_cidrs)
|
||||
|
||||
vpc_id = aws_vpc.main.id
|
||||
cidr_block = var.private_subnet_cidrs[count.index]
|
||||
availability_zone = data.aws_availability_zones.available.names[count.index]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-private-subnet-${count.index + 1}"
|
||||
Type = "Private"
|
||||
}
|
||||
}
|
||||
|
||||
# NAT Gateway
|
||||
resource "aws_eip" "nat" {
|
||||
count = length(aws_subnet.public)
|
||||
|
||||
domain = "vpc"
|
||||
depends_on = [aws_internet_gateway.main]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-nat-eip-${count.index + 1}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_nat_gateway" "main" {
|
||||
count = length(aws_subnet.public)
|
||||
|
||||
allocation_id = aws_eip.nat[count.index].id
|
||||
subnet_id = aws_subnet.public[count.index].id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-nat-gateway-${count.index + 1}"
|
||||
}
|
||||
|
||||
depends_on = [aws_internet_gateway.main]
|
||||
}
|
||||
|
||||
# Route Tables
|
||||
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}-public-rt"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route_table" "private" {
|
||||
count = length(aws_nat_gateway.main)
|
||||
|
||||
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}-private-rt-${count.index + 1}"
|
||||
}
|
||||
}
|
||||
|
||||
# Route Table Associations
|
||||
resource "aws_route_table_association" "public" {
|
||||
count = length(aws_subnet.public)
|
||||
|
||||
subnet_id = aws_subnet.public[count.index].id
|
||||
route_table_id = aws_route_table.public.id
|
||||
}
|
||||
|
||||
resource "aws_route_table_association" "private" {
|
||||
count = length(aws_subnet.private)
|
||||
|
||||
subnet_id = aws_subnet.private[count.index].id
|
||||
route_table_id = aws_route_table.private[count.index].id
|
||||
}
|
||||
|
||||
# Security Groups
|
||||
resource "aws_security_group" "eks_cluster" {
|
||||
name_prefix = "${var.project_name}-eks-cluster"
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-eks-cluster-sg"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group" "eks_nodes" {
|
||||
name_prefix = "${var.project_name}-eks-nodes"
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
ingress {
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "tcp"
|
||||
self = true
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-eks-nodes-sg"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group" "rds" {
|
||||
name_prefix = "${var.project_name}-rds"
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
ingress {
|
||||
from_port = 5432
|
||||
to_port = 5432
|
||||
protocol = "tcp"
|
||||
security_groups = [aws_security_group.eks_nodes.id]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-rds-sg"
|
||||
}
|
||||
}
|
||||
|
||||
# EKS Cluster
|
||||
resource "aws_eks_cluster" "main" {
|
||||
name = "${var.project_name}-cluster"
|
||||
role_arn = aws_iam_role.eks_cluster.arn
|
||||
version = var.kubernetes_version
|
||||
|
||||
vpc_config {
|
||||
subnet_ids = concat(aws_subnet.public[*].id, aws_subnet.private[*].id)
|
||||
endpoint_private_access = true
|
||||
endpoint_public_access = true
|
||||
security_group_ids = [aws_security_group.eks_cluster.id]
|
||||
}
|
||||
|
||||
encryption_config {
|
||||
provider {
|
||||
key_arn = aws_kms_key.eks.arn
|
||||
}
|
||||
resources = ["secrets"]
|
||||
}
|
||||
|
||||
enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
|
||||
|
||||
depends_on = [
|
||||
aws_iam_role_policy_attachment.eks_cluster_policy,
|
||||
aws_iam_role_policy_attachment.eks_vpc_resource_controller,
|
||||
]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-eks-cluster"
|
||||
}
|
||||
}
|
||||
|
||||
# EKS Node Group
|
||||
resource "aws_eks_node_group" "main" {
|
||||
cluster_name = aws_eks_cluster.main.name
|
||||
node_group_name = "${var.project_name}-nodes"
|
||||
node_role_arn = aws_iam_role.eks_nodes.arn
|
||||
subnet_ids = aws_subnet.private[*].id
|
||||
|
||||
capacity_type = "ON_DEMAND"
|
||||
instance_types = var.node_instance_types
|
||||
|
||||
scaling_config {
|
||||
desired_size = var.node_desired_size
|
||||
max_size = var.node_max_size
|
||||
min_size = var.node_min_size
|
||||
}
|
||||
|
||||
update_config {
|
||||
max_unavailable = 1
|
||||
}
|
||||
|
||||
remote_access {
|
||||
ec2_ssh_key = var.key_pair_name
|
||||
source_security_group_ids = [aws_security_group.eks_nodes.id]
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
aws_iam_role_policy_attachment.eks_worker_node_policy,
|
||||
aws_iam_role_policy_attachment.eks_cni_policy,
|
||||
aws_iam_role_policy_attachment.eks_container_registry_policy,
|
||||
]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-eks-nodes"
|
||||
}
|
||||
}
|
||||
|
||||
# IAM Roles
|
||||
resource "aws_iam_role" "eks_cluster" {
|
||||
name = "${var.project_name}-eks-cluster-role"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Statement = [{
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "eks.amazonaws.com"
|
||||
}
|
||||
}]
|
||||
Version = "2012-10-17"
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "eks_cluster_policy" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
|
||||
role = aws_iam_role.eks_cluster.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "eks_vpc_resource_controller" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
|
||||
role = aws_iam_role.eks_cluster.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "eks_nodes" {
|
||||
name = "${var.project_name}-eks-nodes-role"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Statement = [{
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "ec2.amazonaws.com"
|
||||
}
|
||||
}]
|
||||
Version = "2012-10-17"
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "eks_worker_node_policy" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
|
||||
role = aws_iam_role.eks_nodes.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "eks_cni_policy" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
|
||||
role = aws_iam_role.eks_nodes.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "eks_container_registry_policy" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
|
||||
role = aws_iam_role.eks_nodes.name
|
||||
}
|
||||
|
||||
# KMS Key for EKS encryption
|
||||
resource "aws_kms_key" "eks" {
|
||||
description = "EKS Secret Encryption Key"
|
||||
deletion_window_in_days = 7
|
||||
enable_key_rotation = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-eks-encryption-key"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "eks" {
|
||||
name = "alias/${var.project_name}-eks"
|
||||
target_key_id = aws_kms_key.eks.key_id
|
||||
}
|
||||
|
||||
# RDS Subnet Group
|
||||
resource "aws_db_subnet_group" "main" {
|
||||
name = "${var.project_name}-db-subnet-group"
|
||||
subnet_ids = aws_subnet.private[*].id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-db-subnet-group"
|
||||
}
|
||||
}
|
||||
|
||||
# RDS Instance
|
||||
resource "aws_db_instance" "main" {
|
||||
identifier = "${var.project_name}-database"
|
||||
|
||||
engine = "postgres"
|
||||
engine_version = var.postgres_version
|
||||
instance_class = var.db_instance_class
|
||||
|
||||
allocated_storage = var.db_allocated_storage
|
||||
max_allocated_storage = var.db_max_allocated_storage
|
||||
storage_type = "gp3"
|
||||
storage_encrypted = true
|
||||
kms_key_id = aws_kms_key.rds.arn
|
||||
|
||||
db_name = var.db_name
|
||||
username = var.db_username
|
||||
password = random_password.db_password.result
|
||||
|
||||
vpc_security_group_ids = [aws_security_group.rds.id]
|
||||
db_subnet_group_name = aws_db_subnet_group.main.name
|
||||
|
||||
backup_retention_period = var.db_backup_retention_period
|
||||
backup_window = "03:00-04:00"
|
||||
maintenance_window = "sun:04:00-sun:05:00"
|
||||
|
||||
skip_final_snapshot = false
|
||||
final_snapshot_identifier = "${var.project_name}-final-snapshot-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
|
||||
|
||||
performance_insights_enabled = true
|
||||
monitoring_interval = 60
|
||||
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-database"
|
||||
}
|
||||
}
|
||||
|
||||
# KMS Key for RDS encryption
|
||||
resource "aws_kms_key" "rds" {
|
||||
description = "RDS Encryption Key"
|
||||
deletion_window_in_days = 7
|
||||
enable_key_rotation = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-rds-encryption-key"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "rds" {
|
||||
name = "alias/${var.project_name}-rds"
|
||||
target_key_id = aws_kms_key.rds.key_id
|
||||
}
|
||||
|
||||
# RDS Monitoring Role
|
||||
resource "aws_iam_role" "rds_monitoring" {
|
||||
name = "${var.project_name}-rds-monitoring-role"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Statement = [{
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "monitoring.rds.amazonaws.com"
|
||||
}
|
||||
}]
|
||||
Version = "2012-10-17"
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "rds_monitoring" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
|
||||
role = aws_iam_role.rds_monitoring.name
|
||||
}
|
||||
|
||||
# ElastiCache Subnet Group
|
||||
resource "aws_elasticache_subnet_group" "main" {
|
||||
name = "${var.project_name}-cache-subnet-group"
|
||||
subnet_ids = aws_subnet.private[*].id
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-cache-subnet-group"
|
||||
}
|
||||
}
|
||||
|
||||
# ElastiCache Redis Cluster
|
||||
resource "aws_elasticache_replication_group" "main" {
|
||||
replication_group_id = "${var.project_name}-redis"
|
||||
description = "Redis cluster for WiFi-DensePose"
|
||||
|
||||
node_type = var.redis_node_type
|
||||
port = 6379
|
||||
parameter_group_name = "default.redis7"
|
||||
|
||||
num_cache_clusters = var.redis_num_cache_nodes
|
||||
automatic_failover_enabled = var.redis_num_cache_nodes > 1
|
||||
multi_az_enabled = var.redis_num_cache_nodes > 1
|
||||
|
||||
subnet_group_name = aws_elasticache_subnet_group.main.name
|
||||
security_group_ids = [aws_security_group.redis.id]
|
||||
|
||||
at_rest_encryption_enabled = true
|
||||
transit_encryption_enabled = true
|
||||
auth_token = random_password.redis_auth_token.result
|
||||
|
||||
snapshot_retention_limit = 5
|
||||
snapshot_window = "03:00-05:00"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-redis"
|
||||
}
|
||||
}
|
||||
|
||||
# Redis Security Group
|
||||
resource "aws_security_group" "redis" {
|
||||
name_prefix = "${var.project_name}-redis"
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
ingress {
|
||||
from_port = 6379
|
||||
to_port = 6379
|
||||
protocol = "tcp"
|
||||
security_groups = [aws_security_group.eks_nodes.id]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-redis-sg"
|
||||
}
|
||||
}
|
||||
|
||||
# Redis Auth Token
|
||||
resource "random_password" "redis_auth_token" {
|
||||
length = 32
|
||||
special = false
|
||||
}
|
||||
|
||||
# S3 Bucket for application data
|
||||
resource "aws_s3_bucket" "app_data" {
|
||||
bucket = "${var.project_name}-app-data-${random_id.bucket_suffix.hex}"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-app-data"
|
||||
}
|
||||
}
|
||||
|
||||
resource "random_id" "bucket_suffix" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_versioning" "app_data" {
|
||||
bucket = aws_s3_bucket.app_data.id
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_encryption" "app_data" {
|
||||
bucket = aws_s3_bucket.app_data.id
|
||||
|
||||
server_side_encryption_configuration {
|
||||
rule {
|
||||
apply_server_side_encryption_by_default {
|
||||
kms_master_key_id = aws_kms_key.s3.arn
|
||||
sse_algorithm = "aws:kms"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_public_access_block" "app_data" {
|
||||
bucket = aws_s3_bucket.app_data.id
|
||||
|
||||
block_public_acls = true
|
||||
block_public_policy = true
|
||||
ignore_public_acls = true
|
||||
restrict_public_buckets = true
|
||||
}
|
||||
|
||||
# KMS Key for S3 encryption
|
||||
resource "aws_kms_key" "s3" {
|
||||
description = "S3 Encryption Key"
|
||||
deletion_window_in_days = 7
|
||||
enable_key_rotation = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-s3-encryption-key"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "s3" {
|
||||
name = "alias/${var.project_name}-s3"
|
||||
target_key_id = aws_kms_key.s3.key_id
|
||||
}
|
||||
|
||||
# CloudWatch Log Groups
|
||||
resource "aws_cloudwatch_log_group" "eks_cluster" {
|
||||
name = "/aws/eks/${aws_eks_cluster.main.name}/cluster"
|
||||
retention_in_days = var.log_retention_days
|
||||
kms_key_id = aws_kms_key.cloudwatch.arn
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-eks-logs"
|
||||
}
|
||||
}
|
||||
|
||||
# KMS Key for CloudWatch encryption
|
||||
resource "aws_kms_key" "cloudwatch" {
|
||||
description = "CloudWatch Logs Encryption Key"
|
||||
deletion_window_in_days = 7
|
||||
enable_key_rotation = true
|
||||
|
||||
policy = jsonencode({
|
||||
Statement = [
|
||||
{
|
||||
Sid = "Enable IAM User Permissions"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
|
||||
}
|
||||
Action = "kms:*"
|
||||
Resource = "*"
|
||||
},
|
||||
{
|
||||
Sid = "Allow CloudWatch Logs"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "logs.${var.aws_region}.amazonaws.com"
|
||||
}
|
||||
Action = [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
]
|
||||
Resource = "*"
|
||||
}
|
||||
]
|
||||
Version = "2012-10-17"
|
||||
})
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-cloudwatch-encryption-key"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "cloudwatch" {
|
||||
name = "alias/${var.project_name}-cloudwatch"
|
||||
target_key_id = aws_kms_key.cloudwatch.key_id
|
||||
}
|
||||
|
||||
# Application Load Balancer
|
||||
resource "aws_lb" "main" {
|
||||
name = "${var.project_name}-alb"
|
||||
internal = false
|
||||
load_balancer_type = "application"
|
||||
security_groups = [aws_security_group.alb.id]
|
||||
subnets = aws_subnet.public[*].id
|
||||
|
||||
enable_deletion_protection = var.environment == "production"
|
||||
|
||||
access_logs {
|
||||
bucket = aws_s3_bucket.alb_logs.bucket
|
||||
prefix = "alb-logs"
|
||||
enabled = true
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-alb"
|
||||
}
|
||||
}
|
||||
|
||||
# ALB Security Group
|
||||
resource "aws_security_group" "alb" {
|
||||
name_prefix = "${var.project_name}-alb"
|
||||
vpc_id = aws_vpc.main.id
|
||||
|
||||
ingress {
|
||||
from_port = 80
|
||||
to_port = 80
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-alb-sg"
|
||||
}
|
||||
}
|
||||
|
||||
# S3 Bucket for ALB logs
|
||||
resource "aws_s3_bucket" "alb_logs" {
|
||||
bucket = "${var.project_name}-alb-logs-${random_id.bucket_suffix.hex}"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-alb-logs"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_policy" "alb_logs" {
|
||||
bucket = aws_s3_bucket.alb_logs.id
|
||||
|
||||
policy = jsonencode({
|
||||
Statement = [
|
||||
{
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
AWS = "arn:aws:iam::${data.aws_elb_service_account.main.id}:root"
|
||||
}
|
||||
Action = "s3:PutObject"
|
||||
Resource = "${aws_s3_bucket.alb_logs.arn}/alb-logs/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "delivery.logs.amazonaws.com"
|
||||
}
|
||||
Action = "s3:PutObject"
|
||||
Resource = "${aws_s3_bucket.alb_logs.arn}/alb-logs/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
|
||||
Condition = {
|
||||
StringEquals = {
|
||||
"s3:x-amz-acl" = "bucket-owner-full-control"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "delivery.logs.amazonaws.com"
|
||||
}
|
||||
Action = "s3:GetBucketAcl"
|
||||
Resource = aws_s3_bucket.alb_logs.arn
|
||||
}
|
||||
]
|
||||
Version = "2012-10-17"
|
||||
})
|
||||
}
|
||||
|
||||
data "aws_elb_service_account" "main" {}
|
||||
|
||||
# Secrets Manager for application secrets
|
||||
resource "aws_secretsmanager_secret" "app_secrets" {
|
||||
name = "${var.project_name}-app-secrets"
|
||||
description = "Application secrets for WiFi-DensePose"
|
||||
recovery_window_in_days = 7
|
||||
kms_key_id = aws_kms_key.secrets.arn
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-app-secrets"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_secretsmanager_secret_version" "app_secrets" {
|
||||
secret_id = aws_secretsmanager_secret.app_secrets.id
|
||||
secret_string = jsonencode({
|
||||
database_url = "postgresql://${aws_db_instance.main.username}:${random_password.db_password.result}@${aws_db_instance.main.endpoint}/${aws_db_instance.main.db_name}"
|
||||
redis_url = "redis://:${random_password.redis_auth_token.result}@${aws_elasticache_replication_group.main.primary_endpoint_address}:6379"
|
||||
secret_key = random_password.app_secret_key.result
|
||||
jwt_secret = random_password.jwt_secret.result
|
||||
})
|
||||
}
|
||||
|
||||
# Additional random passwords
|
||||
resource "random_password" "app_secret_key" {
|
||||
length = 64
|
||||
special = true
|
||||
}
|
||||
|
||||
resource "random_password" "jwt_secret" {
|
||||
length = 64
|
||||
special = true
|
||||
}
|
||||
|
||||
# KMS Key for Secrets Manager
|
||||
resource "aws_kms_key" "secrets" {
|
||||
description = "Secrets Manager Encryption Key"
|
||||
deletion_window_in_days = 7
|
||||
enable_key_rotation = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-secrets-encryption-key"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "secrets" {
|
||||
name = "alias/${var.project_name}-secrets"
|
||||
target_key_id = aws_kms_key.secrets.key_id
|
||||
}
|
||||
460
terraform/outputs.tf
Normal file
460
terraform/outputs.tf
Normal file
@@ -0,0 +1,460 @@
|
||||
# WiFi-DensePose Terraform Outputs
|
||||
# This file defines outputs that can be used by other Terraform configurations or external systems
|
||||
|
||||
# VPC Outputs
|
||||
output "vpc_id" {
|
||||
description = "ID of the VPC"
|
||||
value = aws_vpc.main.id
|
||||
}
|
||||
|
||||
output "vpc_cidr_block" {
|
||||
description = "CIDR block of the VPC"
|
||||
value = aws_vpc.main.cidr_block
|
||||
}
|
||||
|
||||
output "public_subnet_ids" {
|
||||
description = "IDs of the public subnets"
|
||||
value = aws_subnet.public[*].id
|
||||
}
|
||||
|
||||
output "private_subnet_ids" {
|
||||
description = "IDs of the private subnets"
|
||||
value = aws_subnet.private[*].id
|
||||
}
|
||||
|
||||
output "internet_gateway_id" {
|
||||
description = "ID of the Internet Gateway"
|
||||
value = aws_internet_gateway.main.id
|
||||
}
|
||||
|
||||
output "nat_gateway_ids" {
|
||||
description = "IDs of the NAT Gateways"
|
||||
value = aws_nat_gateway.main[*].id
|
||||
}
|
||||
|
||||
# EKS Cluster Outputs
|
||||
output "cluster_id" {
|
||||
description = "EKS cluster ID"
|
||||
value = aws_eks_cluster.main.id
|
||||
}
|
||||
|
||||
output "cluster_arn" {
|
||||
description = "EKS cluster ARN"
|
||||
value = aws_eks_cluster.main.arn
|
||||
}
|
||||
|
||||
output "cluster_endpoint" {
|
||||
description = "Endpoint for EKS control plane"
|
||||
value = aws_eks_cluster.main.endpoint
|
||||
}
|
||||
|
||||
output "cluster_security_group_id" {
|
||||
description = "Security group ID attached to the EKS cluster"
|
||||
value = aws_eks_cluster.main.vpc_config[0].cluster_security_group_id
|
||||
}
|
||||
|
||||
output "cluster_iam_role_name" {
|
||||
description = "IAM role name associated with EKS cluster"
|
||||
value = aws_iam_role.eks_cluster.name
|
||||
}
|
||||
|
||||
output "cluster_iam_role_arn" {
|
||||
description = "IAM role ARN associated with EKS cluster"
|
||||
value = aws_iam_role.eks_cluster.arn
|
||||
}
|
||||
|
||||
output "cluster_certificate_authority_data" {
|
||||
description = "Base64 encoded certificate data required to communicate with the cluster"
|
||||
value = aws_eks_cluster.main.certificate_authority[0].data
|
||||
}
|
||||
|
||||
output "cluster_primary_security_group_id" {
|
||||
description = "The cluster primary security group ID created by the EKS cluster"
|
||||
value = aws_eks_cluster.main.vpc_config[0].cluster_security_group_id
|
||||
}
|
||||
|
||||
output "cluster_service_cidr" {
|
||||
description = "The CIDR block that Kubernetes pod and service IP addresses are assigned from"
|
||||
value = aws_eks_cluster.main.kubernetes_network_config[0].service_ipv4_cidr
|
||||
}
|
||||
|
||||
# EKS Node Group Outputs
|
||||
output "node_groups" {
|
||||
description = "EKS node groups"
|
||||
value = {
|
||||
main = {
|
||||
arn = aws_eks_node_group.main.arn
|
||||
status = aws_eks_node_group.main.status
|
||||
capacity_type = aws_eks_node_group.main.capacity_type
|
||||
instance_types = aws_eks_node_group.main.instance_types
|
||||
scaling_config = aws_eks_node_group.main.scaling_config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output "node_security_group_id" {
|
||||
description = "ID of the EKS node shared security group"
|
||||
value = aws_security_group.eks_nodes.id
|
||||
}
|
||||
|
||||
output "node_iam_role_name" {
|
||||
description = "IAM role name associated with EKS node group"
|
||||
value = aws_iam_role.eks_nodes.name
|
||||
}
|
||||
|
||||
output "node_iam_role_arn" {
|
||||
description = "IAM role ARN associated with EKS node group"
|
||||
value = aws_iam_role.eks_nodes.arn
|
||||
}
|
||||
|
||||
# Database Outputs
|
||||
output "db_instance_endpoint" {
|
||||
description = "RDS instance endpoint"
|
||||
value = aws_db_instance.main.endpoint
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "db_instance_name" {
|
||||
description = "RDS instance name"
|
||||
value = aws_db_instance.main.db_name
|
||||
}
|
||||
|
||||
output "db_instance_username" {
|
||||
description = "RDS instance root username"
|
||||
value = aws_db_instance.main.username
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "db_instance_port" {
|
||||
description = "RDS instance port"
|
||||
value = aws_db_instance.main.port
|
||||
}
|
||||
|
||||
output "db_subnet_group_id" {
|
||||
description = "RDS subnet group name"
|
||||
value = aws_db_subnet_group.main.id
|
||||
}
|
||||
|
||||
output "db_subnet_group_arn" {
|
||||
description = "RDS subnet group ARN"
|
||||
value = aws_db_subnet_group.main.arn
|
||||
}
|
||||
|
||||
output "db_instance_resource_id" {
|
||||
description = "RDS instance resource ID"
|
||||
value = aws_db_instance.main.resource_id
|
||||
}
|
||||
|
||||
output "db_instance_status" {
|
||||
description = "RDS instance status"
|
||||
value = aws_db_instance.main.status
|
||||
}
|
||||
|
||||
output "db_instance_availability_zone" {
|
||||
description = "RDS instance availability zone"
|
||||
value = aws_db_instance.main.availability_zone
|
||||
}
|
||||
|
||||
output "db_instance_backup_retention_period" {
|
||||
description = "RDS instance backup retention period"
|
||||
value = aws_db_instance.main.backup_retention_period
|
||||
}
|
||||
|
||||
# Redis Outputs
|
||||
output "redis_cluster_id" {
|
||||
description = "ElastiCache Redis cluster identifier"
|
||||
value = aws_elasticache_replication_group.main.id
|
||||
}
|
||||
|
||||
output "redis_primary_endpoint_address" {
|
||||
description = "Address of the endpoint for the primary node in the replication group"
|
||||
value = aws_elasticache_replication_group.main.primary_endpoint_address
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "redis_reader_endpoint_address" {
|
||||
description = "Address of the endpoint for the reader node in the replication group"
|
||||
value = aws_elasticache_replication_group.main.reader_endpoint_address
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "redis_port" {
|
||||
description = "Redis port"
|
||||
value = aws_elasticache_replication_group.main.port
|
||||
}
|
||||
|
||||
output "redis_subnet_group_name" {
|
||||
description = "ElastiCache subnet group name"
|
||||
value = aws_elasticache_subnet_group.main.name
|
||||
}
|
||||
|
||||
# S3 Outputs
|
||||
output "s3_bucket_id" {
|
||||
description = "S3 bucket ID for application data"
|
||||
value = aws_s3_bucket.app_data.id
|
||||
}
|
||||
|
||||
output "s3_bucket_arn" {
|
||||
description = "S3 bucket ARN for application data"
|
||||
value = aws_s3_bucket.app_data.arn
|
||||
}
|
||||
|
||||
output "s3_bucket_domain_name" {
|
||||
description = "S3 bucket domain name"
|
||||
value = aws_s3_bucket.app_data.bucket_domain_name
|
||||
}
|
||||
|
||||
output "s3_bucket_regional_domain_name" {
|
||||
description = "S3 bucket region-specific domain name"
|
||||
value = aws_s3_bucket.app_data.bucket_regional_domain_name
|
||||
}
|
||||
|
||||
output "alb_logs_bucket_id" {
|
||||
description = "S3 bucket ID for ALB logs"
|
||||
value = aws_s3_bucket.alb_logs.id
|
||||
}
|
||||
|
||||
output "alb_logs_bucket_arn" {
|
||||
description = "S3 bucket ARN for ALB logs"
|
||||
value = aws_s3_bucket.alb_logs.arn
|
||||
}
|
||||
|
||||
# Load Balancer Outputs
|
||||
output "alb_id" {
|
||||
description = "Application Load Balancer ID"
|
||||
value = aws_lb.main.id
|
||||
}
|
||||
|
||||
output "alb_arn" {
|
||||
description = "Application Load Balancer ARN"
|
||||
value = aws_lb.main.arn
|
||||
}
|
||||
|
||||
output "alb_dns_name" {
|
||||
description = "Application Load Balancer DNS name"
|
||||
value = aws_lb.main.dns_name
|
||||
}
|
||||
|
||||
output "alb_zone_id" {
|
||||
description = "Application Load Balancer zone ID"
|
||||
value = aws_lb.main.zone_id
|
||||
}
|
||||
|
||||
output "alb_security_group_id" {
|
||||
description = "Application Load Balancer security group ID"
|
||||
value = aws_security_group.alb.id
|
||||
}
|
||||
|
||||
# Security Group Outputs
|
||||
output "security_groups" {
|
||||
description = "Security groups created"
|
||||
value = {
|
||||
eks_cluster = aws_security_group.eks_cluster.id
|
||||
eks_nodes = aws_security_group.eks_nodes.id
|
||||
rds = aws_security_group.rds.id
|
||||
redis = aws_security_group.redis.id
|
||||
alb = aws_security_group.alb.id
|
||||
}
|
||||
}
|
||||
|
||||
# KMS Key Outputs
|
||||
output "kms_key_ids" {
|
||||
description = "KMS Key IDs"
|
||||
value = {
|
||||
eks = aws_kms_key.eks.id
|
||||
rds = aws_kms_key.rds.id
|
||||
s3 = aws_kms_key.s3.id
|
||||
cloudwatch = aws_kms_key.cloudwatch.id
|
||||
secrets = aws_kms_key.secrets.id
|
||||
}
|
||||
}
|
||||
|
||||
output "kms_key_arns" {
|
||||
description = "KMS Key ARNs"
|
||||
value = {
|
||||
eks = aws_kms_key.eks.arn
|
||||
rds = aws_kms_key.rds.arn
|
||||
s3 = aws_kms_key.s3.arn
|
||||
cloudwatch = aws_kms_key.cloudwatch.arn
|
||||
secrets = aws_kms_key.secrets.arn
|
||||
}
|
||||
}
|
||||
|
||||
# Secrets Manager Outputs
|
||||
output "secrets_manager_secret_id" {
|
||||
description = "Secrets Manager secret ID"
|
||||
value = aws_secretsmanager_secret.app_secrets.id
|
||||
}
|
||||
|
||||
output "secrets_manager_secret_arn" {
|
||||
description = "Secrets Manager secret ARN"
|
||||
value = aws_secretsmanager_secret.app_secrets.arn
|
||||
}
|
||||
|
||||
# CloudWatch Outputs
|
||||
output "cloudwatch_log_group_name" {
|
||||
description = "CloudWatch log group name for EKS cluster"
|
||||
value = aws_cloudwatch_log_group.eks_cluster.name
|
||||
}
|
||||
|
||||
output "cloudwatch_log_group_arn" {
|
||||
description = "CloudWatch log group ARN for EKS cluster"
|
||||
value = aws_cloudwatch_log_group.eks_cluster.arn
|
||||
}
|
||||
|
||||
# IAM Role Outputs
|
||||
output "iam_roles" {
|
||||
description = "IAM roles created"
|
||||
value = {
|
||||
eks_cluster = aws_iam_role.eks_cluster.arn
|
||||
eks_nodes = aws_iam_role.eks_nodes.arn
|
||||
rds_monitoring = aws_iam_role.rds_monitoring.arn
|
||||
}
|
||||
}
|
||||
|
||||
# Region and Account Information
|
||||
output "aws_region" {
|
||||
description = "AWS region"
|
||||
value = var.aws_region
|
||||
}
|
||||
|
||||
output "aws_account_id" {
|
||||
description = "AWS account ID"
|
||||
value = data.aws_caller_identity.current.account_id
|
||||
}
|
||||
|
||||
# Kubernetes Configuration
|
||||
output "kubeconfig" {
|
||||
description = "kubectl config as generated by the module"
|
||||
value = {
|
||||
apiVersion = "v1"
|
||||
kind = "Config"
|
||||
current_context = "terraform"
|
||||
contexts = [{
|
||||
name = "terraform"
|
||||
context = {
|
||||
cluster = "terraform"
|
||||
user = "terraform"
|
||||
}
|
||||
}]
|
||||
clusters = [{
|
||||
name = "terraform"
|
||||
cluster = {
|
||||
certificate_authority_data = aws_eks_cluster.main.certificate_authority[0].data
|
||||
server = aws_eks_cluster.main.endpoint
|
||||
}
|
||||
}]
|
||||
users = [{
|
||||
name = "terraform"
|
||||
user = {
|
||||
exec = {
|
||||
apiVersion = "client.authentication.k8s.io/v1beta1"
|
||||
command = "aws"
|
||||
args = [
|
||||
"eks",
|
||||
"get-token",
|
||||
"--cluster-name",
|
||||
aws_eks_cluster.main.name,
|
||||
"--region",
|
||||
var.aws_region,
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Connection Strings (Sensitive)
|
||||
output "database_url" {
|
||||
description = "Database connection URL"
|
||||
value = "postgresql://${aws_db_instance.main.username}:${random_password.db_password.result}@${aws_db_instance.main.endpoint}/${aws_db_instance.main.db_name}"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "redis_url" {
|
||||
description = "Redis connection URL"
|
||||
value = "redis://:${random_password.redis_auth_token.result}@${aws_elasticache_replication_group.main.primary_endpoint_address}:6379"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Application Configuration
|
||||
output "app_config" {
|
||||
description = "Application configuration values"
|
||||
value = {
|
||||
environment = var.environment
|
||||
region = var.aws_region
|
||||
vpc_id = aws_vpc.main.id
|
||||
cluster_name = aws_eks_cluster.main.name
|
||||
namespace = "wifi-densepose"
|
||||
}
|
||||
}
|
||||
|
||||
# Monitoring Configuration
|
||||
output "monitoring_config" {
|
||||
description = "Monitoring configuration"
|
||||
value = {
|
||||
log_group_name = aws_cloudwatch_log_group.eks_cluster.name
|
||||
log_retention = var.log_retention_days
|
||||
kms_key_id = aws_kms_key.cloudwatch.id
|
||||
}
|
||||
}
|
||||
|
||||
# Network Configuration Summary
|
||||
output "network_config" {
|
||||
description = "Network configuration summary"
|
||||
value = {
|
||||
vpc_id = aws_vpc.main.id
|
||||
vpc_cidr = aws_vpc.main.cidr_block
|
||||
public_subnets = aws_subnet.public[*].id
|
||||
private_subnets = aws_subnet.private[*].id
|
||||
availability_zones = aws_subnet.public[*].availability_zone
|
||||
nat_gateways = aws_nat_gateway.main[*].id
|
||||
internet_gateway = aws_internet_gateway.main.id
|
||||
}
|
||||
}
|
||||
|
||||
# Security Configuration Summary
|
||||
output "security_config" {
|
||||
description = "Security configuration summary"
|
||||
value = {
|
||||
kms_keys = {
|
||||
eks = aws_kms_key.eks.arn
|
||||
rds = aws_kms_key.rds.arn
|
||||
s3 = aws_kms_key.s3.arn
|
||||
cloudwatch = aws_kms_key.cloudwatch.arn
|
||||
secrets = aws_kms_key.secrets.arn
|
||||
}
|
||||
security_groups = {
|
||||
eks_cluster = aws_security_group.eks_cluster.id
|
||||
eks_nodes = aws_security_group.eks_nodes.id
|
||||
rds = aws_security_group.rds.id
|
||||
redis = aws_security_group.redis.id
|
||||
alb = aws_security_group.alb.id
|
||||
}
|
||||
secrets_manager = aws_secretsmanager_secret.app_secrets.arn
|
||||
}
|
||||
}
|
||||
|
||||
# Resource Tags
|
||||
output "common_tags" {
|
||||
description = "Common tags applied to resources"
|
||||
value = {
|
||||
Project = var.project_name
|
||||
Environment = var.environment
|
||||
ManagedBy = "Terraform"
|
||||
Owner = var.owner
|
||||
}
|
||||
}
|
||||
|
||||
# Deployment Information
|
||||
output "deployment_info" {
|
||||
description = "Deployment information"
|
||||
value = {
|
||||
timestamp = timestamp()
|
||||
terraform_version = ">=1.0"
|
||||
aws_region = var.aws_region
|
||||
environment = var.environment
|
||||
project_name = var.project_name
|
||||
}
|
||||
}
|
||||
458
terraform/variables.tf
Normal file
458
terraform/variables.tf
Normal file
@@ -0,0 +1,458 @@
|
||||
# WiFi-DensePose Terraform Variables
|
||||
# This file defines all configurable variables for the infrastructure
|
||||
|
||||
# General Configuration
|
||||
variable "project_name" {
|
||||
description = "Name of the project"
|
||||
type = string
|
||||
default = "wifi-densepose"
|
||||
|
||||
validation {
|
||||
condition = can(regex("^[a-z0-9-]+$", var.project_name))
|
||||
error_message = "Project name must contain only lowercase letters, numbers, and hyphens."
|
||||
}
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Environment name (dev, staging, production)"
|
||||
type = string
|
||||
default = "dev"
|
||||
|
||||
validation {
|
||||
condition = contains(["dev", "staging", "production"], var.environment)
|
||||
error_message = "Environment must be one of: dev, staging, production."
|
||||
}
|
||||
}
|
||||
|
||||
variable "owner" {
|
||||
description = "Owner of the infrastructure"
|
||||
type = string
|
||||
default = "wifi-densepose-team"
|
||||
}
|
||||
|
||||
# AWS Configuration
|
||||
variable "aws_region" {
|
||||
description = "AWS region for resources"
|
||||
type = string
|
||||
default = "us-west-2"
|
||||
}
|
||||
|
||||
# Network Configuration
|
||||
variable "vpc_cidr" {
|
||||
description = "CIDR block for VPC"
|
||||
type = string
|
||||
default = "10.0.0.0/16"
|
||||
|
||||
validation {
|
||||
condition = can(cidrhost(var.vpc_cidr, 0))
|
||||
error_message = "VPC CIDR must be a valid IPv4 CIDR block."
|
||||
}
|
||||
}
|
||||
|
||||
variable "public_subnet_cidrs" {
|
||||
description = "CIDR blocks for public subnets"
|
||||
type = list(string)
|
||||
default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
|
||||
|
||||
validation {
|
||||
condition = length(var.public_subnet_cidrs) >= 2
|
||||
error_message = "At least 2 public subnets are required for high availability."
|
||||
}
|
||||
}
|
||||
|
||||
variable "private_subnet_cidrs" {
|
||||
description = "CIDR blocks for private subnets"
|
||||
type = list(string)
|
||||
default = ["10.0.10.0/24", "10.0.20.0/24", "10.0.30.0/24"]
|
||||
|
||||
validation {
|
||||
condition = length(var.private_subnet_cidrs) >= 2
|
||||
error_message = "At least 2 private subnets are required for high availability."
|
||||
}
|
||||
}
|
||||
|
||||
# EKS Configuration
|
||||
variable "kubernetes_version" {
|
||||
description = "Kubernetes version for EKS cluster"
|
||||
type = string
|
||||
default = "1.28"
|
||||
}
|
||||
|
||||
variable "node_instance_types" {
|
||||
description = "EC2 instance types for EKS worker nodes"
|
||||
type = list(string)
|
||||
default = ["t3.medium", "t3.large"]
|
||||
}
|
||||
|
||||
variable "node_desired_size" {
|
||||
description = "Desired number of worker nodes"
|
||||
type = number
|
||||
default = 3
|
||||
|
||||
validation {
|
||||
condition = var.node_desired_size >= 2
|
||||
error_message = "Desired node size must be at least 2 for high availability."
|
||||
}
|
||||
}
|
||||
|
||||
variable "node_min_size" {
|
||||
description = "Minimum number of worker nodes"
|
||||
type = number
|
||||
default = 2
|
||||
|
||||
validation {
|
||||
condition = var.node_min_size >= 1
|
||||
error_message = "Minimum node size must be at least 1."
|
||||
}
|
||||
}
|
||||
|
||||
variable "node_max_size" {
|
||||
description = "Maximum number of worker nodes"
|
||||
type = number
|
||||
default = 10
|
||||
|
||||
validation {
|
||||
condition = var.node_max_size >= var.node_min_size
|
||||
error_message = "Maximum node size must be greater than or equal to minimum node size."
|
||||
}
|
||||
}
|
||||
|
||||
variable "key_pair_name" {
|
||||
description = "EC2 Key Pair name for SSH access to worker nodes"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Database Configuration
|
||||
variable "postgres_version" {
|
||||
description = "PostgreSQL version"
|
||||
type = string
|
||||
default = "15.4"
|
||||
}
|
||||
|
||||
variable "db_instance_class" {
|
||||
description = "RDS instance class"
|
||||
type = string
|
||||
default = "db.t3.micro"
|
||||
}
|
||||
|
||||
variable "db_allocated_storage" {
|
||||
description = "Initial allocated storage for RDS instance (GB)"
|
||||
type = number
|
||||
default = 20
|
||||
|
||||
validation {
|
||||
condition = var.db_allocated_storage >= 20
|
||||
error_message = "Allocated storage must be at least 20 GB."
|
||||
}
|
||||
}
|
||||
|
||||
variable "db_max_allocated_storage" {
|
||||
description = "Maximum allocated storage for RDS instance (GB)"
|
||||
type = number
|
||||
default = 100
|
||||
|
||||
validation {
|
||||
condition = var.db_max_allocated_storage >= var.db_allocated_storage
|
||||
error_message = "Maximum allocated storage must be greater than or equal to allocated storage."
|
||||
}
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
description = "Database name"
|
||||
type = string
|
||||
default = "wifi_densepose"
|
||||
|
||||
validation {
|
||||
condition = can(regex("^[a-zA-Z][a-zA-Z0-9_]*$", var.db_name))
|
||||
error_message = "Database name must start with a letter and contain only letters, numbers, and underscores."
|
||||
}
|
||||
}
|
||||
|
||||
variable "db_username" {
|
||||
description = "Database master username"
|
||||
type = string
|
||||
default = "wifi_admin"
|
||||
|
||||
validation {
|
||||
condition = can(regex("^[a-zA-Z][a-zA-Z0-9_]*$", var.db_username))
|
||||
error_message = "Database username must start with a letter and contain only letters, numbers, and underscores."
|
||||
}
|
||||
}
|
||||
|
||||
variable "db_backup_retention_period" {
|
||||
description = "Database backup retention period in days"
|
||||
type = number
|
||||
default = 7
|
||||
|
||||
validation {
|
||||
condition = var.db_backup_retention_period >= 1 && var.db_backup_retention_period <= 35
|
||||
error_message = "Backup retention period must be between 1 and 35 days."
|
||||
}
|
||||
}
|
||||
|
||||
# Redis Configuration
|
||||
variable "redis_node_type" {
|
||||
description = "ElastiCache Redis node type"
|
||||
type = string
|
||||
default = "cache.t3.micro"
|
||||
}
|
||||
|
||||
variable "redis_num_cache_nodes" {
|
||||
description = "Number of cache nodes in the Redis cluster"
|
||||
type = number
|
||||
default = 2
|
||||
|
||||
validation {
|
||||
condition = var.redis_num_cache_nodes >= 1
|
||||
error_message = "Number of cache nodes must be at least 1."
|
||||
}
|
||||
}
|
||||
|
||||
# Monitoring Configuration
|
||||
variable "log_retention_days" {
|
||||
description = "CloudWatch log retention period in days"
|
||||
type = number
|
||||
default = 30
|
||||
|
||||
validation {
|
||||
condition = contains([
|
||||
1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653
|
||||
], var.log_retention_days)
|
||||
error_message = "Log retention days must be a valid CloudWatch retention period."
|
||||
}
|
||||
}
|
||||
|
||||
# Security Configuration
|
||||
variable "enable_encryption" {
|
||||
description = "Enable encryption for all supported services"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "enable_deletion_protection" {
|
||||
description = "Enable deletion protection for critical resources"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
# Cost Optimization
|
||||
variable "enable_spot_instances" {
|
||||
description = "Enable spot instances for worker nodes (not recommended for production)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "enable_scheduled_scaling" {
|
||||
description = "Enable scheduled scaling for cost optimization"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
# Feature Flags
|
||||
variable "enable_gpu_nodes" {
|
||||
description = "Enable GPU-enabled worker nodes for ML workloads"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "gpu_instance_types" {
|
||||
description = "GPU instance types for ML workloads"
|
||||
type = list(string)
|
||||
default = ["g4dn.xlarge", "g4dn.2xlarge"]
|
||||
}
|
||||
|
||||
variable "enable_fargate" {
|
||||
description = "Enable AWS Fargate for serverless containers"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
# Backup and Disaster Recovery
|
||||
variable "enable_cross_region_backup" {
|
||||
description = "Enable cross-region backup for disaster recovery"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "backup_region" {
|
||||
description = "Secondary region for cross-region backups"
|
||||
type = string
|
||||
default = "us-east-1"
|
||||
}
|
||||
|
||||
# Compliance and Governance
|
||||
variable "enable_config" {
|
||||
description = "Enable AWS Config for compliance monitoring"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "enable_cloudtrail" {
|
||||
description = "Enable AWS CloudTrail for audit logging"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "enable_guardduty" {
|
||||
description = "Enable AWS GuardDuty for threat detection"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
# Application Configuration
|
||||
variable "app_replicas" {
|
||||
description = "Number of application replicas"
|
||||
type = number
|
||||
default = 3
|
||||
|
||||
validation {
|
||||
condition = var.app_replicas >= 1
|
||||
error_message = "Application replicas must be at least 1."
|
||||
}
|
||||
}
|
||||
|
||||
variable "app_cpu_request" {
|
||||
description = "CPU request for application pods"
|
||||
type = string
|
||||
default = "100m"
|
||||
}
|
||||
|
||||
variable "app_memory_request" {
|
||||
description = "Memory request for application pods"
|
||||
type = string
|
||||
default = "256Mi"
|
||||
}
|
||||
|
||||
variable "app_cpu_limit" {
|
||||
description = "CPU limit for application pods"
|
||||
type = string
|
||||
default = "500m"
|
||||
}
|
||||
|
||||
variable "app_memory_limit" {
|
||||
description = "Memory limit for application pods"
|
||||
type = string
|
||||
default = "512Mi"
|
||||
}
|
||||
|
||||
# Domain and SSL Configuration
|
||||
variable "domain_name" {
|
||||
description = "Domain name for the application"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "enable_ssl" {
|
||||
description = "Enable SSL/TLS termination"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "ssl_certificate_arn" {
|
||||
description = "ARN of the SSL certificate in ACM"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Monitoring and Alerting
|
||||
variable "enable_prometheus" {
|
||||
description = "Enable Prometheus monitoring"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "enable_grafana" {
|
||||
description = "Enable Grafana dashboards"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "enable_alertmanager" {
|
||||
description = "Enable AlertManager for notifications"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "slack_webhook_url" {
|
||||
description = "Slack webhook URL for notifications"
|
||||
type = string
|
||||
default = ""
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Development and Testing
|
||||
variable "enable_debug_mode" {
|
||||
description = "Enable debug mode for development"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "enable_test_data" {
|
||||
description = "Enable test data seeding"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
# Performance Configuration
|
||||
variable "enable_autoscaling" {
|
||||
description = "Enable horizontal pod autoscaling"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "min_replicas" {
|
||||
description = "Minimum number of replicas for autoscaling"
|
||||
type = number
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "max_replicas" {
|
||||
description = "Maximum number of replicas for autoscaling"
|
||||
type = number
|
||||
default = 10
|
||||
}
|
||||
|
||||
variable "target_cpu_utilization" {
|
||||
description = "Target CPU utilization percentage for autoscaling"
|
||||
type = number
|
||||
default = 70
|
||||
|
||||
validation {
|
||||
condition = var.target_cpu_utilization > 0 && var.target_cpu_utilization <= 100
|
||||
error_message = "Target CPU utilization must be between 1 and 100."
|
||||
}
|
||||
}
|
||||
|
||||
variable "target_memory_utilization" {
|
||||
description = "Target memory utilization percentage for autoscaling"
|
||||
type = number
|
||||
default = 80
|
||||
|
||||
validation {
|
||||
condition = var.target_memory_utilization > 0 && var.target_memory_utilization <= 100
|
||||
error_message = "Target memory utilization must be between 1 and 100."
|
||||
}
|
||||
}
|
||||
|
||||
# Local Development
|
||||
variable "local_development" {
|
||||
description = "Configuration for local development environment"
|
||||
type = object({
|
||||
enabled = bool
|
||||
skip_expensive_resources = bool
|
||||
use_local_registry = bool
|
||||
})
|
||||
default = {
|
||||
enabled = false
|
||||
skip_expensive_resources = false
|
||||
use_local_registry = false
|
||||
}
|
||||
}
|
||||
|
||||
# Tags
|
||||
variable "additional_tags" {
|
||||
description = "Additional tags to apply to all resources"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
Reference in New Issue
Block a user