Terraform 中用于 aws 安全组的变量值

Variable values in Terraform for aws security groups

我是 terraform 的新手,正在尝试创建一个具有入口和出口规则的 AWS 安全组。我没有对值进行硬编码并创建多个入口和出口块,而是尝试使用 terraform lookup 函数。

main.tf 文件如下所示:

provider "aws" {
  version                 = "~> 2.0"
  region                  = var.region
  profile                 = var.profile
}

resource "aws_security_group" "this" {
  name = "test-sg"
  description = "test security group"

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      description      = lookup(ingress.value, "description", null)
      from_port        = lookup(ingress.value, "from_port", null)
      to_port          = lookup(ingress.value, "to_port", null)
      protocol         = lookup(ingress.value, "protocol", null)
      cidr_blocks      = lookup(ingress.value, "cidr_blocks", null)
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "test-sg"
  }
}

variables.tf 文件看起来像这样

variable "ingress_rules" {
  default     = {
    "description" = ["For HTTP", "For SSH"]
    "from_port"   = ["80", "22"]
    "to_port"     = ["80", "22"]
    "protocol"    = ["tcp", "tcp"]
    "cidr_blocks" = ["0.0.0.0/0", "0.0.0.0/0"]
  }
  type        = map(list(string))
  description = "Security group rules"
}

当我运行terraform validate时显示配置有效,当我运行terraform plan时显示如下错误:

 ingress.value is list of string with 2 elements
 
 Invalid value for "inputMap" parameter: lookup() requires a map as the first
 argument.

花了很长时间,我还是想不出如何解决这个错误。将查找值传递到 variables.tf 文件的正确方法是什么。

您已将变量的默认值构建为五个映射,其中包含一个字符串键和一个字符串列表值。您可能想要一个包含一系列与入口规则的各种属性关联的键和值的映射。您可以相应地更新变量值,例如:

variable "ingress_rules" {
  default     = {
    "my ingress rule" = {
      "description" = "For HTTP"
      "from_port"   = "80"
      "to_port"     = "80"
      "protocol"    = "tcp"
      "cidr_blocks" = ["0.0.0.0/0"]
    },
    "my other ingress rule" = {
      "description" = "For SSH"
      "from_port"   = "22"
      "to_port"     = "22"
      "protocol"    = "tcp"
      "cidr_blocks" = ["0.0.0.0/0"]
    }
  }
  type        = map(any)
  description = "Security group rules"
}

现在,在您的 for_each 迭代器中,第一个 ingress.key 的值将是 my ingress rule,而第一个 ingress.value 的值将是您的整个地图键和字符串。以前,第一个 ingress.keydescription,第一个值是 ["For HTTP", "For SSH"]。这就是您收到该错误的原因:您无法从 ["For HTTP", "For SSH"] 列表中使用键 description 查找值。进行此变量值更新后,您应该会有预期的行为。

请注意,您可以使用对象进一步优化类型:

default = {
  "my ingress rule" = {
    description = "For HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  },
  "my other ingress rule" = {
    description = "For SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
type = map(object({
  description = string
  from_port   = number
  to_port     = number
  protocol    = string
  cidr_blocks = list(string)
}))

我会按如下方式实现它:

resource "aws_security_group" "test_security_group" {
  name = "test-sg"
  description = "test security group"

  dynamic "ingress" {
    for_each = var.sg_ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
      description = ingress.value.description
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "test security group"
  }
}

variables.tf

variable "sg_ingress_rules" {
  description = "Ingress security group rules"
  type        = map
}

my_vars.tfvars

sg_ingress_rules = {
  "1" = {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "HTTP"
  },
  "2" = {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["<my_private_ip>/32"]
    description = "SSH"
  }
}

希望对理解有帮助!