Terraform aws_security_group如何通过变量传入ingress和egress规则块
解决方案
1. 重构变量定义,使用可选对象属性
基于Terraform 1.3及以上版本稳定支持的optional类型约束,你可以直接在变量声明中标记可选字段并设置默认值,无需手动在传参时合并默认配置:
# variables.tf variable "sg_ingress" { type = list(object({ from_port = number to_port = number protocol = string cidr_blocks = optional(list(string), []) ipv6_cidr_blocks = optional(list(string), []) prefix_list_ids = optional(list(string), []) security_groups = optional(list(string), []) self = optional(bool, false) description = optional(string, "") })) default = [] } variable "sg_egress" { type = list(object({ from_port = number to_port = number protocol = string cidr_blocks = optional(list(string), []) ipv6_cidr_blocks = optional(list(string), []) prefix_list_ids = optional(list(string), []) security_groups = optional(list(string), []) self = optional(bool, false) description = optional(string, "") })) default = [] }
只有from_port、to_port、protocol是必填字段,其余字段未传值时会自动使用声明的默认值。
2. 用动态块生成安全组规则
直接通过dynamic块遍历传入的规则列表生成对应的ingress/egress块,空值参数会被AWS provider自动忽略,不需要额外处理:
# main.tf resource "aws_security_group" "sg" { name = "Example security group" vpc_id = var.vpc_id dynamic "ingress" { for_each = var.sg_ingress content { from_port = ingress.value.from_port to_port = ingress.value.to_port protocol = ingress.value.protocol cidr_blocks = ingress.value.cidr_blocks ipv6_cidr_blocks = ingress.value.ipv6_cidr_blocks prefix_list_ids = ingress.value.prefix_list_ids security_groups = ingress.value.security_groups self = ingress.value.self description = ingress.value.description } } dynamic "egress" { for_each = var.sg_egress content { 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 prefix_list_ids = egress.value.prefix_list_ids security_groups = egress.value.security_groups self = egress.value.self description = egress.value.description } } }
3. 简化传参逻辑
现在不需要手动合并默认值,直接按需求传入对应字段即可:
# terragrunt.hcl locals { some_sg_id = "sg-123abc456" } inputs = { sg_egress = [ { from_port = 123 to_port = 123 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] }, { from_port = 53 to_port = 53 protocol = "tcp" security_groups = [local.some_sg_id] } ] sg_ingress = [ { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["10.0.0.0/8"] } ] }
方案优势
- 移除了冗余的默认值合并逻辑,传参更简洁
- 保留了完整的类型校验能力,不会丢失类型安全
- 自动适配所有可选规则参数,无需针对不同规则做特殊处理
- 符合Terraform官方推荐的动态块使用范式
内容的提问来源于stack exchange,提问作者Jack Pettersson
相关产品推荐
相关产品推荐

