hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.64k stars 9.02k forks source link

[New Resource]: Raw AWS WAFv2 ACL rules resource #35143

Open nmguse-bighealth opened 6 months ago

nmguse-bighealth commented 6 months ago

Description

I would like to have either a new resource like aws_wafv2_web_acl/aws_wafv2_rule_group that supports entering raw JSON for WAFv2 rules, or to have those resources extended to support entering raw JSON rules instead of using the terraform blocks.

The create_web_acl API in boto3 appears to me that it could easily accept JSON, so I am hopeful that supporting this would be easy. https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/wafv2/client/create_web_acl.html

The current resources for aws_wafv2_web_acl/aws_wafv2_rule_group work fine for people who have very simple fixed rules that always function exactly the same across all instances of the resource.

However, it is next to impossible to manage any dynamic options due to the inflexibility of Terraform blocks.

For example, say you want to write rules that you'll apply across different environments, with scope down statements of varying length depending on the environment (e.g. limit by host), with some environments having exactly one match, and other environments having 2+. In order to do something like that, you'd need to do something like this (this code is probably not exactly right, I've not tested it):

# For 2 or more domains, we must wrap everything in an or statement
dynamic "or_statement" {
  for_each = length(var.domains) > 1 ? [1] : []

  content {
    dynamic "statement" {
      for_each = length(var.domains)

      content {
        byte_match_statement {
          positional_constraint = "EXACTLY"
          search_string         = statement.value

          field_to_match {
            single_header {
              name = "host"
            }
          }

          text_transformation {
            priority = 0
            type     = "LOWERCASE"
          }
        }
      }
    }
  }
}

# For only 1 domain, we cannot use an or_statement, AWS would reject the rules with a WAFInvalidParameterException
dynamic "byte_match_statement" {
  for_each = length(var.domains) == 1 ? [1] : []

  content {
    positional_constraint = "EXACTLY"
    search_string         = var.domains[0]

    field_to_match {
      single_header {
        name = "host"
      }
    }

    text_transformation {
      priority = 0
      type     = "LOWERCASE"
    }
  }
}

This is also just one simple example, WAFv2 rules have a huge number of options that all need to be written slightly differently depending on the context.

To see an example of the explosion of complexity this starts forcing someone into, in order to support some of the options in WAFv2, take a look at this module: https://github.com/umotif-public/terraform-aws-waf-webaclv2/blob/main/main.tf

The above module is attempting to try to add some dynamic rule support for this resource, but it is far from complete (many options are not supported). It is already over 6,800 lines of code.

Requested Resource(s) and/or Data Source(s)

Either something like: aws_wafv2_web_acl_raw / aws_wafv2_rule_group_raw

Or new parameters to aws_wafv2_web_acl / aws_wafv2_rule_group which support raw JSON for the rules

Potential Terraform Configuration

No response

References

No response

Would you like to implement a fix?

No

github-actions[bot] commented 6 months ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

jpke commented 2 months ago

this would be really nice to have. looks like there is another request for it, from 2022 https://github.com/hashicorp/terraform-provider-aws/issues/27519