From c702fd2a963f7ac870c25b44df970985832b6eb7 Mon Sep 17 00:00:00 2001 From: "Till Markus (INST-CSS/BSV-OS)" Date: Wed, 8 May 2019 09:47:53 +0200 Subject: [PATCH] resource_arm_application_gateway: add review fixes -> flatten, expand methods for group_rules, doc fixes, additional test steps --- azurerm/resource_arm_application_gateway.go | 115 +++++++++-------- .../resource_arm_application_gateway_test.go | 122 ++++++++++++++++++ .../docs/r/application_gateway.html.markdown | 4 +- 3 files changed, 183 insertions(+), 58 deletions(-) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index 27e7c2e2621bd..787747e0d28bb 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -949,14 +949,15 @@ func resourceArmApplicationGateway() *schema.Resource { "REQUEST-941-APPLICATION-ATTACK-XSS", "REQUEST-942-APPLICATION-ATTACK-SQLI", "REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION", - }, true), + }, false), }, "rules": { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeInt, + Type: schema.TypeInt, + ValidateFunc: validation.IntAtLeast(1), }, }, }, @@ -2655,29 +2656,6 @@ 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 _, disabledRuleGroup := range v["disabled_rule_group"].([]interface{}) { - disabledRuleGroupMap := disabledRuleGroup.(map[string]interface{}) - - ruleGroupName := disabledRuleGroupMap["rule_group_name"].(string) - - rules := make([]int32, 0) - for _, rule := range disabledRuleGroupMap["rules"].([]interface{}) { - rules = append(rules, int32(rule.(int))) - } - - if len(rules) == 0 { - rules = nil - } - - ruleGroup := network.ApplicationGatewayFirewallDisabledRuleGroup{ - RuleGroupName: utils.String(ruleGroupName), - Rules: &rules, - } - - disabledRuleGroups = append(disabledRuleGroups, ruleGroup) - } - return &network.ApplicationGatewayWebApplicationFirewallConfiguration{ Enabled: utils.Bool(enabled), FirewallMode: network.ApplicationGatewayFirewallMode(mode), @@ -2686,7 +2664,7 @@ func expandApplicationGatewayWafConfig(d *schema.ResourceData) *network.Applicat FileUploadLimitInMb: utils.Int32(int32(fileUploadLimitInMb)), RequestBodyCheck: utils.Bool(requestBodyCheck), MaxRequestBodySizeInKb: utils.Int32(int32(maxRequestBodySizeInKb)), - DisabledRuleGroups: &disabledRuleGroups, + DisabledRuleGroups: expandApplicationGatewayFirewallDisabledRuleGroup(v["disabled_rule_group"].([]interface{})), } } @@ -2712,37 +2690,10 @@ func flattenApplicationGatewayWafConfig(input *network.ApplicationGatewayWebAppl output["rule_set_version"] = *input.RuleSetVersion } - ruleGroups := make([]interface{}, 0) - if disabledRuleGroups := input.DisabledRuleGroups; disabledRuleGroups != nil { - for _, ruleGroup := range *disabledRuleGroups { - ruleGroupOutput := map[string]interface{}{} - - if ruleGroup.RuleGroupName != nil { - ruleGroupOutput["rule_group_name"] = *ruleGroup.RuleGroupName - } - - ruleOutputs := make([]interface{}, 0) - if rules := ruleGroup.Rules; rules != nil { - for _, rule := range *rules { - ruleOutputs = append(ruleOutputs, rule) - } - } - ruleGroupOutput["rules"] = ruleOutputs - - ruleGroups = append(ruleGroups, ruleGroupOutput) - } - - output["disabled_rule_group"] = ruleGroups - } - - if input.RequestBodyCheck != nil { - output["request_body_check"] = *input.RequestBodyCheck - } - - if input.MaxRequestBodySizeInKb != nil { - output["max_request_body_size_kb"] = *input.MaxRequestBodySizeInKb + if input.DisabledRuleGroups != nil { + output["disabled_rule_group"] = flattenApplicationGateWayDisabledRuleGroups(input.DisabledRuleGroups) } - + if input.FileUploadLimitInMb != nil { output["file_upload_limit_mb"] = int(*input.FileUploadLimitInMb) } @@ -2760,6 +2711,58 @@ func flattenApplicationGatewayWafConfig(input *network.ApplicationGatewayWebAppl return results } +func expandApplicationGatewayFirewallDisabledRuleGroup(d []interface{}) *[]network.ApplicationGatewayFirewallDisabledRuleGroup { + if len(d) == 0 { + return nil + } + + disabledRuleGroups := make([]network.ApplicationGatewayFirewallDisabledRuleGroup, 0) + for _, disabledRuleGroup := range d { + disabledRuleGroupMap := disabledRuleGroup.(map[string]interface{}) + + ruleGroupName := disabledRuleGroupMap["rule_group_name"].(string) + + ruleGroup := network.ApplicationGatewayFirewallDisabledRuleGroup{ + RuleGroupName: utils.String(ruleGroupName), + } + + rules := make([]int32, 0) + for _, rule := range disabledRuleGroupMap["rules"].([]interface{}) { + rules = append(rules, int32(rule.(int))) + } + + if len(rules) > 0 { + ruleGroup.Rules = &rules + } + + disabledRuleGroups = append(disabledRuleGroups, ruleGroup) + } + return &disabledRuleGroups +} + +func flattenApplicationGateWayDisabledRuleGroups(input *[]network.ApplicationGatewayFirewallDisabledRuleGroup) []interface{} { + ruleGroups := make([]interface{}, 0) + for _, ruleGroup := range *input { + ruleGroupOutput := map[string]interface{}{} + + if ruleGroup.RuleGroupName != nil { + ruleGroupOutput["rule_group_name"] = *ruleGroup.RuleGroupName + } + + ruleOutputs := make([]interface{}, 0) + if rules := ruleGroup.Rules; rules != nil { + for _, rule := range *rules { + ruleOutputs = append(ruleOutputs, rule) + } + } + ruleGroupOutput["rules"] = ruleOutputs + + ruleGroups = append(ruleGroups, ruleGroupOutput) + + } + return ruleGroups +} + 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 ff2ee8872e476..3fcf493ea0489 100644 --- a/azurerm/resource_arm_application_gateway_test.go +++ b/azurerm/resource_arm_application_gateway_test.go @@ -569,6 +569,27 @@ func TestAccAzureRMApplicationGateway_webApplicationFirewall_disabledRuleGroups( resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.2.rule_group_name", "REQUEST-942-APPLICATION-ATTACK-SQLI"), ), }, + { + Config: testAccAzureRMApplicationGateway_webApplicationFirewall_disabledRuleGroups_enabled_some_rules(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.request_body_check", "true"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.max_request_body_size_kb", "128"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.file_upload_limit_mb", "100"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.0.rule_group_name", "REQUEST-921-PROTOCOL-ATTACK"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.0.rules.0", "921110"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.0.rules.1", "921151"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.0.rules.2", "921180"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.0.disabled_rule_group.1.rule_group_name", "REQUEST-942-APPLICATION-ATTACK-SQLI"), + ), + }, }, }) } @@ -2217,6 +2238,107 @@ resource "azurerm_application_gateway" "test" { `, template, rInt, rInt) } +func testAccAzureRMApplicationGateway_webApplicationFirewall_disabledRuleGroups_enabled_some_rules(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" + request_body_check = true + max_request_body_size_kb = 128 + file_upload_limit_mb = 100 + + disabled_rule_group { + rule_group_name = "REQUEST-921-PROTOCOL-ATTACK" + rules = [921110, 921151, 921180] + } + + disabled_rule_group { + rule_group_name = "REQUEST-942-APPLICATION-ATTACK-SQLI" + } + + + } + + 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_template(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/application_gateway.html.markdown b/website/docs/r/application_gateway.html.markdown index 8fa648cf75fde..09ca0409a8a43 100644 --- a/website/docs/r/application_gateway.html.markdown +++ b/website/docs/r/application_gateway.html.markdown @@ -391,7 +391,7 @@ A `waf_configuration` block supports the following: * `rule_set_version` - (Required) The Version of the Rule Set used for this Web Application Firewall. -* `disabled_rule_group` - (Optional) one or many `disabled_rule_group` blocks as defined below. +* `disabled_rule_group` - (Optional) one or more `disabled_rule_group` blocks as defined below. * `file_upload_limit_mb` - (Optional) The File Upload Limit in MB. Accepted values are in the range `1`MB to `500`MB. Defaults to `100`MB. @@ -405,7 +405,7 @@ A `disabled_rule_group` block supports the following: * `rule_group_name` - (Required) The rule group where specific rules should be disabled. Accepted values are: `crs_20_protocol_violations`, `crs_21_protocol_anomalies`, `crs_23_request_limits`, `crs_30_http_policy`, `crs_35_bad_robots`, `crs_40_generic_attacks`, `crs_41_sql_injection_attacks`, `crs_41_xss_attacks`, `crs_42_tight_security`, `crs_45_trojans`, `REQUEST-911-METHOD-ENFORCEMENT`, `REQUEST-913-SCANNER-DETECTION`, `REQUEST-920-PROTOCOL-ENFORCEMENT`, `REQUEST-921-PROTOCOL-ATTACK`, `REQUEST-930-APPLICATION-ATTACK-LFI`, `REQUEST-931-APPLICATION-ATTACK-RFI`, `REQUEST-932-APPLICATION-ATTACK-RCE`, `REQUEST-933-APPLICATION-ATTACK-PHP`, `REQUEST-941-APPLICATION-ATTACK-XSS`, `REQUEST-942-APPLICATION-ATTACK-SQLI`, `REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION` -* `rules` - (Optional) A list of rule numbers which should be disabled in that group. Example: [921110, 921151, 921180] if group is set to `REQUEST-921-PROTOCOL-ATTACK`. Disables all rules in the group if `rules` is not specified. +* `rules` - (Optional) A list of rules which should be disabled in that group. Disables all rules in the specified group if `rules` is not specified. ---