Skip to content

Commit 081bf57

Browse files
authored
Merge pull request #13961 from terraform-providers/b-wafv2-web-acl-recursion
resource/wafv2_web_acl: add additional nested statement level
2 parents 04baa55 + 41fc7fa commit 081bf57

File tree

2 files changed

+261
-7
lines changed

2 files changed

+261
-7
lines changed

aws/resource_aws_wafv2_web_acl.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -338,14 +338,14 @@ func wafv2WebACLRootStatementSchema(level int) *schema.Schema {
338338
MaxItems: 1,
339339
Elem: &schema.Resource{
340340
Schema: map[string]*schema.Schema{
341-
"and_statement": wafv2StatementSchema(level - 1),
341+
"and_statement": wafv2StatementSchema(level),
342342
"byte_match_statement": wafv2ByteMatchStatementSchema(),
343343
"geo_match_statement": wafv2GeoMatchStatementSchema(),
344344
"ip_set_reference_statement": wafv2IpSetReferenceStatementSchema(),
345345
"managed_rule_group_statement": wafv2ManagedRuleGroupStatementSchema(),
346-
"not_statement": wafv2StatementSchema(level - 1),
347-
"or_statement": wafv2StatementSchema(level - 1),
348-
"rate_based_statement": wafv2RateBasedStatementSchema(level - 1),
346+
"not_statement": wafv2StatementSchema(level),
347+
"or_statement": wafv2StatementSchema(level),
348+
"rate_based_statement": wafv2RateBasedStatementSchema(level),
349349
"regex_pattern_set_reference_statement": wafv2RegexPatternSetReferenceStatementSchema(),
350350
"rule_group_reference_statement": wafv2RuleGroupReferenceStatementSchema(),
351351
"size_constraint_statement": wafv2SizeConstraintSchema(),
@@ -429,12 +429,12 @@ func wafv2ScopeDownStatementSchema(level int) *schema.Schema {
429429
MaxItems: 1,
430430
Elem: &schema.Resource{
431431
Schema: map[string]*schema.Schema{
432-
"and_statement": wafv2StatementSchema(level - 1),
432+
"and_statement": wafv2StatementSchema(level),
433433
"byte_match_statement": wafv2ByteMatchStatementSchema(),
434434
"geo_match_statement": wafv2GeoMatchStatementSchema(),
435435
"ip_set_reference_statement": wafv2IpSetReferenceStatementSchema(),
436-
"not_statement": wafv2StatementSchema(level - 1),
437-
"or_statement": wafv2StatementSchema(level - 1),
436+
"not_statement": wafv2StatementSchema(level),
437+
"or_statement": wafv2StatementSchema(level),
438438
"regex_pattern_set_reference_statement": wafv2RegexPatternSetReferenceStatementSchema(),
439439
"size_constraint_statement": wafv2SizeConstraintSchema(),
440440
"sqli_match_statement": wafv2SqliMatchStatementSchema(),

aws/resource_aws_wafv2_web_acl_test.go

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package aws
22

33
import (
44
"fmt"
5+
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfawsresource"
56
"regexp"
67
"testing"
78

@@ -436,6 +437,91 @@ func TestAccAwsWafv2WebACL_Tags(t *testing.T) {
436437
})
437438
}
438439

440+
// Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/13862
441+
func TestAccAwsWafv2WebACL_MaxNestedRateBasedStatements(t *testing.T) {
442+
var v wafv2.WebACL
443+
webACLName := acctest.RandomWithPrefix("tf-acc-test")
444+
resourceName := "aws_wafv2_web_acl.test"
445+
446+
resource.ParallelTest(t, resource.TestCase{
447+
PreCheck: func() { testAccPreCheck(t) },
448+
Providers: testAccProviders,
449+
CheckDestroy: testAccCheckAwsWafv2WebACLDestroy,
450+
Steps: []resource.TestStep{
451+
{
452+
Config: testAccAwsWafv2WebACLConfig_multipleNestedRateBasedStatements(webACLName),
453+
Check: resource.ComposeTestCheckFunc(
454+
testAccCheckAwsWafv2WebACLExists(resourceName, &v),
455+
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/webacl/.+$`)),
456+
resource.TestCheckResourceAttr(resourceName, "name", webACLName),
457+
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
458+
tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
459+
"statement.#": "1",
460+
"statement.0.rate_based_statement.#": "1",
461+
"statement.0.rate_based_statement.0.limit": "300",
462+
"statement.0.rate_based_statement.0.aggregate_key_type": "IP",
463+
"statement.0.rate_based_statement.0.scope_down_statement.#": "1",
464+
"statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.#": "1",
465+
"statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.#": "1",
466+
"statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.#": "1",
467+
"statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.#": "2",
468+
"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",
469+
"statement.0.rate_based_statement.0.scope_down_statement.0.not_statement.0.statement.0.or_statement.0.statement.1.ip_set_reference_statement.#": "1",
470+
}),
471+
),
472+
},
473+
{
474+
ResourceName: resourceName,
475+
ImportState: true,
476+
ImportStateVerify: true,
477+
ImportStateIdFunc: testAccAwsWafv2WebACLImportStateIdFunc(resourceName),
478+
},
479+
},
480+
})
481+
}
482+
483+
func TestAccAwsWafv2WebACL_MaxNestedOperatorStatements(t *testing.T) {
484+
var v wafv2.WebACL
485+
webACLName := acctest.RandomWithPrefix("tf-acc-test")
486+
resourceName := "aws_wafv2_web_acl.test"
487+
488+
resource.ParallelTest(t, resource.TestCase{
489+
PreCheck: func() { testAccPreCheck(t) },
490+
Providers: testAccProviders,
491+
CheckDestroy: testAccCheckAwsWafv2WebACLDestroy,
492+
Steps: []resource.TestStep{
493+
{
494+
Config: testAccAwsWafv2WebACLConfig_multipleNestedOperatorStatements(webACLName),
495+
Check: resource.ComposeTestCheckFunc(
496+
testAccCheckAwsWafv2WebACLExists(resourceName, &v),
497+
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/webacl/.+$`)),
498+
resource.TestCheckResourceAttr(resourceName, "name", webACLName),
499+
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
500+
tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
501+
"statement.#": "1",
502+
"statement.0.and_statement.#": "1",
503+
"statement.0.and_statement.0.statement.#": "2",
504+
"statement.0.and_statement.0.statement.0.not_statement.#": "1",
505+
"statement.0.and_statement.0.statement.0.not_statement.0.statement.#": "1",
506+
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.#": "1",
507+
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.#": "2",
508+
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.0.regex_pattern_set_reference_statement.#": "1",
509+
"statement.0.and_statement.0.statement.0.not_statement.0.statement.0.or_statement.0.statement.1.ip_set_reference_statement.#": "1",
510+
"statement.0.and_statement.0.statement.1.geo_match_statement.#": "1",
511+
"statement.0.and_statement.0.statement.1.geo_match_statement.0.country_codes.0": "NL",
512+
}),
513+
),
514+
},
515+
{
516+
ResourceName: resourceName,
517+
ImportState: true,
518+
ImportStateVerify: true,
519+
ImportStateIdFunc: testAccAwsWafv2WebACLImportStateIdFunc(resourceName),
520+
},
521+
},
522+
})
523+
}
524+
439525
// Calculates the index which isn't static because ARN is generated as part of the test
440526
func computeWafv2RuleGroupRefStatementIndex(r *wafv2.WebACL, idx *int, e []interface{}) resource.TestCheckFunc {
441527
return func(s *terraform.State) error {
@@ -1108,6 +1194,174 @@ resource "aws_wafv2_web_acl" "test" {
11081194
`, name, tag1Key, tag1Value, tag2Key, tag2Value)
11091195
}
11101196

1197+
func testAccAwsWafv2WebACLConfig_multipleNestedRateBasedStatements(name string) string {
1198+
return fmt.Sprintf(`
1199+
resource "aws_wafv2_regex_pattern_set" "test" {
1200+
name = "%[1]s"
1201+
scope = "REGIONAL"
1202+
regular_expression {
1203+
regex_string = "one"
1204+
}
1205+
}
1206+
1207+
resource "aws_wafv2_ip_set" "test" {
1208+
name = "%[1]s"
1209+
scope = "REGIONAL"
1210+
ip_address_version = "IPV4"
1211+
addresses = ["1.2.3.4/32", "5.6.7.8/32"]
1212+
}
1213+
1214+
resource "aws_wafv2_web_acl" "test" {
1215+
name = "%[1]s"
1216+
description = "%[1]s"
1217+
scope = "REGIONAL"
1218+
1219+
default_action {
1220+
allow {}
1221+
}
1222+
1223+
rule {
1224+
name = "rule"
1225+
priority = 0
1226+
1227+
action {
1228+
block {}
1229+
}
1230+
1231+
statement {
1232+
rate_based_statement {
1233+
limit = 300
1234+
aggregate_key_type = "IP"
1235+
1236+
scope_down_statement {
1237+
not_statement {
1238+
statement {
1239+
or_statement {
1240+
statement {
1241+
regex_pattern_set_reference_statement {
1242+
arn = aws_wafv2_regex_pattern_set.test.arn
1243+
field_to_match {
1244+
uri_path {}
1245+
}
1246+
text_transformation {
1247+
type = "LOWERCASE"
1248+
priority = 1
1249+
}
1250+
}
1251+
}
1252+
statement {
1253+
ip_set_reference_statement {
1254+
arn = aws_wafv2_ip_set.test.arn
1255+
}
1256+
}
1257+
}
1258+
}
1259+
}
1260+
}
1261+
}
1262+
}
1263+
1264+
visibility_config {
1265+
cloudwatch_metrics_enabled = false
1266+
metric_name = "rule"
1267+
sampled_requests_enabled = false
1268+
}
1269+
}
1270+
1271+
visibility_config {
1272+
cloudwatch_metrics_enabled = false
1273+
metric_name = "waf"
1274+
sampled_requests_enabled = false
1275+
}
1276+
}
1277+
`, name)
1278+
}
1279+
1280+
func testAccAwsWafv2WebACLConfig_multipleNestedOperatorStatements(name string) string {
1281+
return fmt.Sprintf(`
1282+
resource "aws_wafv2_regex_pattern_set" "test" {
1283+
name = "%[1]s"
1284+
scope = "REGIONAL"
1285+
regular_expression {
1286+
regex_string = "one"
1287+
}
1288+
}
1289+
1290+
resource "aws_wafv2_ip_set" "test" {
1291+
name = "%[1]s"
1292+
scope = "REGIONAL"
1293+
ip_address_version = "IPV4"
1294+
addresses = ["1.2.3.4/32", "5.6.7.8/32"]
1295+
}
1296+
1297+
resource "aws_wafv2_web_acl" "test" {
1298+
name = "%[1]s"
1299+
description = "%[1]s"
1300+
scope = "REGIONAL"
1301+
1302+
default_action {
1303+
allow {}
1304+
}
1305+
1306+
rule {
1307+
name = "rule"
1308+
priority = 0
1309+
1310+
action {
1311+
block {}
1312+
}
1313+
1314+
statement {
1315+
and_statement {
1316+
statement {
1317+
not_statement {
1318+
statement {
1319+
or_statement {
1320+
statement {
1321+
regex_pattern_set_reference_statement {
1322+
arn = aws_wafv2_regex_pattern_set.test.arn
1323+
field_to_match {
1324+
uri_path {}
1325+
}
1326+
text_transformation {
1327+
type = "LOWERCASE"
1328+
priority = 1
1329+
}
1330+
}
1331+
}
1332+
statement {
1333+
ip_set_reference_statement {
1334+
arn = aws_wafv2_ip_set.test.arn
1335+
}
1336+
}
1337+
}
1338+
}
1339+
}
1340+
}
1341+
statement {
1342+
geo_match_statement {
1343+
country_codes = ["NL"]
1344+
}
1345+
}
1346+
}
1347+
}
1348+
1349+
visibility_config {
1350+
cloudwatch_metrics_enabled = false
1351+
metric_name = "rule"
1352+
sampled_requests_enabled = false
1353+
}
1354+
}
1355+
1356+
visibility_config {
1357+
cloudwatch_metrics_enabled = false
1358+
metric_name = "waf"
1359+
sampled_requests_enabled = false
1360+
}
1361+
}
1362+
`, name)
1363+
}
1364+
11111365
func testAccAwsWafv2WebACLImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
11121366
return func(s *terraform.State) (string, error) {
11131367
rs, ok := s.RootModule().Resources[resourceName]

0 commit comments

Comments
 (0)