0
votes

I am trying to rate limit requests to the forgot password change URL using WAFv2 rules attached to an ALB on Cloudfront.

What I think I need to do is..

Create two resources aws_wafv2_web_acl.afv2_rate_limit and another called aws_wafv2_regex_pattern_set.wafv2_password_url

Example of rate: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl

Example of regex: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_regex_pattern_set

Combine these into a rule group, call it aws_wafv2_rule_group.wafv2_rule_group_pw_rate_group

Example of group: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_rule

I've created the rate limit and the regex, but I am failing to create the rule group. I put this rule in to refer to the rate limit

    rule {
        name = "rate_limit"
        priority = 1
        action {
            block {}
        }
        statement {
            and_statement {
                statement {
                    rule_group_reference_statement {  # !!FIXME!! doesn't work
                        arn = aws_wafv2_web_acl.wafv2_rate_limit.arn
                    }
                }
           }
        }
        visibility_config {
            cloudwatch_metrics_enabled = false
            metric_name                = "password_url"
            sampled_requests_enabled   = false
        }
    }

I get the error on the rule_group_reference_statement line:

Blocks of type "rule_group_reference_statement" are not expected here.

I can attach the rule group to the ALB.

of course, the first question is whether this is even the right way to go about it?!

thanks for any thoughts.

2

2 Answers

0
votes

You can't nest a rule_group_reference_statement, for example for use inside a and_statement, not_statement or or_statement. It can only be referenced as a top-level statement within a rule.

0
votes

working!

resource "aws_wafv2_web_acl" "wafv2_alb_pw5pm_acl" {
    name        = "wafv2_alb_pw5pm-acl"
    description = "prevent brute forcing password setting or changing"
    scope       = "REGIONAL"       # if using this, no need to set provider

    default_action {
        allow {}    # pass traffic until the rules trigger a block
    }

    rule {
        name     = "rate_limit_pw5pm"
        priority = 1

        action {
            block {}
        }
        statement {
            rate_based_statement {
                #limit              = 300    # 5 per sec = 300 per min
                limit              = 100     # smallest value for testing
                aggregate_key_type = "IP"

                scope_down_statement {
                    regex_pattern_set_reference_statement {
                        arn = aws_wafv2_regex_pattern_set.wafv2_password_uri.arn
                        text_transformation {
                            priority = 1
                            type     = "NONE"
                        }
                        field_to_match {
                            uri_path {}
                        }
                    }
                }
            }

        }
        visibility_config {
            cloudwatch_metrics_enabled = true
            metric_name                = "wafv2_alb_pw5pm_acl_rule_vis"
            sampled_requests_enabled   = false
        }
    }

    visibility_config {
        cloudwatch_metrics_enabled = true
        metric_name                = "wafv2_alb_pw5pm_acl_vis"
        sampled_requests_enabled   = false
    }

    tags = {
        managedby   = "terraform"
    }
}


resource "aws_wafv2_web_acl_association" "web_acl_association_my_lb" {
    resource_arn = aws_lb.xxxxxx.arn
    web_acl_arn  = aws_wafv2_web_acl.wafv2_alb_pw5pm_acl.arn
}