Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cookie match_pattern attribute to aws_wafv2_web_acl #25845

Merged
merged 26 commits into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
05e0272
implement cookie match_pattern
tiborhercz Jul 12, 2022
ea9af55
add 'cookies' to docs wafv2_rule_group
tiborhercz Jul 16, 2022
cc8fd9a
implement flatten func for wafv2
tiborhercz Jul 16, 2022
20f0ab9
add changelog
tiborhercz Jul 16, 2022
7b16927
implement test for aws_wafv2_rule_group
tiborhercz Jul 16, 2022
a0826ec
Merge branch 'hashicorp:main' into f-aws_wafv2_web_acl-add-cookies
tiborhercz Aug 23, 2022
820ac28
implement cookie match_pattern
tiborhercz Jul 12, 2022
d02559e
add 'cookies' to docs wafv2_rule_group
tiborhercz Jul 16, 2022
fb6d6d7
implement flatten func for wafv2
tiborhercz Jul 16, 2022
dd33e58
add changelog
tiborhercz Jul 16, 2022
f1773cb
implement test for aws_wafv2_rule_group
tiborhercz Jul 16, 2022
083d8d4
replace body with cookie
tiborhercz Aug 23, 2022
171bc00
remove entry from test
tiborhercz Aug 23, 2022
48851e3
add MaxItems to cookies
tiborhercz Aug 23, 2022
622d3b2
merge
tiborhercz Aug 23, 2022
67a09ff
Merge branch 'hashicorp:main' into f-aws_wafv2_web_acl-add-cookies
tiborhercz Aug 23, 2022
42f0e6f
update indent for test file
tiborhercz Aug 23, 2022
947ee03
Merge branch 'f-aws_wafv2_web_acl-add-cookies' of github.com:tiborher…
tiborhercz Aug 23, 2022
ff3c745
update indent for test file
tiborhercz Aug 23, 2022
0edc5e6
update indent for test file
tiborhercz Aug 23, 2022
6a41c07
update all to struct instead of bool
tiborhercz Aug 25, 2022
d00fd39
Update .changelog/25845.txt
bschaatsbergen Aug 25, 2022
19d575b
Add `aws_wafv2_web_acl` entry
bschaatsbergen Aug 25, 2022
1207db9
Add `cookies` to `field_to_match` note
bschaatsbergen Aug 25, 2022
ef1712d
r/aws_wafv2_web_acl: Additional documentation for 'cookies'.
ewbankkit Aug 25, 2022
cf49091
r/aws_wafv2_web_acl: Update 'TestAccWAFV2WebACL_Update_rule'.
ewbankkit Aug 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/25845.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_wafv2_rule_group: Add `cookies` attribute to the `field_to_match` block
```

```release-note:enhancement
resource/aws_wafv2_web_acl: Add `cookies` attribute to the `field_to_match` block
```
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
78 changes: 78 additions & 0 deletions internal/service/wafv2/flex.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@ func expandFieldToMatch(l []interface{}) *wafv2.FieldToMatch {
f.Body = &wafv2.Body{}
}

if v, ok := m["cookies"]; ok && len(v.([]interface{})) > 0 {
f.Cookies = expandCookies(m["cookies"].([]interface{}))
}

if v, ok := m["method"]; ok && len(v.([]interface{})) > 0 {
f.Method = &wafv2.Method{}
}
Expand Down Expand Up @@ -445,6 +449,48 @@ func expandIPSetForwardedIPConfig(l []interface{}) *wafv2.IPSetForwardedIPConfig
}
}

func expandCookies(l []interface{}) *wafv2.Cookies {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

cookies := &wafv2.Cookies{
MatchScope: aws.String(m["match_scope"].(string)),
OversizeHandling: aws.String(m["oversize_handling"].(string)),
}

if v, ok := m["match_pattern"]; ok && len(v.([]interface{})) > 0 {
cookies.MatchPattern = expandCookieMatchPattern(v.([]interface{}))
}

return cookies
}

func expandCookieMatchPattern(l []interface{}) *wafv2.CookieMatchPattern {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})
CookieMatchPattern := &wafv2.CookieMatchPattern{}

if v, ok := m["included_cookies"]; ok && len(v.([]interface{})) > 0 {
CookieMatchPattern.IncludedCookies = flex.ExpandStringList(v.([]interface{}))
}

if v, ok := m["excluded_cookies"]; ok && len(v.([]interface{})) > 0 {
CookieMatchPattern.ExcludedCookies = flex.ExpandStringList(v.([]interface{}))
}

if v, ok := m["all"].([]interface{}); ok && len(v) > 0 {
CookieMatchPattern.All = &wafv2.All{}
}

return CookieMatchPattern
}

func expandSingleHeader(l []interface{}) *wafv2.SingleHeader {
if len(l) == 0 || l[0] == nil {
return nil
Expand Down Expand Up @@ -928,6 +974,10 @@ func flattenFieldToMatch(f *wafv2.FieldToMatch) interface{} {
m["body"] = make([]map[string]interface{}, 1)
}

if f.Cookies != nil {
m["cookies"] = flattenCookies(f.Cookies)
}

if f.Method != nil {
m["method"] = make([]map[string]interface{}, 1)
}
Expand Down Expand Up @@ -978,6 +1028,34 @@ func flattenIPSetForwardedIPConfig(i *wafv2.IPSetForwardedIPConfig) interface{}
return []interface{}{m}
}

func flattenCookies(c *wafv2.Cookies) interface{} {
if c == nil {
return []interface{}{}
}

m := map[string]interface{}{
"match_scope": aws.StringValue(c.MatchScope),
"oversize_handling": aws.StringValue(c.OversizeHandling),
"match_pattern": flattenCookiesMatchPattern(c.MatchPattern),
}

return []interface{}{m}
}

func flattenCookiesMatchPattern(c *wafv2.CookieMatchPattern) interface{} {
if c == nil {
return []interface{}{}
}

m := map[string]interface{}{
"all": c.All,
"included_cookies": aws.StringValueSlice(c.IncludedCookies),
"excluded_cookies": aws.StringValueSlice(c.ExcludedCookies),
}

return []interface{}{m}
}

func flattenSingleHeader(s *wafv2.SingleHeader) interface{} {
if s == nil {
return []interface{}{}
Expand Down
86 changes: 86 additions & 0 deletions internal/service/wafv2/rule_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"statement.0.byte_match_statement.0.field_to_match.#": "1",
"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.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",
Expand All @@ -399,6 +400,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"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.#": "1",
"statement.0.byte_match_statement.0.field_to_match.0.cookies.#": "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",
Expand All @@ -407,6 +409,32 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
}),
),
},
{
Config: testAccRuleGroupConfig_byteMatchStatementFieldToMatchCookies(ruleGroupName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRuleGroupExists(resourceName, &v),
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.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.#": "1",
"statement.0.byte_match_statement.0.field_to_match.0.cookies.0.match_scope": "ALL",
"statement.0.byte_match_statement.0.field_to_match.0.cookies.0.oversize_handling": "NO_MATCH",
"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.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_byteMatchStatementFieldToMatchMethod(ruleGroupName),
Check: resource.ComposeTestCheckFunc(
Expand All @@ -419,6 +447,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"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.method.#": "1",
"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",
Expand All @@ -439,6 +468,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"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.method.#": "0",
"statement.0.byte_match_statement.0.field_to_match.0.query_string.#": "1",
"statement.0.byte_match_statement.0.field_to_match.0.single_header.#": "0",
Expand All @@ -459,6 +489,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"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.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.#": "1",
Expand All @@ -480,6 +511,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"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.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",
Expand All @@ -501,6 +533,7 @@ func TestAccWAFV2RuleGroup_ByteMatchStatement_fieldToMatch(t *testing.T) {
"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.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",
Expand Down Expand Up @@ -2528,6 +2561,59 @@ resource "aws_wafv2_rule_group" "test" {
`, name)
}

