diff --git a/.changelog/35521.txt b/.changelog/35521.txt new file mode 100644 index 000000000000..b3575dbff658 --- /dev/null +++ b/.changelog/35521.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_wafv2_rule_group: Add `header_order` to `field_to_match` configuration blocks +``` + +```release-note:enhancement +resource/aws_wafv2_web_acl: Add `header_order`to `field_to_match` configuration blocks +``` \ No newline at end of file diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index 7688975bafb6..f46c8034bbeb 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -531,6 +531,10 @@ func expandFieldToMatch(l []interface{}) *wafv2.FieldToMatch { f.Cookies = expandCookies(m["cookies"].([]interface{})) } + if v, ok := m["header_order"]; ok && len(v.([]interface{})) > 0 { + f.HeaderOrder = expandHeaderOrder(m["header_order"].([]interface{})) + } + if v, ok := m["headers"]; ok && len(v.([]interface{})) > 0 { f.Headers = expandHeaders(m["headers"].([]interface{})) } @@ -907,6 +911,18 @@ func expandXSSMatchStatement(l []interface{}) *wafv2.XssMatchStatement { } } +func expandHeaderOrder(l []interface{}) *wafv2.HeaderOrder { + if len(l) == 0 || l[0] == nil { + return nil + } + + m := l[0].(map[string]interface{}) + + return &wafv2.HeaderOrder{ + OversizeHandling: aws.String(m["oversize_handling"].(string)), + } +} + func expandHeaders(l []interface{}) *wafv2.Headers { if len(l) == 0 || l[0] == nil { return nil @@ -1958,6 +1974,10 @@ func flattenFieldToMatch(f *wafv2.FieldToMatch) interface{} { m["cookies"] = flattenCookies(f.Cookies) } + if f.HeaderOrder != nil { + m["header_order"] = flattenHeaderOrder(f.HeaderOrder) + } + if f.Headers != nil { m["headers"] = flattenHeaders(f.Headers) } @@ -2287,6 +2307,18 @@ func flattenVisibilityConfig(config *wafv2.VisibilityConfig) interface{} { return []interface{}{m} } +func flattenHeaderOrder(s *wafv2.HeaderOrder) interface{} { + if s == nil { + return []interface{}{} + } + + m := map[string]interface{}{ + "oversize_handling": aws.StringValue(s.OversizeHandling), + } + + return []interface{}{m} +} + func flattenHeaders(s *wafv2.Headers) interface{} { if s == nil { return []interface{}{} diff --git a/internal/service/wafv2/rule_group_test.go b/internal/service/wafv2/rule_group_test.go index 44ccd43a6085..70a31387907e 100644 --- a/internal/service/wafv2/rule_group_test.go +++ b/internal/service/wafv2/rule_group_test.go @@ -461,7 +461,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -484,7 +486,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -512,7 +516,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_pattern.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_pattern.0.included_cookies.0": "test", "statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_pattern.0.included_cookies.1": "cookie_test", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -543,6 +549,32 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { }), ), }, + { + Config: testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeaderOrder(ruleGroupName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRuleGroupExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexache.MustCompile(`regional/rulegroup/.+$`)), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{ + "statement.#": "1", + "statement.0.byte_match_statement.#": "1", + "statement.0.byte_match_statement.0.field_to_match.#": "1", + "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "1", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.0.oversize_handling": "MATCH", + "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.single_header.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.single_query_argument.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.uri_path.#": "0", + }), + ), + }, { Config: testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeadersMatchPatternAll(ruleGroupName), Check: resource.ComposeTestCheckFunc( @@ -556,6 +588,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.oversize_handling": "MATCH", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_scope": "ALL", @@ -563,6 +596,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.all.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -585,6 +619,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.oversize_handling": "MATCH", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_scope": "ALL", @@ -594,6 +629,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.0": "session", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.1": "session-id", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -616,6 +652,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.oversize_handling": "MATCH", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_scope": "ALL", @@ -625,6 +662,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.0": "session", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.1": "session-id", "statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -651,7 +689,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "1", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -674,7 +714,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "1", @@ -697,7 +739,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -721,7 +765,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -745,7 +791,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) { "statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0", + "statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.method.#": "0", "statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0", @@ -3294,6 +3342,53 @@ resource "aws_wafv2_rule_group" "test" { `, rName) } +func testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeaderOrder(rName string) string { + return fmt.Sprintf(` +resource "aws_wafv2_rule_group" "test" { + capacity = 50 + name = %[1]q + scope = "REGIONAL" + + rule { + name = "rule-1" + priority = 1 + + action { + allow {} + } + + statement { + byte_match_statement { + search_string = "host:user-agent:accept:authorization:referer" + field_to_match { + header_order { + oversize_handling = "MATCH" + } + } + text_transformation { + priority = 0 + type = "NONE" + } + positional_constraint = "STARTS_WITH" + } + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-rule-metric-name" + sampled_requests_enabled = false + } + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-metric-name" + sampled_requests_enabled = false + } +} +`, rName) +} + func testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeadersMatchPatternAll(rName string) string { return fmt.Sprintf(` resource "aws_wafv2_rule_group" "test" { diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index be83500840a1..285dfa548a35 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -342,6 +342,7 @@ func fieldToMatchBaseSchema() *schema.Resource { "all_query_arguments": emptySchema(), "body": bodySchema(), "cookies": cookiesSchema(), + "header_order": headerOrderSchema(), "headers": headersSchema(), "ja3_fingerprint": ja3fingerprintSchema(), "json_body": jsonBodySchema(), @@ -870,6 +871,18 @@ func matchScopeSchema() *schema.Schema { } } +func headerOrderSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "oversize_handling": oversizeHandlingRequiredSchema(), + }, + }, + } +} + func headersSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index e16534cd2618..cd833fa05e71 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -127,6 +127,10 @@ func TestAccWAFV2WebACL_Update_rule(t *testing.T) { "statement.0.size_constraint_statement.0.field_to_match.0.all_query_arguments.#": "0", "statement.0.size_constraint_statement.0.field_to_match.0.body.#": "0", "statement.0.size_constraint_statement.0.field_to_match.0.cookies.#": "0", + "statement.0.size_constraint_statement.0.field_to_match.0.header_order.#": "0", + "statement.0.size_constraint_statement.0.field_to_match.0.headers.#": "0", + "statement.0.size_constraint_statement.0.field_to_match.0.ja3_fingerprint.#": "0", + "statement.0.size_constraint_statement.0.field_to_match.0.json_body.#": "0", "statement.0.size_constraint_statement.0.field_to_match.0.method.#": "0", "statement.0.size_constraint_statement.0.field_to_match.0.query_string.#": "1", "statement.0.size_constraint_statement.0.field_to_match.0.single_header.#": "0", @@ -1313,6 +1317,54 @@ func TestAccWAFV2WebACL_ByteMatchStatement_body(t *testing.T) { }) } +func TestAccWAFV2WebACL_ByteMatchStatement_headerOrder(t *testing.T) { + ctx := acctest.Context(t) + var v wafv2.WebACL + webACLName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_wafv2_web_acl.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckScopeRegional(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, wafv2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckWebACLDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccWebACLConfig_byteMatchStatementHeaderOrder(webACLName, wafv2.OversizeHandlingMatch), + Check: resource.ComposeTestCheckFunc( + testAccCheckWebACLExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexache.MustCompile(`regional/webacl/.+$`)), + resource.TestCheckResourceAttr(resourceName, "name", webACLName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{ + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "1", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.0.oversize_handling": "MATCH", + }), + ), + }, + { + Config: testAccWebACLConfig_byteMatchStatementHeaderOrder(webACLName, wafv2.OversizeHandlingNoMatch), + Check: resource.ComposeTestCheckFunc( + testAccCheckWebACLExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexache.MustCompile(`regional/webacl/.+$`)), + resource.TestCheckResourceAttr(resourceName, "name", webACLName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{ + "statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "1", + "statement.0.byte_match_statement.0.field_to_match.0.header_order.0.oversize_handling": "NO_MATCH", + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccWebACLImportStateIdFunc(resourceName), + }, + }, + }) +} + func TestAccWAFV2WebACL_GeoMatch_basic(t *testing.T) { ctx := acctest.Context(t) var v wafv2.WebACL @@ -3298,6 +3350,57 @@ resource "aws_wafv2_web_acl" "test" { `, rName, oversizeHandling) } +func testAccWebACLConfig_byteMatchStatementHeaderOrder(rName, oversizeHandling string) string { + return fmt.Sprintf(` +resource "aws_wafv2_web_acl" "test" { + name = %[1]q + description = %[1]q + scope = "REGIONAL" + + default_action { + allow {} + } + + rule { + name = "rule-1" + priority = 1 + + action { + count {} + } + + statement { + byte_match_statement { + search_string = "host:user-agent:accept:authorization:referer" + field_to_match { + header_order { + oversize_handling = %[2]q + } + } + text_transformation { + priority = 0 + type = "NONE" + } + positional_constraint = "STARTS_WITH" + } + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-rule-metric-name" + sampled_requests_enabled = false + } + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-metric-name" + sampled_requests_enabled = false + } +} +`, rName, oversizeHandling) +} + func testAccWebACLConfig_geoMatchStatement(rName, countryCodes string) string { return fmt.Sprintf(` resource "aws_wafv2_web_acl" "test" { diff --git a/website/docs/r/wafv2_rule_group.html.markdown b/website/docs/r/wafv2_rule_group.html.markdown index e263b1c04d2a..6c3a74654ccc 100644 --- a/website/docs/r/wafv2_rule_group.html.markdown +++ b/website/docs/r/wafv2_rule_group.html.markdown @@ -576,12 +576,13 @@ The part of a web request that you want AWS WAF to inspect. Include the single ` The `field_to_match` block supports the following arguments: -~> **NOTE:** Only one of `all_query_arguments`, `body`, `cookies`, `headers`, `json_body`, `method`, `query_string`, `single_header`, `single_query_argument`, or `uri_path` can be specified. +~> **NOTE:** Only one of `all_query_arguments`, `body`, `cookies`, `header_order`, `headers`, `json_body`, `method`, `query_string`, `single_header`, `single_query_argument`, or `uri_path` can be specified. An empty configuration block `{}` should be used when specifying `all_query_arguments`, `body`, `method`, or `query_string` attributes. * `all_query_arguments` - (Optional) Inspect all query arguments. * `body` - (Optional) Inspect the request body, which immediately follows the request headers. * `cookies` - (Optional) Inspect the cookies in the web request. See [Cookies](#cookies) below for details. +* `header_order` - (Optional) Inspect the request headers. See [Header Order](#header-order) below for details. * `headers` - (Optional) Inspect the request headers. See [Headers](#headers) below for details. * `json_body` - (Optional) Inspect the request body as JSON. See [JSON Body](#json-body) for details. * `method` - (Optional) Inspect the HTTP method. The method indicates the type of operation that the request is asking the origin to perform. @@ -611,6 +612,14 @@ The `ip_set_forwarded_ip_config` block supports the following arguments: * `header_name` - (Required) - The name of the HTTP header to use for the IP address. * `position` - (Required) - The position in the header to search for the IP address. Valid values include: `FIRST`, `LAST`, or `ANY`. If `ANY` is specified and the header contains more than 10 IP addresses, AWS WAFv2 inspects the last 10. +### Header Order + +Inspect a string containing the list of the request's header names, ordered as they appear in the web request that AWS WAF receives for inspection. AWS WAF generates the string and then uses that as the field to match component in its inspection. AWS WAF separates the header names in the string using colons and no added spaces, for example `host:user-agent:accept:authorization:referer`. + +The `header_order` block supports the following arguments: + +* `oversize_handling` - (Required) Oversize handling tells AWS WAF what to do with a web request when the request component that the rule inspects is over the limits. Valid values include the following: `CONTINUE`, `MATCH`, `NO_MATCH`. See the AWS [documentation](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-oversize-handling.html) for more information. + ### Headers Inspect the request headers. diff --git a/website/docs/r/wafv2_web_acl.html.markdown b/website/docs/r/wafv2_web_acl.html.markdown index b951cd06d471..ea811ee5a3b9 100644 --- a/website/docs/r/wafv2_web_acl.html.markdown +++ b/website/docs/r/wafv2_web_acl.html.markdown @@ -816,11 +816,12 @@ The part of a web request that you want AWS WAF to inspect. Include the single ` The `field_to_match` block supports the following arguments: -~> **Note** Only one of `all_query_arguments`, `body`, `cookies`, `headers`, `ja3_fingerprint`, `json_body`, `method`, `query_string`, `single_header`, `single_query_argument`, or `uri_path` can be specified. An empty configuration block `{}` should be used when specifying `all_query_arguments`, `method`, or `query_string` attributes. +~> **Note** Only one of `all_query_arguments`, `body`, `cookies`, `header_order`, `headers`, `ja3_fingerprint`, `json_body`, `method`, `query_string`, `single_header`, `single_query_argument`, or `uri_path` can be specified. An empty configuration block `{}` should be used when specifying `all_query_arguments`, `method`, or `query_string` attributes. * `all_query_arguments` - (Optional) Inspect all query arguments. * `body` - (Optional) Inspect the request body, which immediately follows the request headers. See [`body`](#body-block) below for details. * `cookies` - (Optional) Inspect the cookies in the web request. See [`cookies`](#cookies-block) below for details. +* `header_order` - (Optional) Inspect a string containing the list of the request's header names, ordered as they appear in the web request that AWS WAF receives for inspection. See [`header_order`](#header_order-block) below for details. * `headers` - (Optional) Inspect the request headers. See [`headers`](#headers-block) below for details. * `ja3_fingerprint` - (Optional) Inspect the JA3 fingerprint. See [`ja3_fingerprint`](#ja3_fingerprint-block) below for details. * `json_body` - (Optional) Inspect the request body as JSON. See [`json_body`](#json_body-block) for details. @@ -849,6 +850,14 @@ The `ip_set_forwarded_ip_config` block supports the following arguments: * `header_name` - (Required) - Name of the HTTP header to use for the IP address. * `position` - (Required) - Position in the header to search for the IP address. Valid values include: `FIRST`, `LAST`, or `ANY`. If `ANY` is specified and the header contains more than 10 IP addresses, AWS WAFv2 inspects the last 10. +### `header_order` Block + +Inspect a string containing the list of the request's header names, ordered as they appear in the web request that AWS WAF receives for inspection. AWS WAF generates the string and then uses that as the field to match component in its inspection. AWS WAF separates the header names in the string using colons and no added spaces, for example `host:user-agent:accept:authorization:referer`. + +The `header_order` block supports the following arguments: + +* `oversize_handling` - (Required) Oversize handling tells AWS WAF what to do with a web request when the request component that the rule inspects is over the limits. Valid values include the following: `CONTINUE`, `MATCH`, `NO_MATCH`. See the AWS [documentation](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-oversize-handling.html) for more information. + ### `headers` Block Inspect the request headers.