code-server/terraform/modules/security/main.tf
Claude b8094ac6a0
Add comprehensive Terraform infrastructure for code-server deployment on AWS
This commit adds complete Terraform infrastructure as code for deploying
code-server on both EC2 and EKS platforms with enterprise-grade security
and SAML/OIDC authentication.

Features:
- EC2 deployment with Auto Scaling Groups and Application Load Balancer
- EKS deployment with managed node groups and AWS Load Balancer Controller
- Private network setup with VPC, private subnets, and NAT gateways
- SAML/OIDC authentication using OAuth2 Proxy
- Security hardening:
  - KMS encryption for data at rest
  - TLS encryption in transit
  - IAM roles with least privilege
  - Security groups with minimal access
  - VPC Flow Logs
  - IMDSv2 enforcement
- Auto-scaling capabilities for both EC2 and EKS
- CloudWatch logging and monitoring
- Automated deployment scripts

Terraform Modules:
- modules/vpc: VPC with public/private subnets, NAT, and VPC endpoints
- modules/security: Security groups, IAM roles, and KMS keys
- modules/ec2: EC2 Auto Scaling deployment with ALB
- modules/eks: EKS cluster with managed node groups and addons

Deployments:
- deployments/ec2: EC2 deployment configuration
- deployments/eks: EKS deployment configuration with Kubernetes manifests

Documentation:
- README.md: Comprehensive deployment and operations guide
- QUICK-START.md: Quick reference for fast deployment
- SAML-SETUP-GUIDE.md: Step-by-step IdP configuration guide

Scripts:
- scripts/deploy-ec2.sh: Automated EC2 deployment
- scripts/deploy-eks.sh: Automated EKS deployment
- scripts/destroy-ec2.sh: EC2 cleanup
- scripts/destroy-eks.sh: EKS cleanup
2025-11-15 17:29:42 +00:00

334 lines
8 KiB
HCL

# Security Module for Code-Server
# Creates security groups, IAM roles, and ACM certificates
# Security Group for ALB
resource "aws_security_group" "alb" {
name_prefix = "${var.name_prefix}-alb-"
description = "Security group for Application Load Balancer"
vpc_id = var.vpc_id
ingress {
description = "HTTPS from anywhere"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = var.allowed_cidr_blocks
}
ingress {
description = "HTTP from anywhere (redirect to HTTPS)"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = var.allowed_cidr_blocks
}
egress {
description = "Allow all outbound"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(
var.tags,
{
Name = "${var.name_prefix}-alb-sg"
}
)
lifecycle {
create_before_destroy = true
}
}
# Security Group for EC2 Code-Server instances
resource "aws_security_group" "code_server_ec2" {
name_prefix = "${var.name_prefix}-code-server-ec2-"
description = "Security group for Code-Server EC2 instances"
vpc_id = var.vpc_id
ingress {
description = "Code-Server port from ALB"
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
ingress {
description = "OAuth2 Proxy from ALB"
from_port = 4180
to_port = 4180
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
ingress {
description = "SSH from bastion (if needed)"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = var.ssh_allowed_cidr_blocks
}
egress {
description = "Allow all outbound"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(
var.tags,
{
Name = "${var.name_prefix}-code-server-ec2-sg"
}
)
lifecycle {
create_before_destroy = true
}
}
# Security Group for EKS Cluster
resource "aws_security_group" "eks_cluster" {
name_prefix = "${var.name_prefix}-eks-cluster-"
description = "Security group for EKS cluster control plane"
vpc_id = var.vpc_id
egress {
description = "Allow all outbound"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(
var.tags,
{
Name = "${var.name_prefix}-eks-cluster-sg"
}
)
lifecycle {
create_before_destroy = true
}
}
# Security Group for EKS Nodes
resource "aws_security_group" "eks_nodes" {
name_prefix = "${var.name_prefix}-eks-nodes-"
description = "Security group for EKS worker nodes"
vpc_id = var.vpc_id
ingress {
description = "Allow nodes to communicate with each other"
from_port = 0
to_port = 65535
protocol = "tcp"
self = true
}
ingress {
description = "Allow pods to communicate with the cluster API Server"
from_port = 443
to_port = 443
protocol = "tcp"
security_groups = [aws_security_group.eks_cluster.id]
}
ingress {
description = "Allow ALB to reach pods"
from_port = 0
to_port = 65535
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
description = "Allow all outbound"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(
var.tags,
{
Name = "${var.name_prefix}-eks-nodes-sg"
}
)
lifecycle {
create_before_destroy = true
}
}
# Allow EKS control plane to communicate with nodes
resource "aws_security_group_rule" "cluster_to_nodes" {
description = "Allow control plane to communicate with worker nodes"
from_port = 1025
to_port = 65535
protocol = "tcp"
security_group_id = aws_security_group.eks_nodes.id
source_security_group_id = aws_security_group.eks_cluster.id
type = "ingress"
}
# IAM Role for EC2 Code-Server instances
resource "aws_iam_role" "code_server_ec2" {
name = "${var.name_prefix}-code-server-ec2-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
tags = var.tags
}
# IAM Instance Profile for EC2
resource "aws_iam_instance_profile" "code_server_ec2" {
name = "${var.name_prefix}-code-server-ec2-profile"
role = aws_iam_role.code_server_ec2.name
tags = var.tags
}
# Attach SSM policy for Systems Manager access
resource "aws_iam_role_policy_attachment" "code_server_ec2_ssm" {
role = aws_iam_role.code_server_ec2.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
# Attach CloudWatch policy for logging
resource "aws_iam_role_policy_attachment" "code_server_ec2_cloudwatch" {
role = aws_iam_role.code_server_ec2.name
policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
}
# Custom policy for ECR access (to pull container images)
resource "aws_iam_role_policy" "code_server_ec2_ecr" {
name = "${var.name_prefix}-code-server-ec2-ecr-policy"
role = aws_iam_role.code_server_ec2.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
]
Resource = "*"
}
]
})
}
# IAM Role for EKS Cluster
resource "aws_iam_role" "eks_cluster" {
name = "${var.name_prefix}-eks-cluster-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "eks.amazonaws.com"
}
}
]
})
tags = var.tags
}
# Attach required policies for EKS cluster
resource "aws_iam_role_policy_attachment" "eks_cluster_policy" {
role = aws_iam_role.eks_cluster.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
}
resource "aws_iam_role_policy_attachment" "eks_vpc_resource_controller" {
role = aws_iam_role.eks_cluster.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
}
# IAM Role for EKS Node Group
resource "aws_iam_role" "eks_nodes" {
name = "${var.name_prefix}-eks-nodes-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
tags = var.tags
}
# Attach required policies for EKS nodes
resource "aws_iam_role_policy_attachment" "eks_worker_node_policy" {
role = aws_iam_role.eks_nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
}
resource "aws_iam_role_policy_attachment" "eks_cni_policy" {
role = aws_iam_role.eks_nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
}
resource "aws_iam_role_policy_attachment" "eks_container_registry_policy" {
role = aws_iam_role.eks_nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}
resource "aws_iam_role_policy_attachment" "eks_ssm_policy" {
role = aws_iam_role.eks_nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
# KMS Key for encryption at rest
resource "aws_kms_key" "code_server" {
description = "KMS key for Code-Server encryption"
deletion_window_in_days = 10
enable_key_rotation = true
tags = merge(
var.tags,
{
Name = "${var.name_prefix}-kms-key"
}
)
}
resource "aws_kms_alias" "code_server" {
name = "alias/${var.name_prefix}-code-server"
target_key_id = aws_kms_key.code_server.key_id
}