Skip to content

Commit

Permalink
add missing properties in webapplication firewall policy (#23239)
Browse files Browse the repository at this point in the history
  • Loading branch information
wuxu92 authored Sep 20, 2023
1 parent 895a322 commit 40364bf
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,30 @@ func resourceWebApplicationFirewallPolicy() *pluginsdk.Resource {
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(webapplicationfirewallpolicies.WebApplicationFirewallRuleTypeMatchRule),
string(webapplicationfirewallpolicies.WebApplicationFirewallRuleTypeRateLimitRule),
string(webapplicationfirewallpolicies.WebApplicationFirewallRuleTypeInvalid),
}, false),
},
"name": {
Type: pluginsdk.TypeString,
Optional: true,
},
"rate_limit_duration": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(webapplicationfirewallpolicies.PossibleValuesForApplicationGatewayFirewallRateLimitDuration(), false),
},
"rate_limit_threshold": {
Type: pluginsdk.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
},
"group_rate_limit_by": {
// group variables combination not supported yet, use a single variable name
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(webapplicationfirewallpolicies.PossibleValuesForApplicationGatewayFirewallUserSessionVariable(), false),
},
},
},
},
Expand Down Expand Up @@ -349,6 +366,7 @@ func resourceWebApplicationFirewallPolicy() *pluginsdk.Resource {
Optional: true,
Default: true,
},

"mode": {
Type: pluginsdk.TypeString,
Optional: true,
Expand All @@ -358,23 +376,34 @@ func resourceWebApplicationFirewallPolicy() *pluginsdk.Resource {
}, false),
Default: string(webapplicationfirewallpolicies.WebApplicationFirewallModePrevention),
},

"request_body_check": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: true,
},

"file_upload_limit_in_mb": {
Type: pluginsdk.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(1, 4000),
Default: 100,
},

"max_request_body_size_in_kb": {
Type: pluginsdk.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(8, 2000),
Default: 128,
},

"request_body_inspect_limit_in_kb": {
Type: pluginsdk.TypeInt,
Optional: true,
Default: 128,
ValidateFunc: validation.IntAtLeast(0),
},

"log_scrubbing": {
Type: pluginsdk.TypeList,
MaxItems: 1,
Expand Down Expand Up @@ -618,6 +647,27 @@ func expandWebApplicationFirewallPolicyWebApplicationFirewallCustomRule(input []
RuleType: webapplicationfirewallpolicies.WebApplicationFirewallRuleType(ruleType),
}

if rateLimitDuration, ok := v["rate_limit_duration"]; ok && rateLimitDuration.(string) != "" {
result.RateLimitDuration = pointer.To(webapplicationfirewallpolicies.ApplicationGatewayFirewallRateLimitDuration(rateLimitDuration.(string)))
}

if rateLimitThreshHold, ok := v["rate_limit_threshold"]; ok && rateLimitThreshHold.(int) > 0 {
result.RateLimitThreshold = pointer.To(int64(rateLimitThreshHold.(int)))
}

if groupBy, ok := v["group_rate_limit_by"]; ok && groupBy.(string) != "" {
groups := []webapplicationfirewallpolicies.GroupByUserSession{
{
GroupByVariables: []webapplicationfirewallpolicies.GroupByVariable{
{
VariableName: webapplicationfirewallpolicies.ApplicationGatewayFirewallUserSessionVariable(groupBy.(string)),
},
},
},
}
result.GroupByUserSession = &groups
}

results = append(results, result)
}
return &results
Expand All @@ -639,13 +689,15 @@ func expandWebApplicationFirewallPolicyPolicySettings(input []interface{}) *weba
fileUploadLimitInMb := v["file_upload_limit_in_mb"].(int)

result := webapplicationfirewallpolicies.PolicySettings{
State: pointer.To(enabled),
Mode: pointer.To(webapplicationfirewallpolicies.WebApplicationFirewallMode(mode)),
RequestBodyCheck: pointer.To(requestBodyCheck),
MaxRequestBodySizeInKb: pointer.To(int64(maxRequestBodySizeInKb)),
FileUploadLimitInMb: pointer.To(int64(fileUploadLimitInMb)),
LogScrubbing: expandWebApplicationFirewallPolicyLogScrubbing(v["log_scrubbing"].([]interface{})),
State: pointer.To(enabled),
Mode: pointer.To(webapplicationfirewallpolicies.WebApplicationFirewallMode(mode)),
RequestBodyCheck: pointer.To(requestBodyCheck),
MaxRequestBodySizeInKb: pointer.To(int64(maxRequestBodySizeInKb)),
FileUploadLimitInMb: pointer.To(int64(fileUploadLimitInMb)),
LogScrubbing: expandWebApplicationFirewallPolicyLogScrubbing(v["log_scrubbing"].([]interface{})),
RequestBodyInspectLimitInKB: pointer.To(int64(v["request_body_inspect_limit_in_kb"].(int))),
}

return &result
}

