Terraform批量创建多端口协议AWS FSx安全组实现方案
原有代码问题
- 存在循环引用:
local.security_rules内部引用自身的cidr_block字段,Terraform初始化阶段会直接报错 - 遍历逻辑错误:将端口、协议的遍历键当成实际端口号、协议值使用,还试图按规则维度创建安全组,最终会生成数十个无效安全组,不符合4个安全组的需求
- 资源结构不符合AWS Provider规范:没有实现安全组和入/出站规则的挂载逻辑,既没有用独立规则资源,也没有在安全组内定义规则块
- 缺失核心逻辑:没有处理端口范围解析、端口和传输协议的映射关系,双协议端口没有生成对应独立规则
可直接运行的实现方案
代码完全基于flatten函数+dynamic块实现,自动适配端口规则,单安全组入/出站规则各21条,远低于60条的配额限制。
variables.tf
variable "vpc_id" { type = string description = "安全组所属VPC的ID" } variable "security_config" { type = object({ security_groups = list(object({ name = string description = string cidr_block = string })) port_rules = object({ tcp_only = list(string) udp_only = list(string) tcp_udp_both = list(string) }) }) default = { security_groups = [ { name = "sg_1" description = "security group 1 - primary site" cidr_block = "10.1.0.0/28" }, { name = "sg_2" description = "security group 2 - secondary site" cidr_block = "10.2.0.0/28" }, { name = "sg_3" description = "security group 3 - tertiary site" cidr_block = "10.3.0.0/28" }, { name = "sg_4" description = "security group 4 - quorum site" cidr_block = "10.4.0.0/28" } ], port_rules = { tcp_only = ["135", "389", "445", "636", "3268", "3269", "5985", "9389", "49152-65535"] udp_only = ["123"] tcp_udp_both = ["53", "88", "123", "389", "464"] } } }
locals.tf
locals { # 打平所有端口+协议的组合规则 raw_rules = concat( # 仅TCP端口生成单条TCP规则 [for port in var.security_config.port_rules.tcp_only : { port = port protocol = "tcp" }], # 仅UDP端口生成单条UDP规则 [for port in var.security_config.port_rules.udp_only : { port = port protocol = "udp" }], # 双协议端口生成TCP、UDP各一条规则,用flatten打平嵌套列表 flatten([for port in var.security_config.port_rules.tcp_udp_both : [ { port = port, protocol = "tcp" }, { port = port, protocol = "udp" } ]]) ) # 标准化规则:解析端口范围,拆分from_port/to_port standard_rules = [for rule in local.raw_rules : { protocol = rule.protocol from_port = split("-", rule.port)[0] to_port = length(split("-", rule.port)) == 2 ? split("-", rule.port)[1] : split("-", rule.port)[0] }] }
main.tf
resource "aws_security_group" "fsx" { for_each = { for sg in var.security_config.security_groups : sg.name => sg } vpc_id = var.vpc_id name = each.value.name description = each.value.description # 动态生成所有入站规则 dynamic "ingress" { for_each = local.standard_rules content { from_port = ingress.value.from_port to_port = ingress.value.to_port protocol = ingress.value.protocol cidr_blocks = [each.value.cidr_block] } } # 动态生成所有出站规则,和入站规则完全一致 dynamic "egress" { for_each = local.standard_rules content { from_port = egress.value.from_port to_port = egress.value.to_port protocol = egress.value.protocol cidr_blocks = [each.value.cidr_block] } } tags = { Name = each.value.name } }
逻辑说明
- 最终生成4个独立安全组,每个安全组绑定对应站点的独立CIDR网段
- 自动识别单端口、端口范围格式,比如
49152-65535会自动配置为连续端口段 - 自动匹配端口对应的传输协议,双协议端口自动生成两条独立规则,无需手动重复编写
- 入站、出站规则复用同一份标准化配置,后续调整端口只需要修改变量中的端口列表,无需改动资源逻辑
- 单安全组入站、出站规则各21条,远低于单安全组60条规则的配额上限,无需申请配额提升
内容的提问来源于stack exchange,提问作者zibs
相关产品推荐
相关产品推荐

