From 63899ac8e637b32f4d184deb649cb73777682dea Mon Sep 17 00:00:00 2001 From: dbell-infra Date: Wed, 21 Dec 2022 14:49:09 -0800 Subject: [PATCH 01/13] Implement WAFv2 managed rule config --- internal/service/wafv2/flex.go | 78 +++++++++++ internal/service/wafv2/schemas.go | 55 +++++++- internal/service/wafv2/web_acl_test.go | 184 +++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 2 deletions(-) diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index 1ddbf4da499..b8411cafc36 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -985,10 +985,58 @@ func expandManagedRuleGroupStatement(l []interface{}) *wafv2.ManagedRuleGroupSta if v, ok := m["version"]; ok && v != "" { r.Version = aws.String(v.(string)) } + if s, ok := m["managed_rule_group_config"].([]interface{}); ok && len(s) > 0 && s[0] != nil { + r.ManagedRuleGroupConfigs = expandManagedRuleGroupConfigs(s[0].(map[string]interface{})) + } return r } +func expandManagedRuleGroupConfigs(m map[string]interface{}) []*wafv2.ManagedRuleGroupConfig { + c := make([]*wafv2.ManagedRuleGroupConfig, 0) + + if v, ok := m["login_path"]; ok && len(v.(string)) > 0 { + c = append(c, &wafv2.ManagedRuleGroupConfig{ + LoginPath: aws.String(v.(string)), + }) + + } + + if v, ok := m["payload_type"]; ok && len(v.(string)) > 0 { + c = append(c, &wafv2.ManagedRuleGroupConfig{ + PayloadType: aws.String(v.(string)), + }) + + } + + if v, ok := m["password_field"]; ok && len(v.(string)) > 0 { + c = append(c, &wafv2.ManagedRuleGroupConfig{ + PasswordField: &wafv2.PasswordField{ + Identifier: aws.String(v.(string)), + }, + }) + + } + + if v, ok := m["username_field"]; ok && len(v.(string)) > 0 { + c = append(c, &wafv2.ManagedRuleGroupConfig{ + UsernameField: &wafv2.UsernameField{ + Identifier: aws.String(v.(string)), + }, + }) + + } + + if v, ok := m["inspection_level"]; ok && len(v.(string)) > 0 { + c = append(c, &wafv2.ManagedRuleGroupConfig{ + AWSManagedRulesBotControlRuleSet: &wafv2.AWSManagedRulesBotControlRuleSet{ + InspectionLevel: aws.String(v.(string)), + }, + }) + } + return c +} + func expandRateBasedStatement(l []interface{}) *wafv2.RateBasedStatement { if len(l) == 0 || l[0] == nil { return nil @@ -1928,10 +1976,40 @@ func flattenManagedRuleGroupStatement(apiObject *wafv2.ManagedRuleGroupStatement if apiObject.Version != nil { tfMap["version"] = aws.StringValue(apiObject.Version) } + if apiObject.ManagedRuleGroupConfigs != nil { + tfMap["managed_rule_group_config"] = []interface{}{flattenManagedRuleGroupConfigs(apiObject.ManagedRuleGroupConfigs)} + } return []interface{}{tfMap} } +func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) interface{} { + tfMap := map[string]interface{}{} + + for _, config := range c { + if config.AWSManagedRulesBotControlRuleSet != nil { + tfMap["inspection_level"] = aws.StringValue(config.AWSManagedRulesBotControlRuleSet.InspectionLevel) + } + if config.LoginPath != nil { + tfMap["login_path"] = aws.StringValue(config.LoginPath) + + } + if config.PasswordField != nil { + tfMap["password_field"] = aws.StringValue(config.PasswordField.Identifier) + } + + if config.UsernameField != nil { + tfMap["username_field"] = aws.StringValue(config.UsernameField.Identifier) + } + if config.PayloadType != nil { + tfMap["payload_type"] = aws.StringValue(config.PayloadType) + } + } + + return tfMap + +} + func flattenRateBasedStatement(apiObject *wafv2.RateBasedStatement) interface{} { if apiObject == nil { return []interface{}{} diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index 830492766b2..49f66b60ecb 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -841,8 +841,9 @@ func managedRuleGroupStatementSchema(level int) *schema.Schema { Required: true, ValidateFunc: validation.StringLenBetween(1, 128), }, - "rule_action_override": ruleActionOverrideSchema(), - "scope_down_statement": scopeDownStatementSchema(level - 1), + "rule_action_override": ruleActionOverrideSchema(), + "managed_rule_group_config": managedRuleGroupConfigSchema(), + "scope_down_statement": scopeDownStatementSchema(level - 1), "vendor_name": { Type: schema.TypeString, Required: true, @@ -942,6 +943,56 @@ func ruleActionOverrideSchema() *schema.Schema { } } +func managedRuleGroupConfigSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "login_path": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 256), + validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), + ), + }, + "password_field": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 512), + validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), + ), + }, + "payload_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.All( + validation.StringMatch(regexp.MustCompile(`(JSON|FORM_ENCODED)`), "valid values are JSON | FORM_ENCODED"), + ), + }, + "username_field": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 512), + validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), + ), + }, + "inspection_level": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.All( + validation.StringMatch(regexp.MustCompile(`(COMMON|TARGETED)`), "valid values are COMMON | TARGETED"), + ), + }, + }, + }, + } +} + func actionToUseSchema() *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 57435b7b129..5cba588cd23 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -607,6 +607,79 @@ func TestAccWAFV2WebACL_ManagedRuleGroup_basic(t *testing.T) { }) } +func TestAccWAFV2WebACL_ManagedRuleGroup_ManagedRuleGroupConfig(t *testing.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(t); testAccPreCheckScopeRegional(t) }, + ErrorCheck: acctest.ErrorCheck(t, wafv2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckWebACLDestroy, + Steps: []resource.TestStep{ + { + Config: testAccWebACLConfig_managedRuleGroupStatementManagedRuleGroupConfig(webACLName), + Check: resource.ComposeTestCheckFunc( + testAccCheckWebACLExists(resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/webacl/.+$`)), + resource.TestCheckResourceAttr(resourceName, "name", webACLName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{ + "name": "rule-1", + "action.#": "0", + "override_action.#": "1", + "override_action.0.count.#": "0", + "override_action.0.none.#": "1", + "statement.#": "1", + "statement.0.managed_rule_group_statement.#": "1", + "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", + "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", + "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", + "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/login", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field": "/password", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field": "/username", + }), + ), + }, + { + Config: testAccWebACLConfig_managedRuleGroupStatementManagedRuleGroupConfigUpdate(webACLName), + Check: resource.ComposeTestCheckFunc( + testAccCheckWebACLExists(resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/webacl/.+$`)), + resource.TestCheckResourceAttr(resourceName, "name", webACLName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{ + "name": "rule-1", + "action.#": "0", + "override_action.#": "1", + "override_action.0.count.#": "0", + "override_action.0.none.#": "1", + "statement.#": "1", + "statement.0.managed_rule_group_statement.#": "1", + "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", + "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", + "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", + "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/app-login", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field": "/app-password", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field": "/app-username", + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccWebACLImportStateIdFunc(resourceName), + }, + }, + }) +} + func TestAccWAFV2WebACL_ManagedRuleGroup_specifyVersion(t *testing.T) { var v wafv2.WebACL webACLName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -2813,6 +2886,117 @@ resource "aws_wafv2_web_acl" "test" { `, name) } +func testAccWebACLConfig_managedRuleGroupStatementManagedRuleGroupConfig(name 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 + + override_action { + none {} + } + + statement { + managed_rule_group_statement { + name = "AWSManagedRulesATPRuleSet" + vendor_name = "AWS" + + managed_rule_group_config { + login_path = "/login" + password_field = "/password" + payload_type = "JSON" + username_field = "/username" + } + + } + + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-rule-metric-name" + sampled_requests_enabled = false + } + } + + tags = { + Tag1 = "Value1" + Tag2 = "Value2" + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-metric-name" + sampled_requests_enabled = false + } +} +`, name) +} + +func testAccWebACLConfig_managedRuleGroupStatementManagedRuleGroupConfigUpdate(name 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 + + override_action { + none {} + } + + statement { + managed_rule_group_statement { + name = "AWSManagedRulesATPRuleSet" + vendor_name = "AWS" + + managed_rule_group_config { + login_path = "/app-login" + password_field = "/app-password" + payload_type = "JSON" + username_field = "/app-username" + } + } + + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-rule-metric-name" + sampled_requests_enabled = false + } + } + + tags = { + Tag1 = "Value1" + Tag2 = "Value2" + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "friendly-metric-name" + sampled_requests_enabled = false + } +} +`, name) +} + func testAccWebACLConfig_managedRuleGroupStatementUpdate(name string) string { return fmt.Sprintf(` resource "aws_wafv2_web_acl" "test" { From b90fdf381ef8096853551615f35caceec216b70c Mon Sep 17 00:00:00 2001 From: dbell-infra Date: Tue, 27 Dec 2022 11:10:59 -0800 Subject: [PATCH 02/13] add changelog file --- .changelog/28594.txt | 2 ++ internal/service/wafv2/flex.go | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 .changelog/28594.txt diff --git a/.changelog/28594.txt b/.changelog/28594.txt new file mode 100644 index 00000000000..65936e8a0d0 --- /dev/null +++ b/.changelog/28594.txt @@ -0,0 +1,2 @@ +```release-note:enhancement +resource/aws_wafv2_web_acl: Add support for ManagedRuleGroupConfig``` diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index b8411cafc36..af8655b82f0 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -999,14 +999,12 @@ func expandManagedRuleGroupConfigs(m map[string]interface{}) []*wafv2.ManagedRul c = append(c, &wafv2.ManagedRuleGroupConfig{ LoginPath: aws.String(v.(string)), }) - } if v, ok := m["payload_type"]; ok && len(v.(string)) > 0 { c = append(c, &wafv2.ManagedRuleGroupConfig{ PayloadType: aws.String(v.(string)), }) - } if v, ok := m["password_field"]; ok && len(v.(string)) > 0 { @@ -1015,7 +1013,6 @@ func expandManagedRuleGroupConfigs(m map[string]interface{}) []*wafv2.ManagedRul Identifier: aws.String(v.(string)), }, }) - } if v, ok := m["username_field"]; ok && len(v.(string)) > 0 { @@ -1024,7 +1021,6 @@ func expandManagedRuleGroupConfigs(m map[string]interface{}) []*wafv2.ManagedRul Identifier: aws.String(v.(string)), }, }) - } if v, ok := m["inspection_level"]; ok && len(v.(string)) > 0 { @@ -1976,6 +1972,7 @@ func flattenManagedRuleGroupStatement(apiObject *wafv2.ManagedRuleGroupStatement if apiObject.Version != nil { tfMap["version"] = aws.StringValue(apiObject.Version) } + if apiObject.ManagedRuleGroupConfigs != nil { tfMap["managed_rule_group_config"] = []interface{}{flattenManagedRuleGroupConfigs(apiObject.ManagedRuleGroupConfigs)} } @@ -1990,10 +1987,11 @@ func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) interface if config.AWSManagedRulesBotControlRuleSet != nil { tfMap["inspection_level"] = aws.StringValue(config.AWSManagedRulesBotControlRuleSet.InspectionLevel) } + if config.LoginPath != nil { tfMap["login_path"] = aws.StringValue(config.LoginPath) - } + if config.PasswordField != nil { tfMap["password_field"] = aws.StringValue(config.PasswordField.Identifier) } @@ -2001,13 +1999,13 @@ func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) interface if config.UsernameField != nil { tfMap["username_field"] = aws.StringValue(config.UsernameField.Identifier) } + if config.PayloadType != nil { tfMap["payload_type"] = aws.StringValue(config.PayloadType) } } return tfMap - } func flattenRateBasedStatement(apiObject *wafv2.RateBasedStatement) interface{} { From 54974c18ccb55ff9952b6cbfa8c8c64d460e0ec8 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 12:36:07 -0500 Subject: [PATCH 03/13] r/aws_wafv2_web_acl: fmt tests --- internal/service/wafv2/web_acl_test.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index 5cba588cd23..90047302e45 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -2910,15 +2910,13 @@ resource "aws_wafv2_web_acl" "test" { name = "AWSManagedRulesATPRuleSet" vendor_name = "AWS" - managed_rule_group_config { - login_path = "/login" - password_field = "/password" - payload_type = "JSON" - username_field = "/username" - } - + managed_rule_group_config { + login_path = "/login" + password_field = "/password" + payload_type = "JSON" + username_field = "/username" + } } - } visibility_config { From 42f818e3b6206c9b5912eb6575a97e347d817e09 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 12:52:16 -0500 Subject: [PATCH 04/13] r/aws_wafv2_web_acl: fmt tests --- internal/service/wafv2/web_acl_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index 90047302e45..85bec381e06 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -2965,13 +2965,12 @@ resource "aws_wafv2_web_acl" "test" { vendor_name = "AWS" managed_rule_group_config { - login_path = "/app-login" - password_field = "/app-password" - payload_type = "JSON" - username_field = "/app-username" + login_path = "/app-login" + password_field = "/app-password" + payload_type = "JSON" + username_field = "/app-username" } } - } visibility_config { From d93d8b6125f0ee4bc458e8c0399fe97bd569024b Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 12:59:16 -0500 Subject: [PATCH 05/13] r/aws_wafv2_web_acl: fmt tests --- internal/service/wafv2/schemas.go | 16 ++++++---------- internal/service/wafv2/web_acl_test.go | 6 +++--- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index 49f66b60ecb..d08aa460ae6 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -967,11 +967,9 @@ func managedRuleGroupConfigSchema() *schema.Schema { ), }, "payload_type": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.All( - validation.StringMatch(regexp.MustCompile(`(JSON|FORM_ENCODED)`), "valid values are JSON | FORM_ENCODED"), - ), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(wafv2.PayloadType_Values(), false), }, "username_field": { Type: schema.TypeString, @@ -982,11 +980,9 @@ func managedRuleGroupConfigSchema() *schema.Schema { ), }, "inspection_level": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.All( - validation.StringMatch(regexp.MustCompile(`(COMMON|TARGETED)`), "valid values are COMMON | TARGETED"), - ), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(wafv2.InspectionLevel_Values(), false), }, }, }, diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index 85bec381e06..fdc64462615 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -2964,12 +2964,12 @@ resource "aws_wafv2_web_acl" "test" { name = "AWSManagedRulesATPRuleSet" vendor_name = "AWS" - managed_rule_group_config { - login_path = "/app-login" + managed_rule_group_config { + login_path = "/app-login" password_field = "/app-password" payload_type = "JSON" username_field = "/app-username" - } + } } } From 3f62306e7245187a82ead29f7c379e44f11f332f Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 13:47:06 -0500 Subject: [PATCH 06/13] r/aws_wafv2_web_acl: expandManagedRuleGroupConfigs() for list of more that 1 --- internal/service/wafv2/flex.go | 94 +++++++++++++++++++++---------- internal/service/wafv2/schemas.go | 58 +++++++++++++------ 2 files changed, 105 insertions(+), 47 deletions(-) diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index af8655b82f0..e7204829625 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -985,52 +985,84 @@ func expandManagedRuleGroupStatement(l []interface{}) *wafv2.ManagedRuleGroupSta if v, ok := m["version"]; ok && v != "" { r.Version = aws.String(v.(string)) } - if s, ok := m["managed_rule_group_config"].([]interface{}); ok && len(s) > 0 && s[0] != nil { - r.ManagedRuleGroupConfigs = expandManagedRuleGroupConfigs(s[0].(map[string]interface{})) + if v, ok := m["managed_rule_group_config"].([]interface{}); ok && len(v) > 0 { + r.ManagedRuleGroupConfigs = expandManagedRuleGroupConfigs(v) } return r } -func expandManagedRuleGroupConfigs(m map[string]interface{}) []*wafv2.ManagedRuleGroupConfig { - c := make([]*wafv2.ManagedRuleGroupConfig, 0) +func expandManagedRuleGroupConfigs(tfList []interface{}) []*wafv2.ManagedRuleGroupConfig { + if len(tfList) == 0 { + return nil + } - if v, ok := m["login_path"]; ok && len(v.(string)) > 0 { - c = append(c, &wafv2.ManagedRuleGroupConfig{ - LoginPath: aws.String(v.(string)), - }) + var out []*wafv2.ManagedRuleGroupConfig + for _, item := range tfList { + m, ok := item.(map[string]interface{}) + if !ok { + continue + } + var r wafv2.ManagedRuleGroupConfig + if v, ok := m["aws_managed_rules_bot_rule_set"].([]interface{}); ok && len(v) > 0 { + r.AWSManagedRulesBotControlRuleSet = expandAWSManagedRulesBotControlRuleSet(v) + } + if v, ok := m["login_path"].(string); ok && v != "" { + r.LoginPath = aws.String(v) + } + if v, ok := m["payload_type"].(string); ok && v != "" { + r.PayloadType = aws.String(v) + } + if v, ok := m["password_field"].([]interface{}); ok && len(v) > 0 { + r.PasswordField = expandPasswordField(v) + } + if v, ok := m["username_field"].([]interface{}); ok && len(v) > 0 { + r.UsernameField = expandUsernameField(v) + } + + out = append(out, &r) } - if v, ok := m["payload_type"]; ok && len(v.(string)) > 0 { - c = append(c, &wafv2.ManagedRuleGroupConfig{ - PayloadType: aws.String(v.(string)), - }) + return out +} + +func expandPasswordField(tfList []interface{}) *wafv2.PasswordField { + if len(tfList) == 0 || tfList[0] == nil { + return nil } - if v, ok := m["password_field"]; ok && len(v.(string)) > 0 { - c = append(c, &wafv2.ManagedRuleGroupConfig{ - PasswordField: &wafv2.PasswordField{ - Identifier: aws.String(v.(string)), - }, - }) + m := tfList[0].(map[string]interface{}) + out := wafv2.PasswordField{ + Identifier: aws.String(m["identifier"].(string)), } - if v, ok := m["username_field"]; ok && len(v.(string)) > 0 { - c = append(c, &wafv2.ManagedRuleGroupConfig{ - UsernameField: &wafv2.UsernameField{ - Identifier: aws.String(v.(string)), - }, - }) + return &out +} + +func expandUsernameField(tfList []interface{}) *wafv2.UsernameField { + if len(tfList) == 0 || tfList[0] == nil { + return nil } - if v, ok := m["inspection_level"]; ok && len(v.(string)) > 0 { - c = append(c, &wafv2.ManagedRuleGroupConfig{ - AWSManagedRulesBotControlRuleSet: &wafv2.AWSManagedRulesBotControlRuleSet{ - InspectionLevel: aws.String(v.(string)), - }, - }) + m := tfList[0].(map[string]interface{}) + out := wafv2.UsernameField{ + Identifier: aws.String(m["identifier"].(string)), } - return c + + return &out +} + +func expandAWSManagedRulesBotControlRuleSet(tfList []interface{}) *wafv2.AWSManagedRulesBotControlRuleSet { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + m := tfList[0].(map[string]interface{}) + out := wafv2.AWSManagedRulesBotControlRuleSet{ + InspectionLevel: aws.String(m["inspection_level"].(string)), + } + + return &out } func expandRateBasedStatement(l []interface{}) *wafv2.RateBasedStatement { diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index d08aa460ae6..87162784032 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -947,9 +947,22 @@ func managedRuleGroupConfigSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, Optional: true, - MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "aws_managed_rules_bot_control_rule_set": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "inspection_level": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(wafv2.InspectionLevel_Values(), false), + }, + }, + }, + }, "login_path": { Type: schema.TypeString, Optional: true, @@ -959,12 +972,21 @@ func managedRuleGroupConfigSchema() *schema.Schema { ), }, "password_field": { - Type: schema.TypeString, + Type: schema.TypeList, Optional: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 512), - validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), - ), + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "identifier": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 512), + validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), + ), + }, + }, + }, }, "payload_type": { Type: schema.TypeString, @@ -972,17 +994,21 @@ func managedRuleGroupConfigSchema() *schema.Schema { ValidateFunc: validation.StringInSlice(wafv2.PayloadType_Values(), false), }, "username_field": { - Type: schema.TypeString, + Type: schema.TypeList, Optional: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 512), - validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), - ), - }, - "inspection_level": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice(wafv2.InspectionLevel_Values(), false), + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "identifier": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 512), + validation.StringMatch(regexp.MustCompile(`.*\S.*`), `must conform to pattern .*\S.* `), + ), + }, + }, + }, }, }, }, From a21fb4f6fe05316feafb4237c2e157247e81165a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 14:11:10 -0500 Subject: [PATCH 07/13] r/aws_wafv2_web_acl: flattenManagedRuleGroupConfigs() for list of more that 1 --- internal/service/wafv2/flex.go | 66 ++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index e7204829625..a96809cc3b5 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -2006,38 +2006,68 @@ func flattenManagedRuleGroupStatement(apiObject *wafv2.ManagedRuleGroupStatement } if apiObject.ManagedRuleGroupConfigs != nil { - tfMap["managed_rule_group_config"] = []interface{}{flattenManagedRuleGroupConfigs(apiObject.ManagedRuleGroupConfigs)} + tfMap["managed_rule_group_config"] = flattenManagedRuleGroupConfigs(apiObject.ManagedRuleGroupConfigs) } return []interface{}{tfMap} } -func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) interface{} { - tfMap := map[string]interface{}{} +func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) []interface{} { + if len(c) == 0 { + return nil + } + + var out []interface{} for _, config := range c { - if config.AWSManagedRulesBotControlRuleSet != nil { - tfMap["inspection_level"] = aws.StringValue(config.AWSManagedRulesBotControlRuleSet.InspectionLevel) + m := map[string]interface{}{ + "aws_managed_rules_bot_control_rule_set": flattenAWSManagedRulesBotControlRuleSet(config.AWSManagedRulesBotControlRuleSet), + "login_path": aws.StringValue(config.LoginPath), + "payload_type": aws.StringValue(config.PayloadType), + "password_field": flattenPasswordField(config.PasswordField), + "username_field": flattenUsernameField(config.UsernameField), } - if config.LoginPath != nil { - tfMap["login_path"] = aws.StringValue(config.LoginPath) - } + out = append(out, m) + } - if config.PasswordField != nil { - tfMap["password_field"] = aws.StringValue(config.PasswordField.Identifier) - } + return out +} - if config.UsernameField != nil { - tfMap["username_field"] = aws.StringValue(config.UsernameField.Identifier) - } +func flattenPasswordField(apiObject *wafv2.PasswordField) []interface{} { + if apiObject == nil { + return nil + } - if config.PayloadType != nil { - tfMap["payload_type"] = aws.StringValue(config.PayloadType) - } + m := map[string]interface{}{ + "identifier": aws.StringValue(apiObject.Identifier), + } + + return []interface{}{m} +} + +func flattenUsernameField(apiObject *wafv2.UsernameField) []interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{ + "identifier": aws.StringValue(apiObject.Identifier), + } + + return []interface{}{m} +} + +func flattenAWSManagedRulesBotControlRuleSet(apiObject *wafv2.AWSManagedRulesBotControlRuleSet) []interface{} { + if apiObject == nil { + return nil } - return tfMap + m := map[string]interface{}{ + "inspection_level": aws.StringValue(apiObject.InspectionLevel), + } + + return []interface{}{m} } func flattenRateBasedStatement(apiObject *wafv2.RateBasedStatement) interface{} { From 22d9e887b54f439d1dc60a60164e1f83159547e2 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 15:27:27 -0500 Subject: [PATCH 08/13] r/aws_wafv2_web_acl: tweaks to flatteners and expanders --- internal/service/wafv2/flex.go | 61 +++++++++++++++--------- internal/service/wafv2/schemas.go | 1 + internal/service/wafv2/web_acl_test.go | 64 +++++++++++++++----------- 3 files changed, 78 insertions(+), 48 deletions(-) diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index a96809cc3b5..fd27ec4cd6c 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -1003,24 +1003,35 @@ func expandManagedRuleGroupConfigs(tfList []interface{}) []*wafv2.ManagedRuleGro if !ok { continue } - var r wafv2.ManagedRuleGroupConfig + if v, ok := m["aws_managed_rules_bot_rule_set"].([]interface{}); ok && len(v) > 0 { - r.AWSManagedRulesBotControlRuleSet = expandAWSManagedRulesBotControlRuleSet(v) + out = append(out, &wafv2.ManagedRuleGroupConfig{ + AWSManagedRulesBotControlRuleSet: expandManagedRulesBotControlRuleSet(v), + }) } - if v, ok := m["login_path"].(string); ok && v != "" { - r.LoginPath = aws.String(v) + if v, ok := m["login_path"]; ok && len(v.(string)) > 0 { + out = append(out, &wafv2.ManagedRuleGroupConfig{ + LoginPath: aws.String(v.(string)), + }) } - if v, ok := m["payload_type"].(string); ok && v != "" { - r.PayloadType = aws.String(v) + + if v, ok := m["payload_type"]; ok && len(v.(string)) > 0 { + out = append(out, &wafv2.ManagedRuleGroupConfig{ + PayloadType: aws.String(v.(string)), + }) } + if v, ok := m["password_field"].([]interface{}); ok && len(v) > 0 { - r.PasswordField = expandPasswordField(v) + out = append(out, &wafv2.ManagedRuleGroupConfig{ + PasswordField: expandPasswordField(v), + }) } + if v, ok := m["username_field"].([]interface{}); ok && len(v) > 0 { - r.UsernameField = expandUsernameField(v) + out = append(out, &wafv2.ManagedRuleGroupConfig{ + UsernameField: expandUsernameField(v), + }) } - - out = append(out, &r) } return out @@ -1052,7 +1063,7 @@ func expandUsernameField(tfList []interface{}) *wafv2.UsernameField { return &out } -func expandAWSManagedRulesBotControlRuleSet(tfList []interface{}) *wafv2.AWSManagedRulesBotControlRuleSet { +func expandManagedRulesBotControlRuleSet(tfList []interface{}) *wafv2.AWSManagedRulesBotControlRuleSet { if len(tfList) == 0 || tfList[0] == nil { return nil } @@ -2017,21 +2028,27 @@ func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) []interfa return nil } - var out []interface{} - + m := make(map[string]interface{}) for _, config := range c { - m := map[string]interface{}{ - "aws_managed_rules_bot_control_rule_set": flattenAWSManagedRulesBotControlRuleSet(config.AWSManagedRulesBotControlRuleSet), - "login_path": aws.StringValue(config.LoginPath), - "payload_type": aws.StringValue(config.PayloadType), - "password_field": flattenPasswordField(config.PasswordField), - "username_field": flattenUsernameField(config.UsernameField), + if config.AWSManagedRulesBotControlRuleSet != nil { + m["aws_managed_rules_bot_control_rule_set"] = flattenManagedRulesBotControlRuleSet(config.AWSManagedRulesBotControlRuleSet) + } + if config.LoginPath != nil { + m["login_path"] = aws.StringValue(config.LoginPath) + } + if config.PayloadType != nil { + m["payload_type"] = aws.StringValue(config.PayloadType) + } + if config.PasswordField != nil { + m["password_field"] = flattenPasswordField(config.PasswordField) + } + if config.UsernameField != nil { + m["username_field"] = flattenUsernameField(config.UsernameField) } - out = append(out, m) } - return out + return []interface{}{m} } func flattenPasswordField(apiObject *wafv2.PasswordField) []interface{} { @@ -2058,7 +2075,7 @@ func flattenUsernameField(apiObject *wafv2.UsernameField) []interface{} { return []interface{}{m} } -func flattenAWSManagedRulesBotControlRuleSet(apiObject *wafv2.AWSManagedRulesBotControlRuleSet) []interface{} { +func flattenManagedRulesBotControlRuleSet(apiObject *wafv2.AWSManagedRulesBotControlRuleSet) []interface{} { if apiObject == nil { return nil } diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index 87162784032..b99ae0b54fd 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -947,6 +947,7 @@ func managedRuleGroupConfigSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, Optional: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "aws_managed_rules_bot_control_rule_set": { diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index fdc64462615..3974f711209 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -632,15 +632,15 @@ func TestAccWAFV2WebACL_ManagedRuleGroup_ManagedRuleGroupConfig(t *testing.T) { "override_action.0.count.#": "0", "override_action.0.none.#": "1", "statement.#": "1", - "statement.0.managed_rule_group_statement.#": "1", - "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", - "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", - "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", - "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/login", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field": "/password", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field": "/username", + "statement.0.managed_rule_group_statement.#": "1", + "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", + "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", + "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", + "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/login", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field.0.identifier": "/password", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field.0.identifier": "/username", }), ), }, @@ -658,15 +658,15 @@ func TestAccWAFV2WebACL_ManagedRuleGroup_ManagedRuleGroupConfig(t *testing.T) { "override_action.0.count.#": "0", "override_action.0.none.#": "1", "statement.#": "1", - "statement.0.managed_rule_group_statement.#": "1", - "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", - "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", - "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", - "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/app-login", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field": "/app-password", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field": "/app-username", + "statement.0.managed_rule_group_statement.#": "1", + "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", + "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", + "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", + "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/app-login", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field.0.identifier": "/app-password", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", + "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field.0.identifier": "/app-username", }), ), }, @@ -2911,10 +2911,16 @@ resource "aws_wafv2_web_acl" "test" { vendor_name = "AWS" managed_rule_group_config { - login_path = "/login" - password_field = "/password" - payload_type = "JSON" - username_field = "/username" + login_path = "/login" + payload_type = "JSON" + + password_field { + identifier = "/password" + } + + username_field { + identifier = "/username" + } } } } @@ -2965,10 +2971,16 @@ resource "aws_wafv2_web_acl" "test" { vendor_name = "AWS" managed_rule_group_config { - login_path = "/app-login" - password_field = "/app-password" - payload_type = "JSON" - username_field = "/app-username" + login_path = "/app-login" + payload_type = "JSON" + + password_field { + identifier = "/app-password" + } + + username_field { + identifier = "/app-username" + } } } } From aaecc68ca3756296799f753e1dc57fdfe28ae662 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 15:41:30 -0500 Subject: [PATCH 09/13] r/aws_wafv2_web_acl: documentation --- .changelog/28594.txt | 3 ++- website/docs/r/wafv2_web_acl.html.markdown | 23 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.changelog/28594.txt b/.changelog/28594.txt index 65936e8a0d0..4e5d9c1968b 100644 --- a/.changelog/28594.txt +++ b/.changelog/28594.txt @@ -1,2 +1,3 @@ ```release-note:enhancement -resource/aws_wafv2_web_acl: Add support for ManagedRuleGroupConfig``` +resource/aws_wafv2_web_acl: Add support for ManagedRuleGroupConfig +``` diff --git a/website/docs/r/wafv2_web_acl.html.markdown b/website/docs/r/wafv2_web_acl.html.markdown index d94b3cc5829..ed0339885b6 100644 --- a/website/docs/r/wafv2_web_acl.html.markdown +++ b/website/docs/r/wafv2_web_acl.html.markdown @@ -466,6 +466,7 @@ The `managed_rule_group_statement` block supports the following arguments: * `excluded_rule` - (Optional, **Deprecated**) The `rules` whose actions are set to `COUNT` by the web ACL, regardless of the action that is set on the rule. See [Excluded Rule](#excluded-rule) below for details. Use `rule_action_override` instead. (See the [documentation](https://docs.aws.amazon.com/waf/latest/APIReference/API_ManagedRuleGroupStatement.html#WAF-Type-ManagedRuleGroupStatement-ExcludedRules)) * `name` - (Required) Name of the managed rule group. * `rule_action_override` - (Optional) Action settings to use in the place of the rule actions that are configured inside the rule group. You specify one override for each rule whose action you want to change. See [Rule Action Override](#rule-action-override) below for details. +* `managed_rule_group_config`- (Optional) Additional information that's used by a managed rule group. See [Managed Rule Group Config](#managed-rule-group-config) for more details * `scope_down_statement` - Narrows the scope of the statement to matching web requests. This can be any nestable statement, and you can nest statements at any level below this scope-down statement. See [Statement](#statement) above for details. * `vendor_name` - (Required) Name of the managed rule group vendor. * `version` - (Optional) Version of the managed rule group. You can set `Version_1.0` or `Version_1.1` etc. If you want to use the default version, do not set anything. @@ -583,6 +584,28 @@ The `rule_action_override` block supports the following arguments: * `action_to_use` - (Required) Override action to use, in place of the configured action of the rule in the rule group. See [Action](#action) below for details. * `name` - (Required) Name of the rule to override. See the [documentation](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html) for a list of names in the appropriate rule group in use. +### Managed Rule Group Config + +The `managed_rule_group_config` block support the following arguments: + +* `aws_managed_rules_bot_control_rule_set` - (Optional) Additional configuration for using the Bot Control managed rule group. Use this to specify the inspection level that you want to use. See [AWS Managed Rules Bot Control Rule Set](#managed-rules-bot-control-rule-set) for more details +* `login_path` - (Optional) The path of the login endpoint for your application. +* `password_field` - (Optional) Details about your login page password field. See [Password Field](#password-field) for more details. +* `payload_type`- (Optional) The payload type for your login endpoint, either JSON or form encoded. +* `username_field` - (Optional) Details about your login page username field. See [Username Field](#username-field) for more details. + +### Managed Rules Bot Control Rule Set + +* `inspection_level` - (Optional) The inspection level to use for the Bot Control rule group. + +### Password Field + +* `identifier` - (Optional) The name of the password field. + +### Username Field + +* `identifier` - (Optional) The name of the username field. +* ### Field to Match The part of a web request that you want AWS WAF to inspect. Include the single `field_to_match` type that you want to inspect, with additional specifications as needed, according to the type. You specify a single request component in `field_to_match` for each rule statement that requires it. To inspect more than one component of a web request, create a separate rule statement for each component. See the [documentation](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-fields.html#waf-rule-statement-request-component) for more details. From 8edfe296ff41d932728ae60af6dfd9744b89d1ff Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 15:42:11 -0500 Subject: [PATCH 10/13] r/aws_wafv2_web_acl: documentation --- website/docs/r/wafv2_web_acl.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/wafv2_web_acl.html.markdown b/website/docs/r/wafv2_web_acl.html.markdown index ed0339885b6..613bbaeb5e9 100644 --- a/website/docs/r/wafv2_web_acl.html.markdown +++ b/website/docs/r/wafv2_web_acl.html.markdown @@ -605,7 +605,7 @@ The `managed_rule_group_config` block support the following arguments: ### Username Field * `identifier` - (Optional) The name of the username field. -* + ### Field to Match The part of a web request that you want AWS WAF to inspect. Include the single `field_to_match` type that you want to inspect, with additional specifications as needed, according to the type. You specify a single request component in `field_to_match` for each rule statement that requires it. To inspect more than one component of a web request, create a separate rule statement for each component. See the [documentation](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-fields.html#waf-rule-statement-request-component) for more details. From 0d40a0efbb0f6ec8816a1950120ec8a86fca7f61 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 3 Jan 2023 16:35:27 -0500 Subject: [PATCH 11/13] r/aws_wafv2_web_acl: linter --- internal/service/wafv2/flex.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index fd27ec4cd6c..df972d7bbad 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -2045,7 +2045,6 @@ func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) []interfa if config.UsernameField != nil { m["username_field"] = flattenUsernameField(config.UsernameField) } - } return []interface{}{m} From 828d04db35dcca7c42f122032bfd2cce163af0df Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 4 Jan 2023 12:45:29 -0600 Subject: [PATCH 12/13] r/aws_wafv2_web_acl: match managed_rule_group_configs behavior to API --- internal/service/wafv2/flex.go | 42 +++++++-------- internal/service/wafv2/schemas.go | 7 ++- internal/service/wafv2/web_acl_test.go | 60 ++++++++++++---------- website/docs/r/wafv2_web_acl.html.markdown | 2 +- 4 files changed, 56 insertions(+), 55 deletions(-) diff --git a/internal/service/wafv2/flex.go b/internal/service/wafv2/flex.go index df972d7bbad..42c81e97484 100644 --- a/internal/service/wafv2/flex.go +++ b/internal/service/wafv2/flex.go @@ -985,7 +985,7 @@ func expandManagedRuleGroupStatement(l []interface{}) *wafv2.ManagedRuleGroupSta if v, ok := m["version"]; ok && v != "" { r.Version = aws.String(v.(string)) } - if v, ok := m["managed_rule_group_config"].([]interface{}); ok && len(v) > 0 { + if v, ok := m["managed_rule_group_configs"].([]interface{}); ok && len(v) > 0 { r.ManagedRuleGroupConfigs = expandManagedRuleGroupConfigs(v) } @@ -1004,34 +1004,24 @@ func expandManagedRuleGroupConfigs(tfList []interface{}) []*wafv2.ManagedRuleGro continue } + var r wafv2.ManagedRuleGroupConfig if v, ok := m["aws_managed_rules_bot_rule_set"].([]interface{}); ok && len(v) > 0 { - out = append(out, &wafv2.ManagedRuleGroupConfig{ - AWSManagedRulesBotControlRuleSet: expandManagedRulesBotControlRuleSet(v), - }) + r.AWSManagedRulesBotControlRuleSet = expandManagedRulesBotControlRuleSet(v) } - if v, ok := m["login_path"]; ok && len(v.(string)) > 0 { - out = append(out, &wafv2.ManagedRuleGroupConfig{ - LoginPath: aws.String(v.(string)), - }) + if v, ok := m["login_path"].(string); ok && v != "" { + r.LoginPath = aws.String(v) } - - if v, ok := m["payload_type"]; ok && len(v.(string)) > 0 { - out = append(out, &wafv2.ManagedRuleGroupConfig{ - PayloadType: aws.String(v.(string)), - }) + if v, ok := m["payload_type"].(string); ok && v != "" { + r.PayloadType = aws.String(v) } - if v, ok := m["password_field"].([]interface{}); ok && len(v) > 0 { - out = append(out, &wafv2.ManagedRuleGroupConfig{ - PasswordField: expandPasswordField(v), - }) + r.PasswordField = expandPasswordField(v) } - if v, ok := m["username_field"].([]interface{}); ok && len(v) > 0 { - out = append(out, &wafv2.ManagedRuleGroupConfig{ - UsernameField: expandUsernameField(v), - }) + r.UsernameField = expandUsernameField(v) } + + out = append(out, &r) } return out @@ -2017,7 +2007,7 @@ func flattenManagedRuleGroupStatement(apiObject *wafv2.ManagedRuleGroupStatement } if apiObject.ManagedRuleGroupConfigs != nil { - tfMap["managed_rule_group_config"] = flattenManagedRuleGroupConfigs(apiObject.ManagedRuleGroupConfigs) + tfMap["managed_rule_group_configs"] = flattenManagedRuleGroupConfigs(apiObject.ManagedRuleGroupConfigs) } return []interface{}{tfMap} @@ -2028,8 +2018,10 @@ func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) []interfa return nil } - m := make(map[string]interface{}) + var out []interface{} + for _, config := range c { + m := make(map[string]interface{}) if config.AWSManagedRulesBotControlRuleSet != nil { m["aws_managed_rules_bot_control_rule_set"] = flattenManagedRulesBotControlRuleSet(config.AWSManagedRulesBotControlRuleSet) } @@ -2045,9 +2037,11 @@ func flattenManagedRuleGroupConfigs(c []*wafv2.ManagedRuleGroupConfig) []interfa if config.UsernameField != nil { m["username_field"] = flattenUsernameField(config.UsernameField) } + + out = append(out, m) } - return []interface{}{m} + return out } func flattenPasswordField(apiObject *wafv2.PasswordField) []interface{} { diff --git a/internal/service/wafv2/schemas.go b/internal/service/wafv2/schemas.go index b99ae0b54fd..cc2ab0efacb 100644 --- a/internal/service/wafv2/schemas.go +++ b/internal/service/wafv2/schemas.go @@ -841,9 +841,9 @@ func managedRuleGroupStatementSchema(level int) *schema.Schema { Required: true, ValidateFunc: validation.StringLenBetween(1, 128), }, - "rule_action_override": ruleActionOverrideSchema(), - "managed_rule_group_config": managedRuleGroupConfigSchema(), - "scope_down_statement": scopeDownStatementSchema(level - 1), + "rule_action_override": ruleActionOverrideSchema(), + "managed_rule_group_configs": managedRuleGroupConfigSchema(), + "scope_down_statement": scopeDownStatementSchema(level - 1), "vendor_name": { Type: schema.TypeString, Required: true, @@ -947,7 +947,6 @@ func managedRuleGroupConfigSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, Optional: true, - MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "aws_managed_rules_bot_control_rule_set": { diff --git a/internal/service/wafv2/web_acl_test.go b/internal/service/wafv2/web_acl_test.go index 3974f711209..938ab5177d2 100644 --- a/internal/service/wafv2/web_acl_test.go +++ b/internal/service/wafv2/web_acl_test.go @@ -632,15 +632,15 @@ func TestAccWAFV2WebACL_ManagedRuleGroup_ManagedRuleGroupConfig(t *testing.T) { "override_action.0.count.#": "0", "override_action.0.none.#": "1", "statement.#": "1", - "statement.0.managed_rule_group_statement.#": "1", - "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", - "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", - "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", - "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/login", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field.0.identifier": "/password", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field.0.identifier": "/username", + "statement.0.managed_rule_group_statement.#": "1", + "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", + "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", + "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", + "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.0.login_path": "/login", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.1.payload_type": "JSON", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.2.password_field.0.identifier": "/password", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.3.username_field.0.identifier": "/username", }), ), }, @@ -658,15 +658,15 @@ func TestAccWAFV2WebACL_ManagedRuleGroup_ManagedRuleGroupConfig(t *testing.T) { "override_action.0.count.#": "0", "override_action.0.none.#": "1", "statement.#": "1", - "statement.0.managed_rule_group_statement.#": "1", - "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", - "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", - "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", - "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.login_path": "/app-login", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.password_field.0.identifier": "/app-password", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.payload_type": "JSON", - "statement.0.managed_rule_group_statement.0.managed_rule_group_config.0.username_field.0.identifier": "/app-username", + "statement.0.managed_rule_group_statement.#": "1", + "statement.0.managed_rule_group_statement.0.name": "AWSManagedRulesATPRuleSet", + "statement.0.managed_rule_group_statement.0.vendor_name": "AWS", + "statement.0.managed_rule_group_statement.0.excluded_rule.#": "0", + "statement.0.managed_rule_group_statement.0.scope_down_statement.#": "0", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.0.login_path": "/app-login", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.1.payload_type": "JSON", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.2.password_field.0.identifier": "/app-password", + "statement.0.managed_rule_group_statement.0.managed_rule_group_configs.3.username_field.0.identifier": "/app-username", }), ), }, @@ -2910,14 +2910,18 @@ resource "aws_wafv2_web_acl" "test" { name = "AWSManagedRulesATPRuleSet" vendor_name = "AWS" - managed_rule_group_config { - login_path = "/login" + managed_rule_group_configs { + login_path = "/login" + } + managed_rule_group_configs { payload_type = "JSON" - + } + managed_rule_group_configs { password_field { identifier = "/password" } - + } + managed_rule_group_configs { username_field { identifier = "/username" } @@ -2970,14 +2974,18 @@ resource "aws_wafv2_web_acl" "test" { name = "AWSManagedRulesATPRuleSet" vendor_name = "AWS" - managed_rule_group_config { - login_path = "/app-login" + managed_rule_group_configs { + login_path = "/app-login" + } + managed_rule_group_configs { payload_type = "JSON" - + } + managed_rule_group_configs { password_field { identifier = "/app-password" } - + } + managed_rule_group_configs { username_field { identifier = "/app-username" } diff --git a/website/docs/r/wafv2_web_acl.html.markdown b/website/docs/r/wafv2_web_acl.html.markdown index 613bbaeb5e9..71d11d37cad 100644 --- a/website/docs/r/wafv2_web_acl.html.markdown +++ b/website/docs/r/wafv2_web_acl.html.markdown @@ -466,7 +466,7 @@ The `managed_rule_group_statement` block supports the following arguments: * `excluded_rule` - (Optional, **Deprecated**) The `rules` whose actions are set to `COUNT` by the web ACL, regardless of the action that is set on the rule. See [Excluded Rule](#excluded-rule) below for details. Use `rule_action_override` instead. (See the [documentation](https://docs.aws.amazon.com/waf/latest/APIReference/API_ManagedRuleGroupStatement.html#WAF-Type-ManagedRuleGroupStatement-ExcludedRules)) * `name` - (Required) Name of the managed rule group. * `rule_action_override` - (Optional) Action settings to use in the place of the rule actions that are configured inside the rule group. You specify one override for each rule whose action you want to change. See [Rule Action Override](#rule-action-override) below for details. -* `managed_rule_group_config`- (Optional) Additional information that's used by a managed rule group. See [Managed Rule Group Config](#managed-rule-group-config) for more details +* `managed_rule_group_configs`- (Optional) Additional information that's used by a managed rule group. Only one rule attribute is allowed in each config. See [Managed Rule Group Config](#managed-rule-group-config) for more details * `scope_down_statement` - Narrows the scope of the statement to matching web requests. This can be any nestable statement, and you can nest statements at any level below this scope-down statement. See [Statement](#statement) above for details. * `vendor_name` - (Required) Name of the managed rule group vendor. * `version` - (Optional) Version of the managed rule group. You can set `Version_1.0` or `Version_1.1` etc. If you want to use the default version, do not set anything. From 9305b353f7e586b12b7f785808633b4b72a94ccd Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Wed, 4 Jan 2023 14:14:26 -0600 Subject: [PATCH 13/13] r/aws_wafv2_web_acl: tweak docs --- website/docs/r/wafv2_web_acl.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/wafv2_web_acl.html.markdown b/website/docs/r/wafv2_web_acl.html.markdown index 71d11d37cad..a7ebd616925 100644 --- a/website/docs/r/wafv2_web_acl.html.markdown +++ b/website/docs/r/wafv2_web_acl.html.markdown @@ -466,7 +466,7 @@ The `managed_rule_group_statement` block supports the following arguments: * `excluded_rule` - (Optional, **Deprecated**) The `rules` whose actions are set to `COUNT` by the web ACL, regardless of the action that is set on the rule. See [Excluded Rule](#excluded-rule) below for details. Use `rule_action_override` instead. (See the [documentation](https://docs.aws.amazon.com/waf/latest/APIReference/API_ManagedRuleGroupStatement.html#WAF-Type-ManagedRuleGroupStatement-ExcludedRules)) * `name` - (Required) Name of the managed rule group. * `rule_action_override` - (Optional) Action settings to use in the place of the rule actions that are configured inside the rule group. You specify one override for each rule whose action you want to change. See [Rule Action Override](#rule-action-override) below for details. -* `managed_rule_group_configs`- (Optional) Additional information that's used by a managed rule group. Only one rule attribute is allowed in each config. See [Managed Rule Group Config](#managed-rule-group-config) for more details +* `managed_rule_group_configs`- (Optional) Additional information that's used by a managed rule group. Only one rule attribute is allowed in each config. See [Managed Rule Group Configs](#managed-rule-group-configs) for more details * `scope_down_statement` - Narrows the scope of the statement to matching web requests. This can be any nestable statement, and you can nest statements at any level below this scope-down statement. See [Statement](#statement) above for details. * `vendor_name` - (Required) Name of the managed rule group vendor. * `version` - (Optional) Version of the managed rule group. You can set `Version_1.0` or `Version_1.1` etc. If you want to use the default version, do not set anything. @@ -584,9 +584,9 @@ The `rule_action_override` block supports the following arguments: * `action_to_use` - (Required) Override action to use, in place of the configured action of the rule in the rule group. See [Action](#action) below for details. * `name` - (Required) Name of the rule to override. See the [documentation](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html) for a list of names in the appropriate rule group in use. -### Managed Rule Group Config +### Managed Rule Group Configs -The `managed_rule_group_config` block support the following arguments: +The `managed_rule_group_configs` block support the following arguments: * `aws_managed_rules_bot_control_rule_set` - (Optional) Additional configuration for using the Bot Control managed rule group. Use this to specify the inspection level that you want to use. See [AWS Managed Rules Bot Control Rule Set](#managed-rules-bot-control-rule-set) for more details * `login_path` - (Optional) The path of the login endpoint for your application.