diff --git a/.changelog/36045.txt b/.changelog/36045.txt new file mode 100644 index 000000000000..4a77fcfee1cc --- /dev/null +++ b/.changelog/36045.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_wafv2_rule_group: Add `evaluation_window_sec ` argument to the `rate_based_statement` configuration block +``` + +```release-note:enhancement +resource/aws_wafv2_web_acl: Add `evaluation_window_sec ` argument to the `rate_based_statement` configuration block +``` \ No newline at end of file diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index f46c8034bbeb..a9b9b858c673 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -1505,8 +1505,9 @@ func expandRateBasedStatement(l []interface{}) *wafv2.RateBasedStatement { m := l[0].(map[string]interface{}) r := &wafv2.RateBasedStatement{ - AggregateKeyType: aws.String(m["aggregate_key_type"].(string)), - Limit: aws.Int64(int64(m["limit"].(int))), + AggregateKeyType: aws.String(m["aggregate_key_type"].(string)), + EvaluationWindowSec: aws.Int64(int64(m["evaluation_window_sec"].(int))), + Limit: aws.Int64(int64(m["limit"].(int))), } if v, ok := m["forwarded_ip_config"]; ok { @@ -2884,6 +2885,10 @@ func flattenRateBasedStatement(apiObject *wafv2.RateBasedStatement) interface{} tfMap["custom_key"] = flattenRateBasedStatementCustomKeys(apiObject.CustomKeys) } + if apiObject.EvaluationWindowSec != nil { + tfMap["evaluation_window_sec"] = int(aws.Int64Value(apiObject.EvaluationWindowSec)) + } + if apiObject.Limit != nil { tfMap["limit"] = int(aws.Int64Value(apiObject.Limit)) } diff --git a/internal/service/wafv2/rule_group_test.go b/internal/service/wafv2/rule_group_test.go index e731c235306d..8fea8f5be5f6 100644 --- a/internal/service/wafv2/rule_group_test.go +++ b/internal/service/wafv2/rule_group_test.go @@ -2053,6 +2053,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "0", "statement.0.rate_based_statement.0.aggregate_key_type": "IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "600", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2070,6 +2071,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "0", "statement.0.rate_based_statement.0.aggregate_key_type": "FORWARDED_IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "1", "statement.0.rate_based_statement.0.forwarded_ip_config.0.fallback_behavior": "MATCH", "statement.0.rate_based_statement.0.forwarded_ip_config.0.header_name": "X-Forwarded-For", @@ -2089,6 +2091,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "0", "statement.0.rate_based_statement.0.aggregate_key_type": "FORWARDED_IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "1", "statement.0.rate_based_statement.0.forwarded_ip_config.0.fallback_behavior": "NO_MATCH", "statement.0.rate_based_statement.0.forwarded_ip_config.0.header_name": "Updated", @@ -2108,6 +2111,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2135,6 +2139,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "2", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "1", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2162,6 +2167,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2188,6 +2194,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2215,6 +2222,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "2", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2242,6 +2250,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2269,6 +2278,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2296,6 +2306,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2323,6 +2334,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "5", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2340,6 +2352,7 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "0", "statement.0.rate_based_statement.0.aggregate_key_type": "IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "10000", "statement.0.rate_based_statement.0.scope_down_statement.#": "1", @@ -4719,7 +4732,8 @@ resource "aws_wafv2_rule_group" "test" { statement { rate_based_statement { - limit = 50000 + evaluation_window_sec = 600 + limit = 50000 } } diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index 285dfa548a35..129dd5b5cc6f 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -1090,6 +1090,12 @@ func rateBasedStatementSchema(level int) *schema.Schema { }, }, }, + "evaluation_window_sec": { + Type: schema.TypeInt, + Optional: true, + Default: 300, + ValidateFunc: validation.IntInSlice([]int{60, 120, 300, 600}), + }, "forwarded_ip_config": forwardedIPConfigSchema(), "limit": { Type: schema.TypeInt, diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index e9a786b08201..dc69e23a2a60 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -1063,6 +1063,7 @@ func TestAccWAFV2WebACL_RateBased_basic(t *testing.T) { "statement.#": "1", "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1085,6 +1086,7 @@ func TestAccWAFV2WebACL_RateBased_basic(t *testing.T) { "statement.#": "1", "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "600", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "10000", "statement.0.rate_based_statement.0.scope_down_statement.#": "1", @@ -1806,6 +1808,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1834,6 +1837,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "2", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "1", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1862,6 +1866,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1889,6 +1894,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1917,6 +1923,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "2", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1945,6 +1952,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -1973,6 +1981,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2001,6 +2010,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2029,6 +2039,7 @@ func TestAccWAFV2WebACL_RateBased_customKeys(t *testing.T) { "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.custom_key.#": "5", "statement.0.rate_based_statement.0.aggregate_key_type": "CUSTOM_KEYS", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "0", "statement.0.rate_based_statement.0.limit": "50000", "statement.0.rate_based_statement.0.scope_down_statement.#": "0", @@ -2073,6 +2084,7 @@ func TestAccWAFV2WebACL_RateBased_forwardedIP(t *testing.T) { "statement.#": "1", "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "FORWARDED_IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "1", "statement.0.rate_based_statement.0.forwarded_ip_config.0.fallback_behavior": "MATCH", "statement.0.rate_based_statement.0.forwarded_ip_config.0.header_name": "X-Forwarded-For", @@ -2097,6 +2109,7 @@ func TestAccWAFV2WebACL_RateBased_forwardedIP(t *testing.T) { "statement.#": "1", "statement.0.rate_based_statement.#": "1", "statement.0.rate_based_statement.0.aggregate_key_type": "FORWARDED_IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", "statement.0.rate_based_statement.0.forwarded_ip_config.#": "1", "statement.0.rate_based_statement.0.forwarded_ip_config.0.fallback_behavior": "NO_MATCH", "statement.0.rate_based_statement.0.forwarded_ip_config.0.header_name": "Updated", @@ -2722,15 +2735,16 @@ func TestAccWAFV2WebACL_RateBased_maxNested(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "name", webACLName), resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{ - "statement.#": "1", - "statement.0.rate_based_statement.#": "1", - "statement.0.rate_based_statement.0.limit": "300", - "statement.0.rate_based_statement.0.aggregate_key_type": "IP", - "statement.0.rate_based_statement.0.scope_down_statement.#": "1", - "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.#": "1", - "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.#": "1", - "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.#": "1", - "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.#": "3", + "statement.#": "1", + "statement.0.rate_based_statement.#": "1", + "statement.0.rate_based_statement.0.aggregate_key_type": "IP", + "statement.0.rate_based_statement.0.evaluation_window_sec": "300", + "statement.0.rate_based_statement.0.limit": "300", + "statement.0.rate_based_statement.0.scope_down_statement.#": "1", + "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.#": "1", + "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.#": "1", + "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.#": "1", + "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.#": "3", "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.0.regex_pattern_set_reference_statement.#": "1", "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.1.regex_match_statement.#": "1", "statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.2.ip_set_reference_statement.#": "1", @@ -5224,8 +5238,9 @@ resource "aws_wafv2_web_acl" "test" { statement { rate_based_statement { - limit = 10000 - aggregate_key_type = "IP" + limit = 10000 + aggregate_key_type = "IP" + evaluation_window_sec = 600 scope_down_statement { geo_match_statement { diff --git a/website/docs/r/wafv2_rule_group.html.markdown b/website/docs/r/wafv2_rule_group.html.markdown index 6c3a74654ccc..047ebfe66f36 100644 --- a/website/docs/r/wafv2_rule_group.html.markdown +++ b/website/docs/r/wafv2_rule_group.html.markdown @@ -506,6 +506,9 @@ The `rate_based_statement` block supports the following arguments: * `aggregate_key_type` - (Optional) Setting that indicates how to aggregate the request counts. Valid values include: `CONSTANT`, `CUSTOM_KEYS`, `FORWARDED_IP` or `IP`. Default: `IP`. * `custom_key` - (Optional) Aggregate the request counts using one or more web request components as the aggregate keys. See [`custom_key`](#custom_key-block) below for details. +* `evaluation_window_sec` - (Optional) The amount of time, in seconds, that AWS WAF should include in its request counts, looking back from the current time. Valid values are `60`, `120`, `300`, and `600`. Defaults to `300` (5 minutes). + + **NOTE:** This setting doesn't determine how often AWS WAF checks the rate, but how far back it looks each time it checks. AWS WAF checks the rate about every 10 seconds. * `forwarded_ip_config` - (Optional) The configuration for inspecting IP addresses in an HTTP header that you specify, instead of using the IP address that's reported by the web request origin. If `aggregate_key_type` is set to `FORWARDED_IP`, this block is required. See [Forwarded IP Config](#forwarded-ip-config) below for details. * `limit` - (Required) The limit on requests per 5-minute period for a single originating IP address. * `scope_down_statement` - (Optional) An optional nested statement that narrows the scope of the rate-based statement to matching web requests. This can be any nestable statement, and you can nest statements at any level below this scope-down statement. See [Statement](#statement) above for details. If `aggregate_key_type` is set to `CONSTANT`, this block is required. diff --git a/website/docs/r/wafv2_web_acl.html.markdown b/website/docs/r/wafv2_web_acl.html.markdown index 7c178a019655..1b0fac799942 100644 --- a/website/docs/r/wafv2_web_acl.html.markdown +++ b/website/docs/r/wafv2_web_acl.html.markdown @@ -664,6 +664,9 @@ The `rate_based_statement` block supports the following arguments: * `aggregate_key_type` - (Optional) Setting that indicates how to aggregate the request counts. Valid values include: `CONSTANT`, `CUSTOM_KEYS`, `FORWARDED_IP`, or `IP`. Default: `IP`. * `custom_key` - (Optional) Aggregate the request counts using one or more web request components as the aggregate keys. See [`custom_key`](#custom_key-block) below for details. +* `evaluation_window_sec` - (Optional) The amount of time, in seconds, that AWS WAF should include in its request counts, looking back from the current time. Valid values are `60`, `120`, `300`, and `600`. Defaults to `300` (5 minutes). + + **NOTE:** This setting doesn't determine how often AWS WAF checks the rate, but how far back it looks each time it checks. AWS WAF checks the rate about every 10 seconds. * `forwarded_ip_config` - (Optional) Configuration for inspecting IP addresses in an HTTP header that you specify, instead of using the IP address that's reported by the web request origin. If `aggregate_key_type` is set to `FORWARDED_IP`, this block is required. See [`forwarded_ip_config`](#forwarded_ip_config-block) below for details. * `limit` - (Required) Limit on requests per 5-minute period for a single originating IP address. * `scope_down_statement` - (Optional) Optional nested statement that narrows the scope of the rate-based statement to matching web requests. This can be any nestable statement, and you can nest statements at any level below this scope-down statement. See [`statement`](#statement-block) above for details. If `aggregate_key_type` is set to `CONSTANT`, this block is required.