diff --git a/azurerm/helpers/validate/port_or_port_range.go b/azurerm/helpers/validate/port_or_port_range.go new file mode 100644 index 000000000000..5f0df421691a --- /dev/null +++ b/azurerm/helpers/validate/port_or_port_range.go @@ -0,0 +1,63 @@ +package validate + +import ( + "fmt" + "regexp" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func PortOrPortRangeWithin(min int, max int) schema.SchemaValidateFunc { + return func(i interface{}, k string) (warnings []string, errors []error) { + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) + return + } + + assertWithinRange := func(n int) error { + if n < min || n > max { + return fmt.Errorf("port %d is out of range (%d-%d)", n, min, max) + } + + return nil + } + + // Allowed format including: `num` or `num1-num2` (num1 < num2). + groups := regexp.MustCompile(`^(\d+)((-)(\d+))?$`).FindStringSubmatch(v) + if len(groups) != 5 { + errors = append(errors, fmt.Errorf("invalid format of %q", k)) + return + } + + if groups[2] == "" { + p1, _ := strconv.Atoi(groups[1]) + + if err := assertWithinRange(p1); err != nil { + errors = append(errors, err) + return + } + } else { + p1, _ := strconv.Atoi(groups[1]) + p2, _ := strconv.Atoi(groups[4]) + + if p1 >= p2 { + errors = append(errors, fmt.Errorf("beginning port (%d) should be less than ending port (%d)", p1, p2)) + return + } + + if err := assertWithinRange(p1); err != nil { + errors = append(errors, err) + return + } + + if err := assertWithinRange(p2); err != nil { + errors = append(errors, err) + return + } + } + + return nil, nil + } +} diff --git a/azurerm/helpers/validate/port_or_port_range_test.go b/azurerm/helpers/validate/port_or_port_range_test.go new file mode 100644 index 000000000000..e704e12c1545 --- /dev/null +++ b/azurerm/helpers/validate/port_or_port_range_test.go @@ -0,0 +1,51 @@ +package validate + +import ( + "testing" +) + +func TestPortOrPortRangeWithin(t *testing.T) { + testData := []struct { + input string + expected bool + }{ + { + input: "0", + expected: false, + }, + { + input: "65536", + expected: false, + }, + { + input: "1", + expected: true, + }, + { + input: "65535", + expected: true, + }, + { + input: "634", + expected: true, + }, + { + input: "1000-50000", + expected: true, + }, + { + input: "1-65535", + expected: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q..", v.input) + + _, errors := PortOrPortRangeWithin(1, 65535)(v.input, "port_or_port_range") + actual := len(errors) == 0 + if v.expected != actual { + t.Fatalf("Expected %t but got %t", v.expected, actual) + } + } +} diff --git a/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource.go b/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource.go index bf7d146763ac..02dee4d0ce70 100644 --- a/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource.go +++ b/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + azValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/firewall/parse" @@ -257,7 +258,7 @@ func resourceFirewallPolicyRuleCollectionGroup() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.FirewallPolicyRulePort, + ValidateFunc: azValidate.PortOrPortRangeWithin(1, 65535), }, }, }, @@ -349,7 +350,7 @@ func resourceFirewallPolicyRuleCollectionGroup() *schema.Resource { Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.FirewallPolicyRulePort, + ValidateFunc: azValidate.PortOrPortRangeWithin(1, 64000), }, }, "translated_address": { diff --git a/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource_test.go b/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource_test.go index 4670479537d1..ad9e3f1c4702 100644 --- a/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource_test.go +++ b/azurerm/internal/services/firewall/firewall_policy_rule_collection_group_resource_test.go @@ -147,6 +147,7 @@ resource "azurerm_firewall_policy" "test" { location = azurerm_resource_group.test.location dns { network_rule_fqdn_enabled = false + proxy_enabled = true } } @@ -183,7 +184,7 @@ resource "azurerm_firewall_policy_rule_collection_group" "test" { port = 443 } source_addresses = ["10.0.0.1"] - destination_fqdns = [".microsoft.com"] + destination_fqdns = ["terraform.io"] } rule { name = "app_rule_collection1_rule2" @@ -196,7 +197,7 @@ resource "azurerm_firewall_policy_rule_collection_group" "test" { port = 443 } source_ip_groups = [azurerm_ip_group.test_source.id] - destination_fqdns = [".microsoft.com"] + destination_fqdns = ["terraform.io"] } rule { name = "app_rule_collection1_rule3" @@ -284,6 +285,7 @@ resource "azurerm_firewall_policy" "test" { location = azurerm_resource_group.test.location dns { network_rule_fqdn_enabled = false + proxy_enabled = true } } @@ -320,7 +322,7 @@ resource "azurerm_firewall_policy_rule_collection_group" "test" { port = 443 } source_addresses = ["10.0.0.1", "10.0.0.2"] - destination_fqdns = [".microsoft.com"] + destination_fqdns = ["terraform.io"] } rule { name = "app_rule_collection1_rule2" @@ -329,7 +331,7 @@ resource "azurerm_firewall_policy_rule_collection_group" "test" { port = 80 } source_ip_groups = [azurerm_ip_group.test_source.id] - destination_fqdns = [".microsoft.com"] + destination_fqdns = ["terraform.io"] } rule { name = "app_rule_collection1_rule3" @@ -355,21 +357,21 @@ resource "azurerm_firewall_policy_rule_collection_group" "test" { protocols = ["TCP", "UDP"] source_addresses = ["10.0.0.1"] destination_addresses = ["192.168.1.2", "ApiManagement"] - destination_ports = ["80", "1000-2000"] + destination_ports = ["80", "1-65535"] } rule { name = "network_rule_collection1_rule2" protocols = ["TCP", "UDP"] source_addresses = ["10.0.0.1", "10.0.0.2"] destination_fqdns = ["time.windows.com"] - destination_ports = ["80", "1000-2000"] + destination_ports = ["80", "1-65535"] } rule { name = "network_rule_collection1_rule3" protocols = ["TCP"] source_ip_groups = [azurerm_ip_group.test_source.id] destination_ip_groups = [azurerm_ip_group.test_destination.id] - destination_ports = ["80", "1000-2000"] + destination_ports = ["80", "1-65535"] } } diff --git a/azurerm/internal/services/firewall/validate/firewall_policy_rule_port.go b/azurerm/internal/services/firewall/validate/firewall_policy_rule_port.go deleted file mode 100644 index 03e07e923dd0..000000000000 --- a/azurerm/internal/services/firewall/validate/firewall_policy_rule_port.go +++ /dev/null @@ -1,53 +0,0 @@ -package validate - -import ( - "fmt" - "regexp" - "strconv" -) - -func FirewallPolicyRulePort(i interface{}, k string) (warnings []string, errors []error) { - v, ok := i.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) - return - } - - assertWithinRnage := func(n int) error { - if n < 0 || n > 64000 { - return fmt.Errorf("port %d is out of range (0-64000)", n) - } - return nil - } - - // Allowed format including: `num` or `num1-num2` (num1 < num2). - groups := regexp.MustCompile(`^(\d+)((-)(\d+))?$`).FindStringSubmatch(v) - if len(groups) != 5 { - errors = append(errors, fmt.Errorf("invalid format of %q", k)) - return - } - if groups[2] == "" { - p1, _ := strconv.Atoi(groups[1]) - if err := assertWithinRnage(p1); err != nil { - errors = append(errors, err) - return - } - } else { - p1, _ := strconv.Atoi(groups[1]) - p2, _ := strconv.Atoi(groups[4]) - if p1 >= p2 { - errors = append(errors, fmt.Errorf("beginning port (%d) should be less than endping port (%d)", p1, p2)) - return - } - if err := assertWithinRnage(p1); err != nil { - errors = append(errors, err) - return - } - if err := assertWithinRnage(p2); err != nil { - errors = append(errors, err) - return - } - } - - return nil, nil -}