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

WAFv2: Added support for label_match_statement and rule_label #19576

Merged
15 changes: 15 additions & 0 deletions .changelog/19576.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```release-notes:enhancement
resource/aws_wafv2_web_acl: Add `rule_label` to rules.
```

```release-notes:enhancement
resource/aws_wafv2_web_acl: Added support for `label_match_statement` to rules.
```

```release-notes:enhancement
resource/aws_wafv2_rule_group: Add `rule_label` to rules.
```

```release-notes:enhancement
resource/aws_wafv2_rule_group: Added support for `label_match_statement` to rules.
```
127 changes: 126 additions & 1 deletion internal/service/wafv2/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ func wafv2EmptySchemaDeprecated() *schema.Schema {
}
}

func wafv2RuleLabelsSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 1024),
validation.StringMatch(regexp.MustCompile(`^[0-9A-Za-z_\-:]+$`), "must contain only alphanumeric, underscore, hyphen, and colon characters"),
),
},
},
},
}
}

func wafv2RootStatementSchema(level int) *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Expand All @@ -46,6 +65,7 @@ func wafv2RootStatementSchema(level int) *schema.Schema {
"byte_match_statement": wafv2ByteMatchStatementSchema(),
"geo_match_statement": wafv2GeoMatchStatementSchema(),
"ip_set_reference_statement": wafv2IpSetReferenceStatementSchema(),
"label_match_statement": wafv2LabelMatchStatementSchema(),
"not_statement": wafv2StatementSchema(level - 1),
"or_statement": wafv2StatementSchema(level - 1),
"regex_pattern_set_reference_statement": wafv2RegexPatternSetReferenceStatementSchema(),
Expand Down Expand Up @@ -74,6 +94,7 @@ func wafv2StatementSchema(level int) *schema.Schema {
"byte_match_statement": wafv2ByteMatchStatementSchema(),
"geo_match_statement": wafv2GeoMatchStatementSchema(),
"ip_set_reference_statement": wafv2IpSetReferenceStatementSchema(),
"label_match_statement": wafv2LabelMatchStatementSchema(),
"not_statement": wafv2StatementSchema(level - 1),
"or_statement": wafv2StatementSchema(level - 1),
"regex_pattern_set_reference_statement": wafv2RegexPatternSetReferenceStatementSchema(),
Expand Down Expand Up @@ -102,6 +123,7 @@ func wafv2StatementSchema(level int) *schema.Schema {
"byte_match_statement": wafv2ByteMatchStatementSchema(),
"geo_match_statement": wafv2GeoMatchStatementSchema(),
"ip_set_reference_statement": wafv2IpSetReferenceStatementSchema(),
"label_match_statement": wafv2LabelMatchStatementSchema(),
"regex_pattern_set_reference_statement": wafv2RegexPatternSetReferenceStatementSchema(),
"size_constraint_statement": wafv2SizeConstraintSchema(),
"sqli_match_statement": wafv2SqliMatchStatementSchema(),
Expand Down Expand Up @@ -207,6 +229,31 @@ func wafv2IpSetReferenceStatementSchema() *schema.Schema {
}
}

func wafv2LabelMatchStatementSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 1024),
validation.StringMatch(regexp.MustCompile(`^[0-9A-Za-z_\-:]+$`), "must contain only alphanumeric, underscore, hyphen, and colon characters"),
),
},
"scope": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(wafv2.LabelMatchScope_Values(), false),
},
},
},
}
}

func wafv2RegexPatternSetReferenceStatementSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Expand Down Expand Up @@ -545,13 +592,39 @@ func expandWafv2Rule(m map[string]interface{}) *wafv2.Rule {
return nil
}

return &wafv2.Rule{
rule := &wafv2.Rule{
Name: aws.String(m["name"].(string)),
Priority: aws.Int64(int64(m["priority"].(int))),
Action: expandWafv2RuleAction(m["action"].([]interface{})),
Statement: expandWafv2RootStatement(m["statement"].([]interface{})),
VisibilityConfig: expandWafv2VisibilityConfig(m["visibility_config"].([]interface{})),
}

if v, ok := m["rule_label"].(*schema.Set); ok && v.Len() > 0 {
rule.RuleLabels = expandWafv2RuleLabels(v.List())
}

return rule
}

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