Expand Down Expand Up @@ -961,6 +1013,14 @@ func flattenWebApplicationFirewallPolicyWebApplicationFirewallCustomRule(input *
v["match_conditions"] = flattenWebApplicationFirewallPolicyMatchCondition(item.MatchConditions)
v["priority"] = int(item.Priority)
v["rule_type"] = string(item.RuleType)
v["rate_limit_duration"] = pointer.From(item.RateLimitDuration)
v["rate_limit_threshold"] = pointer.From(item.RateLimitThreshold)

if item.GroupByUserSession != nil && len(*item.GroupByUserSession) > 0 {
if groupVariable := (*item.GroupByUserSession)[0].GroupByVariables; len(groupVariable) > 0 {
v["group_rate_limit_by"] = groupVariable[0].VariableName
}
}

results = append(results, v)
}
Expand All @@ -981,6 +1041,7 @@ func flattenWebApplicationFirewallPolicyPolicySettings(input *webapplicationfire
result["max_request_body_size_in_kb"] = int(pointer.From(input.MaxRequestBodySizeInKb))
result["file_upload_limit_in_mb"] = int(pointer.From(input.FileUploadLimitInMb))
result["log_scrubbing"] = flattenWebApplicationFirewallPolicyLogScrubbing(input.LogScrubbing)
result["request_body_inspect_limit_in_kb"] = pointer.From(input.RequestBodyInspectLimitInKB)

return []interface{}{result}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,35 @@ func TestAccWebApplicationFirewallPolicy_updateOverrideRules(t *testing.T) {
})
}

func TestAccWebApplicationFirewallPolicy_rateLimit(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_web_application_firewall_policy", "test")
r := WebApplicationFirewallResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.rateLimit(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.rateLimitUpdate(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.rateLimit(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccWebApplicationFirewallPolicy_knownCVEs(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_web_application_firewall_policy", "test")
r := WebApplicationFirewallResource{}
Expand Down Expand Up @@ -513,6 +542,174 @@ resource "azurerm_web_application_firewall_policy" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (WebApplicationFirewallResource) rateLimit(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_web_application_firewall_policy" "test" {
name = "acctestwafpolicy-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
tags = {
env = "test"
}
custom_rules {
name = "Rule1"
priority = 1
rule_type = "RateLimitRule"
rate_limit_duration = "FiveMins"
rate_limit_threshold = 100
group_rate_limit_by = "ClientAddr"
match_conditions {
match_variables {
variable_name = "RemoteAddr"
}
operator = "IPMatch"
negation_condition = false
match_values = ["192.168.1.0/24", "10.0.0.0/24"]
}
action = "Block"
}
managed_rules {
exclusion {
match_variable = "RequestHeaderNames"
selector = "x-shared-secret"
selector_match_operator = "Equals"
}
exclusion {
match_variable = "RequestCookieNames"
selector = "too-much-fun"
selector_match_operator = "EndsWith"
}
managed_rule_set {
type = "OWASP"
version = "3.2"
rule_group_override {
rule_group_name = "REQUEST-920-PROTOCOL-ENFORCEMENT"
rule {
id = "920300"
enabled = true
action = "Log"
}
rule {
id = "920440"
enabled = true
action = "Block"
}
}
}
}
policy_settings {
enabled = true
mode = "Prevention"
request_body_inspect_limit_in_kb = 1000
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (WebApplicationFirewallResource) rateLimitUpdate(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_web_application_firewall_policy" "test" {
name = "acctestwafpolicy-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
tags = {
env = "test"
}
custom_rules {
name = "Rule1"
priority = 1
rule_type = "RateLimitRule"
rate_limit_duration = "OneMin"
rate_limit_threshold = 123
group_rate_limit_by = "GeoLocation"
match_conditions {
match_variables {
variable_name = "RemoteAddr"
}
operator = "IPMatch"
negation_condition = false
match_values = ["192.168.1.0/24", "10.0.0.0/24"]
}
action = "Block"
}
managed_rules {
exclusion {
match_variable = "RequestHeaderNames"
selector = "x-shared-secret"
selector_match_operator = "Equals"
}
exclusion {
match_variable = "RequestCookieNames"
selector = "too-much-fun"
selector_match_operator = "EndsWith"
}
managed_rule_set {
type = "OWASP"
version = "3.2"
rule_group_override {
rule_group_name = "REQUEST-920-PROTOCOL-ENFORCEMENT"
rule {
id = "920300"
enabled = true
action = "Log"
}
rule {
id = "920440"
enabled = true
action = "Block"
}
}
}
}
policy_settings {
enabled = true
mode = "Prevention"
request_body_inspect_limit_in_kb = 1234
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (WebApplicationFirewallResource) updateOverrideRules(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
10 changes: 9 additions & 1 deletion website/docs/r/web_application_firewall_policy.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,18 @@ The `custom_rules` block supports the following:

* `priority` - (Required) Describes priority of the rule. Rules with a lower value will be evaluated before rules with a higher value.

* `rule_type` - (Required) Describes the type of rule. Possible values are `MatchRule` and `Invalid`.
* `rule_type` - (Required) Describes the type of rule. Possible values are `MatchRule`, `RateLimitRule` and `Invalid`.

* `match_conditions` - (Required) One or more `match_conditions` blocks as defined below.

* `action` - (Required) Type of action. Possible values are `Allow`, `Block` and `Log`.

* `rate_limit_duration` - (Optional) Specifies the duration at which the rate limit policy will be applied. Should be used with `RateLimitRule` rule type. Possible values are `FiveMins` and `OneMin`.

* `rate_limit_threshold` - (Optional) Specifies the threshold value for the rate limit policy. Must be greater than or equal to 1 if provided.

* `group_rate_limit_by` - (Optional) Specifies what grouping the rate limit will count requests by. Possible values are `GeoLocation`, `ClientAddr` and `None`.

---

The `match_conditions` block supports the following:
Expand Down Expand Up @@ -184,6 +190,8 @@ The `policy_settings` block supports the following:

* `log_scrubbing` - (Optional) One `log_scrubbing` block as defined below.

* `request_body_inspect_limit_in_kb` - (Optional) Specifies the maximum request body inspection limit in KB for the Web Application Firewall. Defaults to `128`.

---

The `managed_rules` block supports the following:
Expand Down

0 comments on commit 40364bf

Please sign in to comment.