Skip to content

Commit

Permalink
Merge pull request #27682 from RemcodM/improve_resource_nesting_rule_…
Browse files Browse the repository at this point in the history
…group_wafv2

resource/wafv2_rule_group: add additional nested statement level
  • Loading branch information
ewbankkit committed Nov 7, 2022
2 parents aa0b654 + 25b1362 commit d8aae0d
Show file tree
Hide file tree
Showing 3 changed files with 296 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .changelog/27682.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_wafv2_rule_group: Correct maximum nesting level for `and_statement`, `not_statement`, `or_statement` and `rate_based_statement`
```
289 changes: 289 additions & 0 deletions internal/service/wafv2/rule_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1960,6 +1960,94 @@ func TestAccWAFV2RuleGroup_rateBasedStatement(t *testing.T) {
})
}

func TestAccWAFV2RuleGroup_RateBased_maxNested(t *testing.T) {
var v wafv2.RuleGroup
ruleGroupName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_wafv2_rule_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccPreCheckScopeRegional(t) },
ErrorCheck: acctest.ErrorCheck(t, wafv2.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckRuleGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccRuleGroupConfig_multipleNestedRateBasedStatements(ruleGroupName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRuleGroupExists(resourceName, &v),
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/rulegroup/.+$`)),
resource.TestCheckResourceAttr(resourceName, "name", ruleGroupName),
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.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",
}),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: testAccWebACLImportStateIdFunc(resourceName),
},
},
})
}

func TestAccWAFV2RuleGroup_Operators_maxNested(t *testing.T) {
var v wafv2.RuleGroup
ruleGroupName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_wafv2_rule_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccPreCheckScopeRegional(t) },
ErrorCheck: acctest.ErrorCheck(t, wafv2.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckRuleGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccRuleGroupConfig_multipleNestedOperatorStatements(ruleGroupName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRuleGroupExists(resourceName, &v),
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/rulegroup/.+$`)),
resource.TestCheckResourceAttr(resourceName, "name", ruleGroupName),
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
"statement.#": "1",
"statement.0.and_statement.#": "1",
"statement.0.and_statement.0.statement.#": "2",
"statement.0.and_statement.0.statement.0.not_statement.#": "1",
"statement.0.and_statement.0.statement.0.not_statement.0.statement.#": "1",
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.#": "1",
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.#": "3",
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.0.regex_pattern_set_reference_statement.#": "1",
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.1.regex_match_statement.#": "1",
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.2.ip_set_reference_statement.#": "1",
"statement.0.and_statement.0.statement.1.geo_match_statement.#": "1",
"statement.0.and_statement.0.statement.1.geo_match_statement.0.country_codes.0": "NL",
}),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: testAccWebACLImportStateIdFunc(resourceName),
},
},
})
}

func testAccPreCheckScopeRegional(t *testing.T) {
conn := acctest.Provider.Meta().(*conns.AWSClient).WAFV2Conn

Expand Down Expand Up @@ -4289,6 +4377,207 @@ resource "aws_wafv2_rule_group" "test" {
`, name, name, tag1Key, tag1Value, tag2Key, tag2Value)
}

func testAccRuleGroupConfig_multipleNestedRateBasedStatements(name string) string {
return fmt.Sprintf(`
resource "aws_wafv2_regex_pattern_set" "test" {
name = %[1]q
scope = "REGIONAL"
regular_expression {
regex_string = "[a-z]([a-z0-9_-]*[a-z0-9])?"
}
}
resource "aws_wafv2_ip_set" "test" {
name = %[1]q
scope = "REGIONAL"
ip_address_version = "IPV4"
addresses = ["1.2.3.4/32", "5.6.7.8/32"]
}
resource "aws_wafv2_rule_group" "test" {
capacity = 300
name = %[1]q
description = %[1]q
scope = "REGIONAL"
rule {
name = "rule"
priority = 0
action {
block {}
}
statement {
rate_based_statement {
limit = 300
aggregate_key_type = "IP"
scope_down_statement {
not_statement {
statement {
or_statement {
statement {
regex_pattern_set_reference_statement {
arn = aws_wafv2_regex_pattern_set.test.arn
field_to_match {
uri_path {}
}
text_transformation {
type = "LOWERCASE"
priority = 1
}
}
}
statement {
regex_match_statement {
regex_string = "[a-z]([a-z0-9_-]*[a-z0-9])?"
field_to_match {
uri_path {}
}
text_transformation {
type = "LOWERCASE"
priority = 1
}
}
}
statement {
ip_set_reference_statement {
arn = aws_wafv2_ip_set.test.arn
}
}
}
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "rule"
sampled_requests_enabled = false
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "waf"
sampled_requests_enabled = false
}
}
`, name)
}

func testAccRuleGroupConfig_multipleNestedOperatorStatements(name string) string {
return fmt.Sprintf(`
resource "aws_wafv2_regex_pattern_set" "test" {
name = %[1]q
scope = "REGIONAL"
regular_expression {
regex_string = "[a-z]([a-z0-9_-]*[a-z0-9])?"
}
}
resource "aws_wafv2_ip_set" "test" {
name = %[1]q
scope = "REGIONAL"
ip_address_version = "IPV4"
addresses = ["1.2.3.4/32", "5.6.7.8/32"]
}
resource "aws_wafv2_rule_group" "test" {
capacity = 300
name = %[1]q
description = %[1]q
scope = "REGIONAL"
rule {
name = "rule"
priority = 0
action {
block {}
}
statement {
and_statement {
statement {
not_statement {
statement {
or_statement {
statement {
regex_pattern_set_reference_statement {
arn = aws_wafv2_regex_pattern_set.test.arn
field_to_match {
uri_path {}
}
text_transformation {
type = "LOWERCASE"
priority = 1
}
}
}
statement {
regex_match_statement {
regex_string = "[a-z]([a-z0-9_-]*[a-z0-9])?"
field_to_match {
uri_path {}
}
text_transformation {
type = "LOWERCASE"
priority = 1
}
}
}
statement {
ip_set_reference_statement {
arn = aws_wafv2_ip_set.test.arn
}
}
}
}
}
}
statement {
geo_match_statement {
country_codes = ["NL"]
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "rule"
sampled_requests_enabled = false
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "waf"
sampled_requests_enabled = false
}
}
`, name)
}

func testAccRuleGroupImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceName]
Expand Down
8 changes: 4 additions & 4 deletions internal/service/wafv2/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ func ruleGroupRootStatementSchema(level int) *schema.Schema {
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"and_statement": statementSchema(level - 1),
"and_statement": statementSchema(level),
"byte_match_statement": byteMatchStatementSchema(),
"geo_match_statement": geoMatchStatementSchema(),
"ip_set_reference_statement": ipSetReferenceStatementSchema(),
"label_match_statement": labelMatchStatementSchema(),
"not_statement": statementSchema(level - 1),
"or_statement": statementSchema(level - 1),
"rate_based_statement": rateBasedStatementSchema(level - 1),
"not_statement": statementSchema(level),
"or_statement": statementSchema(level),
"rate_based_statement": rateBasedStatementSchema(level),
"regex_match_statement": regexMatchStatementSchema(),
"regex_pattern_set_reference_statement": regexPatternSetReferenceStatementSchema(),
"size_constraint_statement": sizeConstraintSchema(),
Expand Down

0 comments on commit d8aae0d

Please sign in to comment.