labels := make([]*wafv2.Label, 0)

for _, label := range l {
if label == nil {
continue
}
m := label.(map[string]interface{})
labels = append(labels, &wafv2.Label{
Name: aws.String(m["name"].(string)),
})
}

return labels
}

func expandWafv2RuleAction(l []interface{}) *wafv2.RuleAction {
Expand Down Expand Up @@ -766,6 +839,10 @@ func expandWafv2Statement(m map[string]interface{}) *wafv2.Statement {
statement.GeoMatchStatement = expandWafv2GeoMatchStatement(v.([]interface{}))
}

if v, ok := m["label_match_statement"]; ok {
statement.LabelMatchStatement = expandWafv2LabelMatchStatement(v.([]interface{}))
}

if v, ok := m["not_statement"]; ok {
statement.NotStatement = expandWafv2NotStatement(v.([]interface{}))
}
Expand Down Expand Up @@ -974,6 +1051,21 @@ func expandWafv2GeoMatchStatement(l []interface{}) *wafv2.GeoMatchStatement {
return statement
}

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

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

statement := &wafv2.LabelMatchStatement{
Key: aws.String(m["key"].(string)),
Scope: aws.String(m["scope"].(string)),
}

return statement
}

func expandWafv2NotStatement(l []interface{}) *wafv2.NotStatement {
if len(l) == 0 || l[0] == nil {
return nil
Expand Down Expand Up @@ -1067,6 +1159,7 @@ func flattenWafv2Rules(r []*wafv2.Rule) interface{} {
m["action"] = flattenWafv2RuleAction(rule.Action)
m["name"] = aws.StringValue(rule.Name)
m["priority"] = int(aws.Int64Value(rule.Priority))
m["rule_label"] = flattenWafv2RuleLabels(rule.RuleLabels)
m["statement"] = flattenWafv2RootStatement(rule.Statement)
m["visibility_config"] = flattenWafv2VisibilityConfig(rule.VisibilityConfig)
out[i] = m
Expand Down Expand Up @@ -1184,6 +1277,21 @@ func flattenWafv2CustomHeader(h *wafv2.CustomHTTPHeader) map[string]interface{}
return m
}

func flattenWafv2RuleLabels(l []*wafv2.Label) []interface{} {
if len(l) == 0 {
return nil
}

out := make([]interface{}, len(l))
for i, label := range l {
out[i] = map[string]interface{}{
"name": aws.StringValue(label.Name),
}
}

return out
}

func flattenWafv2RootStatement(s *wafv2.Statement) interface{} {
if s == nil {
return []interface{}{}
Expand Down Expand Up @@ -1224,6 +1332,10 @@ func flattenWafv2Statement(s *wafv2.Statement) map[string]interface{} {
m["geo_match_statement"] = flattenWafv2GeoMatchStatement(s.GeoMatchStatement)
}

if s.LabelMatchStatement != nil {
m["label_match_statement"] = flattenWafv2LabelMatchStatement(s.LabelMatchStatement)
}

if s.NotStatement != nil {
m["not_statement"] = flattenWafv2NotStatement(s.NotStatement)
}
Expand Down Expand Up @@ -1404,6 +1516,19 @@ func flattenWafv2GeoMatchStatement(g *wafv2.GeoMatchStatement) interface{} {
return []interface{}{m}
}

func flattenWafv2LabelMatchStatement(l *wafv2.LabelMatchStatement) interface{} {
if l == nil {
return []interface{}{}
}

m := map[string]interface{}{
"key": aws.StringValue(l.Key),
"scope": aws.StringValue(l.Scope),
}

return []interface{}{m}
}

func flattenWafv2NotStatement(a *wafv2.NotStatement) interface{} {
if a == nil {
return []interface{}{}
Expand Down
1 change: 1 addition & 0 deletions internal/service/wafv2/rule_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func ResourceRuleGroup() *schema.Resource {
Type: schema.TypeInt,
Required: true,
},
"rule_label": wafv2RuleLabelsSchema(),
"statement": wafv2RootStatementSchema(3),
"visibility_config": wafv2VisibilityConfigSchema(),
},
Expand Down
Loading