Skip to content

Commit 60b3b69

Browse files
authored
Merge pull request #35521 from acwwat/f-aws_wafv2-header_order_support
feat: Add header_order field support to aws_wafv2_webacl and rule_group
2 parents 33b88e2 + 92b6f0c commit 60b3b69

File tree

7 files changed

+270
-2
lines changed

7 files changed

+270
-2
lines changed

.changelog/35521.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
resource/aws_wafv2_rule_group: Add `header_order` to `field_to_match` configuration blocks
3+
```
4+
5+
```release-note:enhancement
6+
resource/aws_wafv2_web_acl: Add `header_order`to `field_to_match` configuration blocks
7+
```

internal/service/wafv2/flex.go

+32
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,10 @@ func expandFieldToMatch(l []interface{}) *wafv2.FieldToMatch {
531531
f.Cookies = expandCookies(m["cookies"].([]interface{}))
532532
}
533533

534+
if v, ok := m["header_order"]; ok && len(v.([]interface{})) > 0 {
535+
f.HeaderOrder = expandHeaderOrder(m["header_order"].([]interface{}))
536+
}
537+
534538
if v, ok := m["headers"]; ok && len(v.([]interface{})) > 0 {
535539
f.Headers = expandHeaders(m["headers"].([]interface{}))
536540
}
@@ -907,6 +911,18 @@ func expandXSSMatchStatement(l []interface{}) *wafv2.XssMatchStatement {
907911
}
908912
}
909913

914+
func expandHeaderOrder(l []interface{}) *wafv2.HeaderOrder {
915+
if len(l) == 0 || l[0] == nil {
916+
return nil
917+
}
918+
919+
m := l[0].(map[string]interface{})
920+
921+
return &wafv2.HeaderOrder{
922+
OversizeHandling: aws.String(m["oversize_handling"].(string)),
923+
}
924+
}
925+
910926
func expandHeaders(l []interface{}) *wafv2.Headers {
911927
if len(l) == 0 || l[0] == nil {
912928
return nil
@@ -1958,6 +1974,10 @@ func flattenFieldToMatch(f *wafv2.FieldToMatch) interface{} {
19581974
m["cookies"] = flattenCookies(f.Cookies)
19591975
}
19601976

1977+
if f.HeaderOrder != nil {
1978+
m["header_order"] = flattenHeaderOrder(f.HeaderOrder)
1979+
}
1980+
19611981
if f.Headers != nil {
19621982
m["headers"] = flattenHeaders(f.Headers)
19631983
}
@@ -2287,6 +2307,18 @@ func flattenVisibilityConfig(config *wafv2.VisibilityConfig) interface{} {
22872307
return []interface{}{m}
22882308
}
22892309

2310+
func flattenHeaderOrder(s *wafv2.HeaderOrder) interface{} {
2311+
if s == nil {
2312+
return []interface{}{}
2313+
}
2314+
2315+
m := map[string]interface{}{
2316+
"oversize_handling": aws.StringValue(s.OversizeHandling),
2317+
}
2318+
2319+
return []interface{}{m}
2320+
}
2321+
22902322
func flattenHeaders(s *wafv2.Headers) interface{} {
22912323
if s == nil {
22922324
return []interface{}{}

internal/service/wafv2/rule_group_test.go

+95
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
461461
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "1",
462462
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
463463
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
464+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
464465
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
466+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
465467
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
466468
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
467469
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -484,7 +486,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
484486
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
485487
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "1",
486488
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
489+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
487490
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
491+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
488492
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
489493
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
490494
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -512,7 +516,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
512516
"statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_pattern.#": "1",
513517
"statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_pattern.0.included_cookies.0": "test",
514518
"statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_pattern.0.included_cookies.1": "cookie_test",
519+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
515520
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
521+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
516522
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
517523
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
518524
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -543,6 +549,32 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
543549
}),
544550
),
545551
},
552+
{
553+
Config: testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeaderOrder(ruleGroupName),
554+
Check: resource.ComposeTestCheckFunc(
555+
testAccCheckRuleGroupExists(ctx, resourceName, &v),
556+
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexache.MustCompile(`regional/rulegroup/.+$`)),
557+
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
558+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
559+
"statement.#": "1",
560+
"statement.0.byte_match_statement.#": "1",
561+
"statement.0.byte_match_statement.0.field_to_match.#": "1",
562+
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
563+
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
564+
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
565+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "1",
566+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.0.oversize_handling": "MATCH",
567+
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
568+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
569+
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
570+
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
571+
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
572+
"statement.0.byte_match_statement.0.field_to_match.0.single_header.#": "0",
573+
"statement.0.byte_match_statement.0.field_to_match.0.single_query_argument.#": "0",
574+
"statement.0.byte_match_statement.0.field_to_match.0.uri_path.#": "0",
575+
}),
576+
),
577+
},
546578
{
547579
Config: testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeadersMatchPatternAll(ruleGroupName),
548580
Check: resource.ComposeTestCheckFunc(
@@ -556,13 +588,15 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
556588
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
557589
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
558590
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
591+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
559592
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "1",
560593
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.oversize_handling": "MATCH",
561594
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_scope": "ALL",
562595
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.#": "1",
563596
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.all.#": "1",
564597
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.#": "0",
565598
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.#": "0",
599+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
566600
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
567601
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
568602
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -585,6 +619,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
585619
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
586620
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
587621
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
622+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
588623
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "1",
589624
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.oversize_handling": "MATCH",
590625
"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) {
594629
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.0": "session",
595630
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.1": "session-id",
596631
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.#": "0",
632+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
597633
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
598634
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
599635
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -616,6 +652,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
616652
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
617653
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
618654
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
655+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
619656
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "1",
620657
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.oversize_handling": "MATCH",
621658
"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) {
625662
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.0": "session",
626663
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.excluded_headers.1": "session-id",
627664
"statement.0.byte_match_statement.0.field_to_match.0.headers.0.match_pattern.0.included_headers.#": "0",
665+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
628666
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
629667
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
630668
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -651,7 +689,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
651689
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
652690
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
653691
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
692+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
654693
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
694+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
655695
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
656696
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "1",
657697
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -674,7 +714,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
674714
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
675715
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
676716
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
717+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
677718
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
719+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
678720
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
679721
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
680722
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "1",
@@ -697,7 +739,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
697739
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
698740
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
699741
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
742+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
700743
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
744+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
701745
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
702746
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
703747
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -721,7 +765,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
721765
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
722766
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
723767
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
768+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
724769
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
770+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
725771
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
726772
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
727773
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -745,7 +791,9 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
745791
"statement.0.byte_match_statement.0.field_to_match.0.all_query_arguments.#": "0",
746792
"statement.0.byte_match_statement.0.field_to_match.0.body.#": "0",
747793
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "0",
794+
"statement.0.byte_match_statement.0.field_to_match.0.header_order.#": "0",
748795
"statement.0.byte_match_statement.0.field_to_match.0.headers.#": "0",
796+
"statement.0.byte_match_statement.0.field_to_match.0.ja3_fingerprint.#": "0",
749797
"statement.0.byte_match_statement.0.field_to_match.0.json_body.#": "0",
750798
"statement.0.byte_match_statement.0.field_to_match.0.method.#": "0",
751799
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "0",
@@ -3294,6 +3342,53 @@ resource "aws_wafv2_rule_group" "test" {
32943342
`, rName)
32953343
}
32963344

