Search code examples
terraformterraform-provider-awsamazon-waf

How to Exclude list of variablized rules dynamically from AWS WAF Terraform resource aws_wafv2_web_acl


I am trying to Create an AWS WEB-ACL using Terraform having multiple rules, also want to exclude multiple rules from AWS Managed rulset. but I am not able to exclude multiple rules dynamically coming from variables. here is my code.

variable.tfvars

# Region
region="us-east-1"

# Environment
environment="nonprod"


# ACLs Definations
acls = {
  web: {
    AWSManagedRuleSets: [
      {
        name: "AWSManagedRulesCommonRuleSet",
        vendor_name: "AWS",
        excluded_rule: [
          "SizeRestrictions_QUERYSTRING",
          "NoUserAgent_HEADER"
        ]
      }
    ]
  },

  api: {
    AWSManagedRuleSets: [
      {
        name: "AWSManagedRulesCommonRuleSet",
        vendor_name: "AWS",
        excluded_rule: [
          "SizeRestrictions_QUERYSTRING",
          "NoUserAgent_HEADER"
        ]
      },
      {
        name: "AWSManagedRulesLinuxRuleSet",
        vendor_name: "AWS",
        excluded_rule: []
      }
    ]
  },
}

main.tf

resource "aws_wafv2_web_acl" "web_acl" {
  for_each = var.acls
  name        = "waf-web-acl-${lower(var.environment)}-${each.key}"
  description = "WAF ACL ap-${each.key} for env ${lower(var.environment)}"
  scope       = "REGIONAL"

  default_action {
    allow {}
  }


  dynamic "rule" {
    for_each = var.acls[each.key]["AWSManagedRuleSets"]
    content {
      name = rule.value.name
      priority = 0
      override_action {
        count {}
      }
      statement {
        managed_rule_group_statement {
          name        = rule.value.name
          vendor_name = rule.value.vendor_name
//    HERE I WANNA EXCLUDE ALL THE RULE LISTED IN VARIABLE
//          excluded_rule = rule.value.excluded_rule
//          excluded_rule {
//            name = "SizeRestrictions_QUERYSTRING"
//          }
//          excluded_rule {
//            name = "NoUserAgent_HEADER"
//          }
        }
      }
      visibility_config {
        cloudwatch_metrics_enabled = true
        metric_name                = "waf-rule-${lower(var.environment)}-${each.key}-${rule.value.name}"
        sampled_requests_enabled   = true
      }
    }
}

  tags = {
    ManagedBy = "Terraform"
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "waf-web-acl-${lower(var.environment)}-${each.key}"
    sampled_requests_enabled   = true
  }
}

Solution

  • I don't have access to AWS but I think it's possible with a nested block like below..

    dynamic "rule" {
        for_each = var.acls[each.key]["AWSManagedRuleSets"]
        content {
          name = rule.value.name
          priority = 0
          override_action {
            count {}
          }
          statement {
            managed_rule_group_statement {
              name        = rule.value.name
              vendor_name = rule.value.vendor_name
            }
            // another for_each loop to iterate over excluded_rule list
            dynamic "excluded_rule" {
              for_each = rule.value.excluded_rule
              content {
                name = excluded_rule.value
              }
            }
          }
          visibility_config {
            cloudwatch_metrics_enabled = true
            metric_name                = "waf-rule-${lower(var.environment)}-${each.key}-${rule.value.name}"
            sampled_requests_enabled   = true
          }
        }
    }