我需要设置一个模块来创建 aws 安全组,该模块可用于创建具有不同端口和 CIDR 值的多个 secuiryt 组。 例如,EC2 的安全组将需要端口 80 和 443 来连接互联网,另一个 EC2 仅需要端口 8000,对于来自 2 个 ec2 的安全组的具有端口 5432 的 rds,对于来自 2 个 ec2 的安全组的具有端口 6379 的 Redis。
dynamic "ingress" {
iterator = port
for_each = var.ingress_ports
content {
description = "HTTP connection from Web"
from_port = port.value
to_port = port.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
我尝试使用 for_each 并将端口作为值传递,但我需要一种方法来循环或从环境变量引用其他安全组。在某些情况下,CIDR 将是其他安全组中的 IP。有没有办法解决这个问题。
首先,您可以不使用
aws_security_group
资源的入口块,而是使用单独的 aws_vpc_security_group_ingress_rule
资源,这使得您使用循环的方式更加灵活,然后使用 dynamic
块。
然后,当您可以创建一个输入变量时,它不包含简单的 ip 列表,而是包含入口规则数据的复杂对象:
variable "ingress_ips" {
type = list(object({
ip = string
from_port = number
to_port = number
ip_protocol = string
}))
default = []
}
现在您可以对
aws_vpc_security_group_ingress_rule
资源使用 foreach
resource "aws_vpc_security_group_ingress_rule" "ip_ingress_rule" {
for_each = { for ip in var.ingress_ips : "${ip.ip}${ip.from_port}${ip.ip_protocol}" => ip }
security_group_id = aws_security_group.this.id
cidr_ipv4 = "${each.value.ip}"
from_port = each.value.from_port
to_port = each.value.to_port
ip_protocol = "${each.value.ip_protocol}"
depends_on = [
aws_security_group.this
]
}
将列表映射到映射并创建复杂键的棘手部分是由于 terraform 想要迭代唯一的集合:具有唯一键的集合或映射。您无法投射要设置的对象列表,因此您需要创建一个地图。
要为安全组创建规则,您只需执行相同的操作:创建一个包含对象列表的变量,其中您有一个
ip
而不是 security_group_id
,并将其映射到 referenced_security_group_id
资源中的 aws_vpc_security_group_ingress_rule
。