func testAccRuleGroupConfig_byteMatchStatementFieldToMatchCookies(name string) string {
return fmt.Sprintf(`
resource "aws_wafv2_rule_group" "test" {
capacity = 15
name = "%s"
scope = "REGIONAL"

rule {
name = "rule-1"
priority = 1

action {
allow {}
}

statement {
byte_match_statement {
positional_constraint = "CONTAINS"
search_string = "word"

field_to_match {
cookies {
match_pattern {
included_cookies = ["test", "cookie_test"]
}
match_scope = "ALL"
oversize_handling = "NO_MATCH"
}
}

text_transformation {
priority = 1
type = "NONE"
}
}
}

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
}
}
`, name)
}

func testAccRuleGroupConfig_byteMatchStatementFieldToMatchSingleHeader(name string) string {
return fmt.Sprintf(`
resource "aws_wafv2_rule_group" "test" {
Expand Down
42 changes: 40 additions & 2 deletions internal/service/wafv2/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,46 @@ func fieldToMatchBaseSchema() *schema.Resource {
Schema: map[string]*schema.Schema{
"all_query_arguments": emptySchema(),
"body": emptySchema(),
"method": emptySchema(),
"query_string": emptySchema(),
"cookies": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"match_scope": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(wafv2.MapMatchScope_Values(), false),
},
"oversize_handling": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(wafv2.OversizeHandling_Values(), false),
},
"match_pattern": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"all": emptySchema(),
"included_cookies": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"excluded_cookies": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
},
},
},
"method": emptySchema(),
"query_string": emptySchema(),
"single_header": {
Type: schema.TypeList,
Optional: true,
Expand Down
19 changes: 13 additions & 6 deletions internal/service/wafv2/web_acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,19 @@ func TestAccWAFV2WebACL_Update_rule(t *testing.T) {
"visibility_config.0.metric_name": fmt.Sprintf("%s-metric-name-1", webACLName),
"visibility_config.0.sampled_requests_enabled": "false",
"statement.#": "1",
"statement.0.size_constraint_statement.#": "1",
"statement.0.size_constraint_statement.0.comparison_operator": "LT",
"statement.0.size_constraint_statement.0.field_to_match.#": "1",
"statement.0.size_constraint_statement.0.field_to_match.0.query_string.#": "1",
"statement.0.size_constraint_statement.0.size": "50",
"statement.0.size_constraint_statement.0.text_transformation.#": "2",
"statement.0.size_constraint_statement.#": "1",
"statement.0.size_constraint_statement.0.comparison_operator": "LT",
"statement.0.size_constraint_statement.0.field_to_match.#": "1",
"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.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",
"statement.0.size_constraint_statement.0.field_to_match.0.single_query_argument.#": "0",
"statement.0.size_constraint_statement.0.field_to_match.0.uri_path.#": "0",
"statement.0.size_constraint_statement.0.size": "50",
"statement.0.size_constraint_statement.0.text_transformation.#": "2",
}),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*.statement.0.size_constraint_statement.0.text_transformation.*", map[string]string{
"priority": "2",
Expand Down
14 changes: 13 additions & 1 deletion website/docs/r/wafv2_rule_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -492,11 +492,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`, `method`, `query_string`, `single_header`, `single_query_argument`, or `uri_path` can be specified.
~> **NOTE:** Only one of `all_query_arguments`, `body`, `cookies`, `method`, `query_string`, `single_header`, `single_query_argument`, or `uri_path` can be specified.
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
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 request cookies.
* `method` - (Optional) Inspect the HTTP method. The method indicates the type of operation that the request is asking the origin to perform.
* `query_string` - (Optional) Inspect the query string. This is the part of a URL that appears after a `?` character, if any.
* `single_header` - (Optional) Inspect a single header. See [Single Header](#single-header) below for details.
Expand Down Expand Up @@ -540,6 +541,17 @@ The `single_query_argument` block supports the following arguments:

* `name` - (Optional) The name of the query header to inspect. This setting must be provided as lower case characters.

### Cookies

Inspect the cookies in the web request. You can specify the parts of the cookies to inspect and you can narrow the set of cookies to inspect by including or excluding specific keys.
This is used to indicate the web request component to inspect, in the [FieldToMatch](https://docs.aws.amazon.com/waf/latest/APIReference/API_FieldToMatch.html) specification.

The `cookies` block supports the following arguments:

* `match_pattern` - (Required) The filter to use to identify the subset of cookies to inspect in a web request. You must specify exactly one setting: either `all`, `included_cookies` or `excluded_cookies`. More details: [CookieMatchPattern](https://docs.aws.amazon.com/waf/latest/APIReference/API_CookieMatchPattern.html)
* `match_scope` - (Required) The parts of the cookies to inspect with the rule inspection criteria. If you specify All, AWS WAF inspects both keys and values. Valid values: `ALL`, `KEY`, `VALUE`
* `oversize_handling` - (Required) What AWS WAF should do if the cookies of the request are larger than AWS WAF can inspect. AWS WAF does not support inspecting the entire contents of request cookies when they exceed 8 KB (8192 bytes) or 200 total cookies. The underlying host service forwards a maximum of 200 cookies and at most 8 KB of cookie contents to AWS WAF. Valid values: `CONTINUE`, `MATCH`, `NO_MATCH`

### Text Transformation

The `text_transformation` block supports the following arguments:
Expand Down
Loading