使用 Terraform 动态创建多个 WAF 规则

问题描述

我有一段 terraform 代码,它使用 AWS 中的一组规则创建了一个 Web ACL。

provider "aws" {
  region = "eu-west-2"
}

resource "aws_wafv2_web_acl" "foo" {
    name        = "foo"
    description = "foo"
    scope       = "REGIONAL"
    default_action {
        block {}
    }
    rule {
      name = "AWS-AWSManagedRulesLinuxRuleSet"
      priority = 0
      override_action {
        count {}
      }
      statement {
        managed_rule_group_statement {
          name = "AWS-AWSManagedRulesLinuxRuleSet"
          vendor_name = "AWS"
        }
      }
      visibility_config {
        cloudwatch_metrics_enabled = false 
        metric_name                 = "foo_name"
        sampled_requests_enabled   = false
      }
    }
    rule {
      name = "AWS-AWSManagedRulessqliRuleSet"
      priority = 1
      override_action {
        count {}
      }
      statement {
        managed_rule_group_statement {
          name = "AWS-AWSManagedRulessqliRuleSet"
          vendor_name = "AWS"
        }
      }
      visibility_config {
        cloudwatch_metrics_enabled = false
        metric_name                = "foo_name"
        sampled_requests_enabled   = false
      }
    }
    tags = {
      Tag1 = "Value1"
    }
    visibility_config {
      metric_name = "foo"
      sampled_requests_enabled = false
      cloudwatch_metrics_enabled = false
    }   
}

这很好用,但添加更多规则意味着我的代码开始变得有点像一个整体。

有没有办法使用 dynamic_blocksfor_each 或其他东西在 terraform 中创建多个规则,以一种看起来更干净和干燥的方式?

解决方法

您可以像这样将 dynamicfor_each 结合使用:

定义一个变量:

variable "rules" {
  type    = list
  default = [
    {
      name = "AWS-AWSManagedRulesLinuxRuleSet"
      priority = 0
      managed_rule_group_statement_name = "AWS-AWSManagedRulesLinuxRuleSet"
      managed_rule_group_statement_vendor_name = "AWS"
      metric_name = "foo_name"
    },{
      name = "AWS-AWSManagedRulesSQLiRuleSet"
      priority = 1
      managed_rule_group_statement_name = "AWS-AWSManagedRulesSQLiRuleSet"
      managed_rule_group_statement_vendor_name = "AWS"
      metric_name = "foo_name"
    }
  ]
}

然后在资源中使用:

dynamic "rule" {
  for_each = toset(var.rules)

  content {
    name = rule.value.name
    priority = rule.value.priority
    override_action {
      count {}
    }
    statement {
      managed_rule_group_statement {
        name = rule.value.managed_rule_group_statement_name
        vendor_name = rule.value.managed_rule_group_statement_vendor_name
      }
    }
    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = rule.value.metric_name
      sampled_requests_enabled   = false
    }
  }
}

(注意:这显然替换了您之前的 rule 块。另请参阅有关 Dynamic Blocks 的文档了解更多信息。)