3345+
func testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeaderOrder(rName string) string {
3346+
return fmt.Sprintf(`
3347+
resource "aws_wafv2_rule_group" "test" {
3348+
capacity = 50
3349+
name = %[1]q
3350+
scope = "REGIONAL"
3351+
3352+
rule {
3353+
name = "rule-1"
3354+
priority = 1
3355+
3356+
action {
3357+
allow {}
3358+
}
3359+
3360+
statement {
3361+
byte_match_statement {
3362+
search_string = "host:user-agent:accept:authorization:referer"
3363+
field_to_match {
3364+
header_order {
3365+
oversize_handling = "MATCH"
3366+
}
3367+
}
3368+
text_transformation {
3369+
priority = 0
3370+
type = "NONE"
3371+
}
3372+
positional_constraint = "STARTS_WITH"
3373+
}
3374+
}
3375+
3376+
visibility_config {
3377+
cloudwatch_metrics_enabled = false
3378+
metric_name = "friendly-rule-metric-name"
3379+
sampled_requests_enabled = false
3380+
}
3381+
}
3382+
3383+
visibility_config {
3384+
cloudwatch_metrics_enabled = false
3385+
metric_name = "friendly-metric-name"
3386+
sampled_requests_enabled = false
3387+
}
3388+
}
3389+
`, rName)
3390+
}
3391+
32973392
func testAccRuleGroupConfig_byteMatchStatementFieldToMatchHeadersMatchPatternAll(rName string) string {
32983393
return fmt.Sprintf(`
32993394
resource "aws_wafv2_rule_group" "test" {

internal/service/wafv2/schemas.go

+13
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ func fieldToMatchBaseSchema() *schema.Resource {
342342
"all_query_arguments": emptySchema(),
343343
"body": bodySchema(),
344344
"cookies": cookiesSchema(),
345+
"header_order": headerOrderSchema(),
345346
"headers": headersSchema(),
346347
"ja3_fingerprint": ja3fingerprintSchema(),
347348
"json_body": jsonBodySchema(),
@@ -870,6 +871,18 @@ func matchScopeSchema() *schema.Schema {
870871
}
871872
}
872873

874+
func headerOrderSchema() *schema.Schema {
875+
return &schema.Schema{
876+
Type: schema.TypeList,
877+
Optional: true,
878+
Elem: &schema.Resource{
879+
Schema: map[string]*schema.Schema{
880+
"oversize_handling": oversizeHandlingRequiredSchema(),
881+
},
882+
},
883+
}
884+
}
885+
873886
func headersSchema() *schema.Schema {
874887
return &schema.Schema{
875888
Type: schema.TypeList,

0 commit comments

Comments
 (0)