From 5275a6d120e119c72a94706208ee7f3113c20eac Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Wed, 1 May 2019 21:57:59 +0100 Subject: [PATCH 1/4] Application gateway: disabled rule groups --- azurerm/resource_arm_application_gateway.go | 77 +++++++++++ .../resource_arm_application_gateway_test.go | 130 ++++++++++++++++++ 2 files changed, 207 insertions(+) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index 58c7966848a7..60cc3c74e1de 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -902,6 +902,27 @@ func resourceArmApplicationGateway() *schema.Resource { "3.0", }, false), }, + "disabled_rule_group": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rule_group_name": { + Type: schema.TypeString, + Required: true, + }, + + "rules": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, "file_upload_limit_mb": { Type: schema.TypeInt, Optional: true, @@ -2612,6 +2633,30 @@ func expandApplicationGatewayWafConfig(d *schema.ResourceData) *network.Applicat requestBodyCheck := v["request_body_check"].(bool) maxRequestBodySizeInKb := v["max_request_body_size_kb"].(int) + disabledRuleGroups := make([]network.ApplicationGatewayFirewallDisabledRuleGroup, 0) + + for _, raw := range v["disabled_rule_group"].([]interface{}) { + v := raw.(map[string]interface{}) + + name := v["rule_group_name"].(string) + + rules := make([]int32, 0) + + for _, rule := range v["rules"].([]interface{}) { + rules = append(rules, int32(rule.(int))) + } + + output := network.ApplicationGatewayFirewallDisabledRuleGroup{ + RuleGroupName: utils.String(name), + } + + if len(rules) > 0 { + output.Rules = &rules + } + + disabledRuleGroups = append(disabledRuleGroups, output) + } + return &network.ApplicationGatewayWebApplicationFirewallConfiguration{ Enabled: utils.Bool(enabled), FirewallMode: network.ApplicationGatewayFirewallMode(mode), @@ -2620,6 +2665,7 @@ func expandApplicationGatewayWafConfig(d *schema.ResourceData) *network.Applicat FileUploadLimitInMb: utils.Int32(int32(fileUploadLimitInMb)), RequestBodyCheck: utils.Bool(requestBodyCheck), MaxRequestBodySizeInKb: utils.Int32(int32(maxRequestBodySizeInKb)), + DisabledRuleGroups: &disabledRuleGroups, } } @@ -2657,11 +2703,42 @@ func flattenApplicationGatewayWafConfig(input *network.ApplicationGatewayWebAppl output["max_request_body_size_kb"] = int(*input.MaxRequestBodySizeInKb) } + if input.DisabledRuleGroups != nil { + output["disabled_rule_group"] = flattenApplicationGatewayDisabledRuleGroups(input.DisabledRuleGroups) + } + results = append(results, output) return results } +func flattenApplicationGatewayDisabledRuleGroups(input *[]network.ApplicationGatewayFirewallDisabledRuleGroup) []interface{} { + result := make([]interface{}, 0) + if input == nil { + return []interface{}{} + } + + for _, v := range *input { + output := map[string]interface{}{} + + output["rule_group_name"] = string(*v.RuleGroupName) + + if v.Rules != nil { + for _, r := range *v.Rules { + rulesOutput := map[string]interface{}{} + + rulesOutput["rules"] = r + + result = append(result, rulesOutput) + } + } + + result = append(result, output) + } + + return []interface{}{result} +} + func expandApplicationGatewayCustomErrorConfigurations(vs []interface{}) *[]network.ApplicationGatewayCustomError { results := make([]network.ApplicationGatewayCustomError, 0) diff --git a/azurerm/resource_arm_application_gateway_test.go b/azurerm/resource_arm_application_gateway_test.go index 31079575000b..c89fcaa22485 100644 --- a/azurerm/resource_arm_application_gateway_test.go +++ b/azurerm/resource_arm_application_gateway_test.go @@ -494,6 +494,38 @@ func TestAccAzureRMApplicationGateway_webApplicationFirewall(t *testing.T) { }) } +func TestAccAzureRMApplicationGateway_webApplicationFirewallDisabledRuleGroups(t *testing.T) { + resourceName := "azurerm_application_gateway.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_webApplicationFirewallDisabledRuleGroups(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "sku.0.name", "WAF_v2"), + resource.TestCheckResourceAttr(resourceName, "sku.0.tier", "WAF_v2"), + resource.TestCheckResourceAttr(resourceName, "sku.0.capacity", "1"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.firewall_mode", "Detection"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.rule_set_type", "OWASP"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.rule_set_version", "3.0"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.file_upload_limit_mb", "100"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.request_body_check", "true"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.max_request_body_size_kb", "100"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.0.rule_group_name", "REQUEST-913-SCANNER-DETECTION"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.0.rules.0", "913100"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.1.rule_group_name", "REQUEST-920-PROTOCOL-ENFORCEMENT"), + ), + }, + }, + }) +} + func TestAccAzureRMApplicationGateway_connectionDraining(t *testing.T) { resourceName := "azurerm_application_gateway.test" ri := tf.AccRandTimeInt() @@ -1998,6 +2030,104 @@ resource "azurerm_application_gateway" "test" { `, template, rInt) } +func testAccAzureRMApplicationGateway_webApplicationFirewallDisabledRuleGroups(rInt int, location string) string { + template := testAccAzureRMApplicationGateway_template(rInt, location) + return fmt.Sprintf(` +%s + +# since these variables are re-used - a locals block makes this more maintainable +locals { + backend_address_pool_name = "${azurerm_virtual_network.test.name}-beap" + frontend_port_name = "${azurerm_virtual_network.test.name}-feport" + frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip" + http_setting_name = "${azurerm_virtual_network.test.name}-be-htst" + listener_name = "${azurerm_virtual_network.test.name}-httplstn" + request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt" +} + +resource "azurerm_public_ip" "test_standard" { + name = "acctest-pubip-%d-standard" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "Standard" + allocation_method = "Static" +} + +resource "azurerm_application_gateway" "test" { + name = "acctestag-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + sku { + name = "WAF_v2" + tier = "WAF_v2" + capacity = 1 + } + + waf_configuration { + enabled = true + firewall_mode = "Detection" + rule_set_type = "OWASP" + rule_set_version = "3.0" + file_upload_limit_mb = 100 + request_body_check = true + max_request_body_size_kb = 100 + + disabled_rule_group { + rule_group_name = "REQUEST-913-SCANNER-DETECTION" + rules = [ 913100 ] + } + + disabled_rule_group { + rule_group_name = "REQUEST-920-PROTOCOL-ENFORCEMENT" + } + } + + gateway_ip_configuration { + name = "my-gateway-ip-configuration" + subnet_id = "${azurerm_subnet.test.id}" + } + + frontend_port { + name = "${local.frontend_port_name}" + port = 80 + } + + frontend_ip_configuration { + name = "${local.frontend_ip_configuration_name}" + public_ip_address_id = "${azurerm_public_ip.test_standard.id}" + } + + backend_address_pool { + name = "${local.backend_address_pool_name}" + } + + backend_http_settings { + name = "${local.http_setting_name}" + cookie_based_affinity = "Disabled" + port = 80 + protocol = "Http" + request_timeout = 1 + } + + http_listener { + name = "${local.listener_name}" + frontend_ip_configuration_name = "${local.frontend_ip_configuration_name}" + frontend_port_name = "${local.frontend_port_name}" + protocol = "Http" + } + + request_routing_rule { + name = "${local.request_routing_rule_name}" + rule_type = "Basic" + http_listener_name = "${local.listener_name}" + backend_address_pool_name = "${local.backend_address_pool_name}" + backend_http_settings_name = "${local.http_setting_name}" + } +} +`, template, rInt, rInt) +} + func testAccAzureRMApplicationGateway_connectionDraining(rInt int, location string) string { template := testAccAzureRMApplicationGateway_template(rInt, location) return fmt.Sprintf(` From 1e57568fd6dc0befc95912574f68fafee553a2b7 Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Thu, 2 May 2019 19:48:27 +0100 Subject: [PATCH 2/4] Update docs --- website/docs/r/application_gateway.html.markdown | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/website/docs/r/application_gateway.html.markdown b/website/docs/r/application_gateway.html.markdown index c90463dc6147..e258e693c364 100644 --- a/website/docs/r/application_gateway.html.markdown +++ b/website/docs/r/application_gateway.html.markdown @@ -397,6 +397,16 @@ A `waf_configuration` block supports the following: * `max_request_body_size_kb` - (Optional) The Maximum Request Body Size in KB. Accepted values are in the range `1`KB to `128`KB. Defaults to `128`KB. +* `disabled_rule_group` - (Optional) a disabled rule block + +--- + +A `disabled_rule_group` block supports the following: + +* `rule_group_name` - (Required) The rule group name to disable, e.g. `REQUEST-913-SCANNER-DETECTION`. + +* `rules` - (Optional) A list of rules to disabled, e.g. `[ 913100 ]`. Disables all rules in the group if `rules` is not specified. + --- A `custom_error_configuration` block supports the following: From 8f563e612eb394a3a9de125e3b4a2aac1979e245 Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Fri, 3 May 2019 09:11:29 +0100 Subject: [PATCH 3/4] Better but not working --- azurerm/resource_arm_application_gateway.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index 60cc3c74e1de..30d4b4dcca83 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -2724,13 +2724,12 @@ func flattenApplicationGatewayDisabledRuleGroups(input *[]network.ApplicationGat output["rule_group_name"] = string(*v.RuleGroupName) if v.Rules != nil { + rulesOutput := make([]interface{}, 0) for _, r := range *v.Rules { - rulesOutput := map[string]interface{}{} - - rulesOutput["rules"] = r - - result = append(result, rulesOutput) + rulesOutput = append(rulesOutput, r) } + + output["rules"] = rulesOutput } result = append(result, output) From 53fbd84d67b1d7b373051e6fd6db7b61e90fc295 Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Fri, 3 May 2019 14:23:35 +0100 Subject: [PATCH 4/4] Fix tests and lint --- azurerm/resource_arm_application_gateway.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index 30d4b4dcca83..4cbf7b59dc9b 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -2721,7 +2721,7 @@ func flattenApplicationGatewayDisabledRuleGroups(input *[]network.ApplicationGat for _, v := range *input { output := map[string]interface{}{} - output["rule_group_name"] = string(*v.RuleGroupName) + output["rule_group_name"] = *v.RuleGroupName if v.Rules != nil { rulesOutput := make([]interface{}, 0) @@ -2735,7 +2735,7 @@ func flattenApplicationGatewayDisabledRuleGroups(input *[]network.ApplicationGat result = append(result, output) } - return []interface{}{result} + return result } func expandApplicationGatewayCustomErrorConfigurations(vs []interface{}) *[]network.ApplicationGatewayCustomError {