From fbdcf746c8d8bf5b99b48764720432ac645c7bab Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 9 Oct 2017 09:10:03 +0100 Subject: [PATCH] Refactoring NSG's --- .../import_arm_network_security_group_test.go | 42 ++++++ .../resource_arm_network_security_group.go | 124 ++++++++---------- ...esource_arm_network_security_group_test.go | 106 +++++++++++---- .../r/network_security_group.html.markdown | 32 +++-- 4 files changed, 198 insertions(+), 106 deletions(-) diff --git a/azurerm/import_arm_network_security_group_test.go b/azurerm/import_arm_network_security_group_test.go index ace2cf541f79..314992dc0be4 100644 --- a/azurerm/import_arm_network_security_group_test.go +++ b/azurerm/import_arm_network_security_group_test.go @@ -27,3 +27,45 @@ func TestAccAzureRMNetworkSecurityGroup_importBasic(t *testing.T) { }, }) } + +func TestAccAzureRMNetworkSecurityGroup_importSingleRule(t *testing.T) { + resourceName := "azurerm_network_security_group.test" + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkSecurityGroup_singleRule(rInt, testLocation()), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMNetworkSecurityGroup_importMultipleRules(t *testing.T) { + resourceName := "azurerm_network_security_group.test" + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkSecurityGroup_anotherRule(rInt, testLocation()), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/azurerm/resource_arm_network_security_group.go b/azurerm/resource_arm_network_security_group.go index 7486172220b6..098deb001c97 100644 --- a/azurerm/resource_arm_network_security_group.go +++ b/azurerm/resource_arm_network_security_group.go @@ -1,13 +1,11 @@ package azurerm import ( - "bytes" "fmt" "log" "time" "github.com/Azure/azure-sdk-for-go/arm/network" - "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" @@ -38,7 +36,7 @@ func resourceArmNetworkSecurityGroup() *schema.Resource { "resource_group_name": resourceGroupNameSchema(), "security_rule": { - Type: schema.TypeSet, + Type: schema.TypeList, Optional: true, Computed: true, Elem: &schema.Resource{ @@ -108,7 +106,6 @@ func resourceArmNetworkSecurityGroup() *schema.Resource { }, }, }, - Set: resourceArmNetworkSecurityGroupRuleHash, }, "tags": tagsSchema(), @@ -117,8 +114,7 @@ func resourceArmNetworkSecurityGroup() *schema.Resource { } func resourceArmNetworkSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient) - secClient := client.secGroupClient + client := meta.(*ArmClient).secGroupClient name := d.Get("name").(string) location := d.Get("location").(string) @@ -127,7 +123,7 @@ func resourceArmNetworkSecurityGroupCreate(d *schema.ResourceData, meta interfac sgRules, sgErr := expandAzureRmSecurityRules(d) if sgErr != nil { - return fmt.Errorf("Error Building list of Network Security Group Rules: %s", sgErr) + return fmt.Errorf("Error Building list of Network Security Group Rules: %+v", sgErr) } azureRMLockByName(name, networkSecurityGroupResourceName) @@ -142,21 +138,21 @@ func resourceArmNetworkSecurityGroupCreate(d *schema.ResourceData, meta interfac Tags: expandTags(tags), } - _, error := secClient.CreateOrUpdate(resGroup, name, sg, make(chan struct{})) - err := <-error + _, createErr := client.CreateOrUpdate(resGroup, name, sg, make(chan struct{})) + err := <-createErr if err != nil { return err } - read, err := secClient.Get(resGroup, name, "") + read, err := client.Get(resGroup, name, "") if err != nil { return err } if read.ID == nil { - return fmt.Errorf("Cannot read Virtual Network %s (resource group %s) ID", name, resGroup) + return fmt.Errorf("Cannot read Virtual Network %q (resource group %q) ID", name, resGroup) } - log.Printf("[DEBUG] Waiting for NSG (%s) to become available", d.Get("name")) + log.Printf("[DEBUG] Waiting for NSG (%q) to become available", name) stateConf := &resource.StateChangeConf{ Pending: []string{"Updating", "Creating"}, Target: []string{"Succeeded"}, @@ -165,7 +161,7 @@ func resourceArmNetworkSecurityGroupCreate(d *schema.ResourceData, meta interfac MinTimeout: 15 * time.Second, } if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("Error waiting for NSG (%s) to become available: %s", d.Get("name"), err) + return fmt.Errorf("Error waiting for NSG (%q) to become available: %+v", name, err) } d.SetId(*read.ID) @@ -174,7 +170,7 @@ func resourceArmNetworkSecurityGroupCreate(d *schema.ResourceData, meta interfac } func resourceArmNetworkSecurityGroupRead(d *schema.ResourceData, meta interface{}) error { - secGroupClient := meta.(*ArmClient).secGroupClient + client := meta.(*ArmClient).secGroupClient id, err := parseAzureResourceID(d.Id()) if err != nil { @@ -183,29 +179,30 @@ func resourceArmNetworkSecurityGroupRead(d *schema.ResourceData, meta interface{ resGroup := id.ResourceGroup name := id.Path["networkSecurityGroups"] - resp, err := secGroupClient.Get(resGroup, name, "") + resp, err := client.Get(resGroup, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") return nil } - return fmt.Errorf("Error making Read request on Azure Network Security Group %s: %s", name, err) + return fmt.Errorf("Error making Read request on Azure Network Security Group %q: %+v", name, err) } - if resp.SecurityGroupPropertiesFormat.SecurityRules != nil { - d.Set("security_rule", flattenNetworkSecurityRules(resp.SecurityGroupPropertiesFormat.SecurityRules)) - } - - d.Set("resource_group_name", resGroup) d.Set("name", resp.Name) + d.Set("resource_group_name", resGroup) d.Set("location", azureRMNormalizeLocation(*resp.Location)) + + if props := resp.SecurityGroupPropertiesFormat; props != nil { + d.Set("security_rule", flattenNetworkSecurityRules(props.SecurityRules)) + } + flattenAndSetTags(d, resp.Tags) return nil } func resourceArmNetworkSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error { - secGroupClient := meta.(*ArmClient).secGroupClient + client := meta.(*ArmClient).secGroupClient id, err := parseAzureResourceID(d.Id()) if err != nil { @@ -214,62 +211,58 @@ func resourceArmNetworkSecurityGroupDelete(d *schema.ResourceData, meta interfac resGroup := id.ResourceGroup name := id.Path["networkSecurityGroups"] - _, error := secGroupClient.Delete(resGroup, name, make(chan struct{})) - err = <-error + _, deleteErr := client.Delete(resGroup, name, make(chan struct{})) + err = <-deleteErr return err } -func resourceArmNetworkSecurityGroupRuleHash(v interface{}) int { - var buf bytes.Buffer - m := v.(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%s-", m["protocol"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["source_port_range"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["destination_port_range"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["source_address_prefix"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["destination_address_prefix"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["access"].(string))) - buf.WriteString(fmt.Sprintf("%d-", m["priority"].(int))) - buf.WriteString(fmt.Sprintf("%s-", m["direction"].(string))) - - return hashcode.String(buf.String()) -} - -func flattenNetworkSecurityRules(rules *[]network.SecurityRule) []map[string]interface{} { - result := make([]map[string]interface{}, 0, len(*rules)) - for _, rule := range *rules { - sgRule := make(map[string]interface{}) - sgRule["name"] = *rule.Name - sgRule["destination_address_prefix"] = *rule.SecurityRulePropertiesFormat.DestinationAddressPrefix - sgRule["destination_port_range"] = *rule.SecurityRulePropertiesFormat.DestinationPortRange - sgRule["source_address_prefix"] = *rule.SecurityRulePropertiesFormat.SourceAddressPrefix - sgRule["source_port_range"] = *rule.SecurityRulePropertiesFormat.SourcePortRange - sgRule["priority"] = int(*rule.SecurityRulePropertiesFormat.Priority) - sgRule["access"] = rule.SecurityRulePropertiesFormat.Access - sgRule["direction"] = rule.SecurityRulePropertiesFormat.Direction - sgRule["protocol"] = rule.SecurityRulePropertiesFormat.Protocol - - if rule.SecurityRulePropertiesFormat.Description != nil { - sgRule["description"] = *rule.SecurityRulePropertiesFormat.Description +func flattenNetworkSecurityRules(rules *[]network.SecurityRule) []interface{} { + result := make([]interface{}, 0) + + if rules != nil { + for _, rule := range *rules { + sgRule := make(map[string]interface{}) + sgRule["name"] = *rule.Name + + if props := rule.SecurityRulePropertiesFormat; props != nil { + sgRule["destination_address_prefix"] = *props.DestinationAddressPrefix + sgRule["destination_port_range"] = *props.DestinationPortRange + sgRule["source_address_prefix"] = *props.SourceAddressPrefix + sgRule["source_port_range"] = *props.SourcePortRange + sgRule["priority"] = int(*props.Priority) + sgRule["access"] = string(props.Access) + sgRule["direction"] = string(props.Direction) + sgRule["protocol"] = string(props.Protocol) + + if props.Description != nil { + sgRule["description"] = *props.Description + } + } + + result = append(result, sgRule) } - - result = append(result, sgRule) } + return result } func expandAzureRmSecurityRules(d *schema.ResourceData) ([]network.SecurityRule, error) { - sgRules := d.Get("security_rule").(*schema.Set).List() - rules := make([]network.SecurityRule, 0, len(sgRules)) + sgRules := d.Get("security_rule").([]interface{}) + rules := make([]network.SecurityRule, 0) for _, sgRaw := range sgRules { data := sgRaw.(map[string]interface{}) + name := data["name"].(string) source_port_range := data["source_port_range"].(string) destination_port_range := data["destination_port_range"].(string) source_address_prefix := data["source_address_prefix"].(string) destination_address_prefix := data["destination_address_prefix"].(string) priority := int32(data["priority"].(int)) + access := data["access"].(string) + direction := data["direction"].(string) + protocol := data["protocol"].(string) properties := network.SecurityRulePropertiesFormat{ SourcePortRange: &source_port_range, @@ -277,16 +270,15 @@ func expandAzureRmSecurityRules(d *schema.ResourceData) ([]network.SecurityRule, SourceAddressPrefix: &source_address_prefix, DestinationAddressPrefix: &destination_address_prefix, Priority: &priority, - Access: network.SecurityRuleAccess(data["access"].(string)), - Direction: network.SecurityRuleDirection(data["direction"].(string)), - Protocol: network.SecurityRuleProtocol(data["protocol"].(string)), + Access: network.SecurityRuleAccess(access), + Direction: network.SecurityRuleDirection(direction), + Protocol: network.SecurityRuleProtocol(protocol), } if v := data["description"].(string); v != "" { properties.Description = &v } - name := data["name"].(string) rule := network.SecurityRule{ Name: &name, SecurityRulePropertiesFormat: &properties, @@ -298,11 +290,11 @@ func expandAzureRmSecurityRules(d *schema.ResourceData) ([]network.SecurityRule, return rules, nil } -func networkSecurityGroupStateRefreshFunc(client *ArmClient, resourceGroupName string, sgName string) resource.StateRefreshFunc { +func networkSecurityGroupStateRefreshFunc(client network.SecurityGroupsClient, resourceGroupName string, sgName string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - res, err := client.secGroupClient.Get(resourceGroupName, sgName, "") + res, err := client.Get(resourceGroupName, sgName, "") if err != nil { - return nil, "", fmt.Errorf("Error issuing read request in networkSecurityGroupStateRefreshFunc to Azure ARM for NSG '%s' (RG: '%s'): %s", sgName, resourceGroupName, err) + return nil, "", fmt.Errorf("Error issuing read request in networkSecurityGroupStateRefreshFunc for NSG '%s' (RG: '%s'): %+v", sgName, resourceGroupName, err) } return res, *res.SecurityGroupPropertiesFormat.ProvisioningState, nil diff --git a/azurerm/resource_arm_network_security_group_test.go b/azurerm/resource_arm_network_security_group_test.go index dad6eab11502..eda9861ae21d 100644 --- a/azurerm/resource_arm_network_security_group_test.go +++ b/azurerm/resource_arm_network_security_group_test.go @@ -2,12 +2,12 @@ package azurerm import ( "fmt" - "net/http" "testing" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func TestAccAzureRMNetworkSecurityGroup_basic(t *testing.T) { @@ -28,6 +28,49 @@ func TestAccAzureRMNetworkSecurityGroup_basic(t *testing.T) { }) } +func TestAccAzureRMNetworkSecurityGroup_singleRule(t *testing.T) { + resourceName := "azurerm_network_security_group.test" + rInt := acctest.RandInt() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkSecurityGroup_singleRule(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkSecurityGroupExists(resourceName), + ), + }, + }, + }) +} + +func TestAccAzureRMNetworkSecurityGroup_update(t *testing.T) { + resourceName := "azurerm_network_security_group.test" + rInt := acctest.RandInt() + location := testLocation() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkSecurityGroup_singleRule(rInt, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkSecurityGroupExists(resourceName), + ), + }, + { + Config: testAccAzureRMNetworkSecurityGroup_basic(rInt, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkSecurityGroupExists(resourceName), + ), + }, + }, + }) +} + func TestAccAzureRMNetworkSecurityGroup_disappears(t *testing.T) { resourceName := "azurerm_network_security_group.test" rInt := acctest.RandInt() @@ -87,7 +130,7 @@ func TestAccAzureRMNetworkSecurityGroup_addingExtraRules(t *testing.T) { CheckDestroy: testCheckAzureRMNetworkSecurityGroupDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkSecurityGroup_basic(rInt, testLocation()), + Config: testAccAzureRMNetworkSecurityGroup_singleRule(rInt, testLocation()), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkSecurityGroupExists(resourceName), resource.TestCheckResourceAttr(resourceName, "security_rule.#", "1"), @@ -110,24 +153,23 @@ func testCheckAzureRMNetworkSecurityGroupExists(name string) resource.TestCheckF rs, ok := s.RootModule().Resources[name] if !ok { - return fmt.Errorf("Not found: %s", name) + return fmt.Errorf("Not found: %q", name) } sgName := rs.Primary.Attributes["name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for network security group: %s", sgName) + return fmt.Errorf("Bad: no resource group found in state for network security group: %q", sgName) } - conn := testAccProvider.Meta().(*ArmClient).secGroupClient - - resp, err := conn.Get(resourceGroup, sgName, "") + client := testAccProvider.Meta().(*ArmClient).secGroupClient + resp, err := client.Get(resourceGroup, sgName, "") if err != nil { - return fmt.Errorf("Bad: Get on secGroupClient: %+v", err) - } + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Network Security Group %q (resource group: %q) does not exist", name, resourceGroup) + } - if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Network Security Group %q (resource group: %q) does not exist", name, resourceGroup) + return fmt.Errorf("Bad: Get on secGroupClient: %+v", err) } return nil @@ -145,15 +187,17 @@ func testCheckAzureRMNetworkSecurityGroupDisappears(name string) resource.TestCh sgName := rs.Primary.Attributes["name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for network security group: %s", sgName) + return fmt.Errorf("Bad: no resource group found in state for network security group: %q", sgName) } - conn := testAccProvider.Meta().(*ArmClient).secGroupClient - - _, error := conn.Delete(resourceGroup, sgName, make(chan struct{})) - err := <-error + client := testAccProvider.Meta().(*ArmClient).secGroupClient + deleteResp, deleteErr := client.Delete(resourceGroup, sgName, make(chan struct{})) + resp := <-deleteResp + err := <-deleteErr if err != nil { - return fmt.Errorf("Bad: Delete on secGroupClient: %+v", err) + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Bad: Delete on secGroupClient: %+v", err) + } } return nil @@ -161,7 +205,7 @@ func testCheckAzureRMNetworkSecurityGroupDisappears(name string) resource.TestCh } func testCheckAzureRMNetworkSecurityGroupDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*ArmClient).secGroupClient + client := testAccProvider.Meta().(*ArmClient).secGroupClient for _, rs := range s.RootModule().Resources { if rs.Type != "azurerm_network_security_group" { @@ -171,15 +215,16 @@ func testCheckAzureRMNetworkSecurityGroupDestroy(s *terraform.State) error { name := rs.Primary.Attributes["name"] resourceGroup := rs.Primary.Attributes["resource_group_name"] - resp, err := conn.Get(resourceGroup, name, "") + resp, err := client.Get(resourceGroup, name, "") if err != nil { - return nil + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + return err } - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Network Security Group still exists:\n%#v", resp.SecurityGroupPropertiesFormat) - } + return fmt.Errorf("Network Security Group still exists:\n%#v", resp.SecurityGroupPropertiesFormat) } return nil @@ -192,6 +237,21 @@ resource "azurerm_resource_group" "test" { location = "%s" } +resource "azurerm_network_security_group" "test" { + name = "acceptanceTestSecurityGroup1" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location) +} + +func testAccAzureRMNetworkSecurityGroup_singleRule(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + resource "azurerm_network_security_group" "test" { name = "acceptanceTestSecurityGroup1" location = "${azurerm_resource_group.test.location}" diff --git a/website/docs/r/network_security_group.html.markdown b/website/docs/r/network_security_group.html.markdown index 44c6522ca5d3..1e2e9df731bd 100644 --- a/website/docs/r/network_security_group.html.markdown +++ b/website/docs/r/network_security_group.html.markdown @@ -3,12 +3,13 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_network_security_group" sidebar_current: "docs-azurerm-resource-network-security-group" description: |- - Create a network security group that contains a list of network security rules. Network security groups enable inbound or outbound traffic to be enabled or denied. + Manages a network security group that contains a list of network security rules. Network security groups enable inbound or outbound traffic to be enabled or denied. + --- -# azurerm\_network\_security\_group +# azurerm_network_security_group -Create a network security group that contains a list of network security rules. +Manages a network security group that contains a list of network security rules. Network security groups enable inbound or outbound traffic to be enabled or denied. ~> **NOTE on Network Security Groups and Network Security Rules:** Terraform currently provides both a standalone [Network Security Rule resource](network_security_rule.html), and allows for Network Security Rules to be defined in-line within the [Network Security Group resource](network_security_group.html). @@ -24,7 +25,7 @@ resource "azurerm_resource_group" "test" { resource "azurerm_network_security_group" "test" { name = "acceptanceTestSecurityGroup1" - location = "West US" + location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" security_rule { @@ -49,16 +50,13 @@ resource "azurerm_network_security_group" "test" { The following arguments are supported: -* `name` - (Required) Specifies the name of the network security group. Changing this forces a - new resource to be created. +* `name` - (Required) Specifies the name of the network security group. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to - create the availability set. +* `resource_group_name` - (Required) The name of the resource group in which to create the availability set. Changing this forces a new resource to be created. * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `security_rule` - (Optional) Can be specified multiple times to define multiple - security rules. Each `security_rule` block supports fields documented below. +* `security_rule` - (Optional) One or more `security_rule` blocks as defined below. * `tags` - (Optional) A mapping of tags to assign to the resource. @@ -69,21 +67,21 @@ The `security_rule` block supports: * `description` - (Optional) A description for this rule. Restricted to 140 characters. -* `protocol` - (Required) Network protocol this rule applies to. Can be Tcp, Udp or * to match both. +* `protocol` - (Required) Network protocol this rule applies to. Can be `Tcp`, `Udp` or `*` to match both. -* `source_port_range` - (Required) Source Port or Range. Integer or range between 0 and 65535 or * to match any. +* `source_port_range` - (Required) Source Port or Range. Integer or range between `0` and `65535` or `*` to match any. -* `destination_port_range` - (Required) Destination Port or Range. Integer or range between 0 and 65535 or * to match any. +* `destination_port_range` - (Required) Destination Port or Range. Integer or range between `0` and `65535` or `*` to match any. -* `source_address_prefix` - (Required) CIDR or source IP range or * to match any IP. Tags such as ‘VirtualNetwork’, ‘AzureLoadBalancer’ and ‘Internet’ can also be used. +* `source_address_prefix` - (Required) CIDR or source IP range or * to match any IP. Tags such as `VirtualNetwork`, `AzureLoadBalancer` and `Internet` can also be used. -* `destination_address_prefix` - (Required) CIDR or destination IP range or * to match any IP. Tags such as ‘VirtualNetwork’, ‘AzureLoadBalancer’ and ‘Internet’ can also be used. +* `destination_address_prefix` - (Required) CIDR or destination IP range or * to match any IP. Tags such as `VirtualNetwork`, `AzureLoadBalancer` and `Internet` can also be used. -* `access` - (Required) Specifies whether network traffic is allowed or denied. Possible values are "Allow” and "Deny”. +* `access` - (Required) Specifies whether network traffic is allowed or denied. Possible values are `Allow` and `Deny`. * `priority` - (Required) Specifies the priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule. -* `direction` - (Required) The direction specifies if rule will be evaluated on incoming or outgoing traffic. Possible values are "Inbound” and "Outbound”. +* `direction` - (Required) The direction specifies if rule will be evaluated on incoming or outgoing traffic. Possible values are `Inbound` and `Outbound`. ## Attributes Reference