"Invalid value for module argument" 包含 CIDR 块列表

"Invalid value for module argument" with list of CIDR blocks

我正在尝试向 cloudposse 添加多个规则 security group。这是相关代码:

module "subnets" {
  source = "cloudposse/dynamic-subnets/aws"
  version = "0.39.8"

  vpc_id              = module.vpc.vpc_id
  igw_id              = module.vpc.igw_id
  cidr_block          = module.vpc.vpc_cidr_block
  availability_zones  = local.az_names
  # nat_gateway_enabled = true

  context = module.this.context
}

module "sg" {
  source = "cloudposse/security-group/aws"
  version = "0.4.3"

  attributes = ["primary"]

  rules = [
    {
      key         = "HTTP"
      type        = "ingress"
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = module.subnets.public_subnet_cidrs
      self        = null
      description = "Allow HTTP from IPs in our public subnets (which includes the ALB)"
    },
    {
      key         = "SSH"
      type        = "ingress"
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
      self        = null
      description = "Allow SSH from all IPs"
    }
  ]

  vpc_id  = module.vpc.vpc_id
  context = module.this.context
}

这是失败的:

Error: Invalid value for module argument The given value is not suitable for child module variable “rules” defined at .terraform/modules/project_module.sg/variables.tf:60,1-17: element types must all match for conversion to list.

问题是cidr_blocks。如果我用 ["0.0.0.0/0"] 替换第一个,它就可以工作。我看到 output from the aws-dynamic-subnets moduleaws_subnet.public.*.cidr_block。资源中 cidr_blocks 变量的当前值为 ["172.16.96.0/19", "172.16.128.0/19"],这对我来说确实像一个字符串列表。当我打开 terraform console 并询问 public_subnet_cidrs 的类型时,我只得到 dynamic。我尝试将输出包装在 tolist() 中,并在第二个入口规则中向 cidr_blocks 数组添加一个空字符串(以创建相同长度的列表),但都没有改变错误。

我已经成功解决了这个问题,方法是对 HTTP 规则使用 rule_matrix,然后还使用 SSH 规则的单个规则字典定义 rules,但这感觉很老套。

我做错了什么?

您可以使用 rule_maps,而不是 rules

module "sg" {
  source = "cloudposse/security-group/aws"
  version = "0.4.3"

  attributes = ["primary"]

  rules_map = {
        "HTTP" = [{
          key         = "HTTP"
          type        = "ingress"
          from_port   = 80
          to_port     = 80
          protocol    = "tcp"
          cidr_blocks = module.subnets.public_subnet_cidrs
          self        = null
          description = "Allow HTTP from IPs in our public subnets (which includes the ALB)"
        }],
       "SSH" = [{
          key         = "SSH"
          type        = "ingress"
          from_port   = 22
          to_port     = 22
          protocol    = "tcp"
          cidr_blocks = ["0.0.0.0/0"]
          self        = null
          description = "Allow SSH from all IPs"
        }
      ]
    }

  vpc_id  = module.vpc.vpc_id
  context = module.this.context
}

这比同时使用 rulesrule_matrix 更简洁一些。另外我不确定为什么只使用 rules 不起作用。我猜它对 cidr_blocks 进行了一些内部处理,并期望它们是完全相同的类型(包含 3 个 non-empty 字符串元素的列表)。