You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建支持多场景配置的可复用AWS安全组Terraform模块

可复用Terraform AWS安全组模块解决方案

核心思路

将单一的端口变量重构为结构化的规则数组,每个规则独立定义端口范围、协议、来源类型(CIDR/安全组ID),通过dynamic块遍历生成对应Ingress规则,同时支持灵活的Egress规则配置,完全覆盖混合使用CIDR和安全组引用的场景。

模块实现代码

variables.tf

定义结构化规则变量,添加验证逻辑避免无效配置:

variable "name" {
  description = "安全组名称"
  type        = string
}

variable "description" {
  description = "安全组描述"
  type        = string
  default     = "Managed by Terraform"
}

variable "vpc_id" {
  description = "安全组所属VPC ID"
  type        = string
}

# 结构化Ingress规则:支持CIDR、IPv6 CIDR或安全组来源
variable "ingress_rules" {
  description = "Ingress规则列表,每个规则需指定端口、协议及至少一种来源"
  type = list(object({
    description               = string
    from_port                 = number
    to_port                   = number
    protocol                  = string
    cidr_blocks               = list(string)
    source_security_group_ids = list(string)
    ipv6_cidr_blocks          = list(string)
  }))
  default = []
  # 验证规则:确保每个规则至少有一个合法来源
  validation {
    condition     = alltrue([for r in var.ingress_rules : length(r.cidr_blocks) > 0 || length(r.source_security_group_ids) > 0 || length(r.ipv6_cidr_blocks) > 0])
    error_message = "每个Ingress规则必须指定CIDR、IPv6 CIDR或安全组来源中的至少一种。"
  }
}

# 可选默认Egress规则:开放全部出站流量
variable "egress_rules" {
  description = "Egress规则列表"
  type = list(object({
    description      = string
    from_port        = number
    to_port          = number
    protocol         = string
    cidr_blocks      = list(string)
    ipv6_cidr_blocks = list(string)
  }))
  default = [
    {
      description      = "Allow all outbound traffic"
      from_port        = 0
      to_port          = 0
      protocol         = "-1"
      cidr_blocks      = ["0.0.0.0/0"]
      ipv6_cidr_blocks = ["::/0"]
    }
  ]
}

main.tf

通过dynamic块遍历规则数组,生成安全组配置:

resource "aws_security_group" "this" {
  name        = var.name
  description = var.description
  vpc_id      = var.vpc_id

  # 动态生成Ingress规则
  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      description               = ingress.value.description
      from_port                 = ingress.value.from_port
      to_port                   = ingress.value.to_port
      protocol                  = ingress.value.protocol
      cidr_blocks               = ingress.value.cidr_blocks
      source_security_group_ids = ingress.value.source_security_group_ids
      ipv6_cidr_blocks          = ingress.value.ipv6_cidr_blocks
    }
  }

  # 动态生成Egress规则
  dynamic "egress" {
    for_each = var.egress_rules
    content {
      description      = egress.value.description
      from_port        = egress.value.from_port
      to_port          = egress.value.to_port
      protocol         = egress.value.protocol
      cidr_blocks      = egress.value.cidr_blocks
      ipv6_cidr_blocks = egress.value.ipv6_cidr_blocks
    }
  }

  tags = {
    Name = var.name
  }
}

outputs.tf

输出安全组ID/ARN,供其他资源或模块引用:

output "security_group_id" {
  description = "安全组ID"
  value       = aws_security_group.this.id
}

output "security_group_arn" {
  description = "安全组ARN"
  value       = aws_security_group.this.arn
}

模块使用示例(匹配需求场景)

调用模块创建你需要的四个安全组:

# 1. Web EC2安全组:开放80、443端口至公网
module "web_ec2_sg" {
  source = "./path/to/your/sg-module" # 替换为你的模块实际路径

  name        = "web-ec2-sg"
  description = "Web EC2安全组:允许公网访问80/443"
  vpc_id      = var.vpc_id

  ingress_rules = [
    {
      description               = "Allow HTTP from public"
      from_port                 = 80
      to_port                   = 80
      protocol                  = "tcp"
      cidr_blocks               = ["0.0.0.0/0"]
      source_security_group_ids = []
      ipv6_cidr_blocks          = ["::/0"]
    },
    {
      description               = "Allow HTTPS from public"
      from_port                 = 443
      to_port                   = 443
      protocol                  = "tcp"
      cidr_blocks               = ["0.0.0.0/0"]
      source_security_group_ids = []
      ipv6_cidr_blocks          = ["::/0"]
    }
  ]
}

# 2. App EC2安全组:开放8000端口至公网
module "app_ec2_sg" {
  source = "./path/to/your/sg-module"

  name        = "app-ec2-sg"
  description = "App EC2安全组:允许公网访问8000"
  vpc_id      = var.vpc_id

  ingress_rules = [
    {
      description               = "Allow App traffic from public"
      from_port                 = 8000
      to_port                   = 8000
      protocol                  = "tcp"
      cidr_blocks               = ["0.0.0.0/0"]
      source_security_group_ids = []
      ipv6_cidr_blocks          = ["::/0"]
    }
  ]
}

# 3. RDS安全组:开放5432端口给Web/App EC2安全组
module "rds_sg" {
  source = "./path/to/your/sg-module"

  name        = "rds-sg"
  description = "RDS安全组:仅允许Web/App EC2访问5432"
  vpc_id      = var.vpc_id

  ingress_rules = [
    {
      description               = "Allow PostgreSQL from Web/App EC2"
      from_port                 = 5432
      to_port                   = 5432
      protocol                  = "tcp"
      cidr_blocks               = []
      source_security_group_ids = [module.web_ec2_sg.security_group_id, module.app_ec2_sg.security_group_id]
      ipv6_cidr_blocks          = []
    }
  ]
}

# 4. Redis安全组:开放6379端口给Web/App EC2安全组
module "redis_sg" {
  source = "./path/to/your/sg-module"

  name        = "redis-sg"
  description = "Redis安全组:仅允许Web/App EC2访问6379"
  vpc_id      = var.vpc_id

  ingress_rules = [
    {
      description               = "Allow Redis from Web/App EC2"
      from_port                 = 6379
      to_port                   = 6379
      protocol                  = "tcp"
      cidr_blocks               = []
      source_security_group_ids = [module.web_ec2_sg.security_group_id, module.app_ec2_sg.security_group_id]
      ipv6_cidr_blocks          = []
    }
  ]
}

关键说明

  • 灵活性:每个Ingress规则可独立选择来源类型,同时支持CIDR公网访问和安全组内部访问。
  • 可复用性:模块可重复调用创建任意数量的安全组,无需修改核心代码。
  • 依赖自动处理:Terraform会自动识别安全组之间的依赖关系(如RDS安全组依赖Web/App安全组ID),无需手动配置depends_on。
  • 错误预防:变量验证逻辑避免出现无来源的无效规则。

内容的提问来源于stack exchange,提问作者Nijo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:23:12