From 49dbb261b8bfcbc17f1e4b860db16e22ed3980f0 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 1 Jun 2018 14:17:00 -0600 Subject: [PATCH 1/5] Adding network rules to storage accounts --- azurerm/resource_arm_storage_account.go | 172 +++++++++++++++++++ azurerm/resource_arm_storage_account_test.go | 121 +++++++++++++ website/docs/r/storage_account.html.markdown | 55 ++++++ 3 files changed, 348 insertions(+) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index c95c8839d337..015535310769 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -141,6 +141,48 @@ func resourceArmStorageAccount() *schema.Resource { Optional: true, }, + "network_rules": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bypass": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(storage.AzureServices), + string(storage.Logging), + string(storage.Metrics), + string(storage.None), + }, true), + }, + Set: schema.HashString, + }, + "default_access_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "ip_rules": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "virtual_network_subnet_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + }, + }, + "primary_location": { Type: schema.TypeString, Computed: true, @@ -245,6 +287,8 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e storageType := fmt.Sprintf("%s_%s", accountTier, replicationType) storageAccountEncryptionSource := d.Get("account_encryption_source").(string) + networkRules := expandStorageAccountNetworkRules(d) + parameters := storage.AccountCreateParameters{ Location: &location, Sku: &storage.Sku{ @@ -261,6 +305,7 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e KeySource: storage.KeySource(storageAccountEncryptionSource), }, EnableHTTPSTrafficOnly: &enableHTTPSTrafficOnly, + NetworkRuleSet: networkRules, }, } @@ -457,6 +502,22 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("enable_https_traffic_only") } + if d.HasChange("network_rules") { + networkRules := expandStorageAccountNetworkRules(d) + + opts := storage.AccountUpdateParameters{ + AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ + NetworkRuleSet: networkRules, + }, + } + _, err := client.Update(ctx, resourceGroupName, storageAccountName, opts) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account network_rules %q: %+v", storageAccountName, err) + } + + d.SetPartial("network_rules") + } + d.Partial(false) return nil } @@ -571,6 +632,12 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err d.Set("secondary_table_endpoint", "") } } + + if networkRules := props.NetworkRuleSet; networkRules != nil { + if err := d.Set("network_rules", flattenStorageAccountNetworkRules(networkRules)); err != nil { + return fmt.Errorf("Error flattening `network_rules`: %+v", err) + } + } } d.Set("primary_access_key", accessKeys[0].Value) @@ -626,6 +693,111 @@ func flattenStorageAccountCustomDomain(input *storage.CustomDomain) []interface{ return []interface{}{domain} } +func expandStorageAccountNetworkRules(d *schema.ResourceData) *storage.NetworkRuleSet { + networkRules := d.Get("network_rules").([]interface{}) + if networkRules == nil || len(networkRules) == 0 { + return nil + } + + networkRule := networkRules[0].(map[string]interface{}) + networkRuleSet := &storage.NetworkRuleSet{} + + networkRuleSet.IPRules = expandStorageAccountIPRules(networkRule) + networkRuleSet.VirtualNetworkRules = expandStorageAccountVirtualNetworks(networkRule) + networkRuleSet.Bypass = expandStorageAccountBypass(networkRule) + if networkRule["default_access_enabled"].(bool) { + networkRuleSet.DefaultAction = storage.DefaultActionAllow + } else { + networkRuleSet.DefaultAction = storage.DefaultActionDeny + } + + return networkRuleSet +} + +func expandStorageAccountIPRules(networkRule map[string]interface{}) *[]storage.IPRule { + ipRulesInfo := networkRule["ip_rules"].(*schema.Set).List() + ipRules := make([]storage.IPRule, len(ipRulesInfo)) + + for i, ipRuleConfig := range ipRulesInfo { + attrs := ipRuleConfig.(string) + ipRule := storage.IPRule{ + IPAddressOrRange: utils.String(attrs), + Action: storage.Allow, + } + ipRules[i] = ipRule + } + + return &ipRules +} + +func expandStorageAccountVirtualNetworks(networkRule map[string]interface{}) *[]storage.VirtualNetworkRule { + virtualNetworkInfo := networkRule["virtual_network_subnet_ids"].(*schema.Set).List() + virtualNetworks := make([]storage.VirtualNetworkRule, len(virtualNetworkInfo)) + + for i, virtualNetworkConfig := range virtualNetworkInfo { + attrs := virtualNetworkConfig.(string) + virtualNetwork := storage.VirtualNetworkRule{ + VirtualNetworkResourceID: utils.String(attrs), + Action: storage.Allow, + } + virtualNetworks[i] = virtualNetwork + } + + return &virtualNetworks +} + +func expandStorageAccountBypass(networkRule map[string]interface{}) storage.Bypass { + bypassInfo := networkRule["bypass"].(*schema.Set).List() + + var bypassValues []string + for _, bypassConfig := range bypassInfo { + bypassValues = append(bypassValues, bypassConfig.(string)) + } + + return storage.Bypass(strings.Join(bypassValues, ", ")) +} + +func flattenStorageAccountNetworkRules(input *storage.NetworkRuleSet) []interface{} { + networkRules := make(map[string]interface{}, 0) + + networkRules["ip_rules"] = schema.NewSet(schema.HashString, flattenStorageAccountIPRules(input.IPRules)) + networkRules["virtual_network_subnet_ids"] = schema.NewSet(schema.HashString, flattenStorageAccountVirtualNetworks(input.VirtualNetworkRules)) + if input.DefaultAction != "" { + networkRules["default_access_enabled"] = (input.DefaultAction == storage.DefaultActionAllow) + } + networkRules["bypass"] = schema.NewSet(schema.HashString, flattenStorageAccountBypass(input.Bypass)) + return []interface{}{networkRules} +} + +func flattenStorageAccountIPRules(input *[]storage.IPRule) []interface{} { + ipRules := make([]interface{}, len(*input)) + for i, ipRule := range *input { + ipRules[i] = *ipRule.IPAddressOrRange + } + + return ipRules +} + +func flattenStorageAccountVirtualNetworks(input *[]storage.VirtualNetworkRule) []interface{} { + virtualNetworks := make([]interface{}, len(*input)) + for i, virtualNetwork := range *input { + virtualNetworks[i] = *virtualNetwork.VirtualNetworkResourceID + } + + return virtualNetworks +} + +func flattenStorageAccountBypass(input storage.Bypass) []interface{} { + bypassValues := strings.Split(string(input), ", ") + bypass := make([]interface{}, len(bypassValues)) + + for i, value := range bypassValues { + bypass[i] = value + } + + return bypass +} + func validateArmStorageAccountName(v interface{}, k string) (ws []string, es []error) { input := v.(string) diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index 8a50dca6654d..e1f58b8151e7 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -345,6 +345,42 @@ func TestAccAzureRMStorageAccount_NonStandardCasing(t *testing.T) { }) } +func TestAccAzureRMStorageAccount_networkRules(t *testing.T) { + resourceName := "azurerm_storage_account.testsa" + ri := acctest.RandInt() + rs := acctest.RandString(4) + location := testLocation() + preConfig := testAccAzureRMStorageAccount_networkRules(ri, rs, location) + postConfig := testAccAzureRMStorageAccount_networkRulesUpdate(ri, rs, location) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.ip_rules.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.virtual_network_subnet_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.default_access_enabled", "false"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.ip_rules.#", "2"), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.virtual_network_subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.default_access_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.bypass.#", "2"), + ), + }, + }, + }) +} + func testCheckAzureRMStorageAccountExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API @@ -738,3 +774,88 @@ resource "azurerm_storage_account" "testsa" { } `, rInt, location, rString) } + +func testAccAzureRMStorageAccount_networkRules(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "testAccAzureRMSA-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.testrg.location}" + resource_group_name = "${azurerm_resource_group.testrg.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = "${azurerm_resource_group.testrg.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" + service_endpoints = ["Microsoft.Storage"] + } + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + network_rules { + ip_rules = ["127.0.0.1"] + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } + + tags { + environment = "production" + } +} +`, rInt, location, rInt, rInt, rString) +} + +func testAccAzureRMStorageAccount_networkRulesUpdate(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "testAccAzureRMSA-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.testrg.location}" + resource_group_name = "${azurerm_resource_group.testrg.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = "${azurerm_resource_group.testrg.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" + service_endpoints = ["Microsoft.Storage"] + } + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + network_rules { + ip_rules = ["127.0.0.1", "127.0.0.2"] + bypass = ["Logging", "Metrics"] + default_access_enabled = true + } + + tags { + environment = "production" + } +} +`, rInt, location, rInt, rInt, rString) +} diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index f2eb13964f24..0aefa5668875 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -31,6 +31,48 @@ resource "azurerm_storage_account" "testsa" { } ``` +## Example Usage with Network Rules + +```hcl +resource "azurerm_resource_group" "testrg" { + name = "resourceGroupName" + location = "westus" +} + +resource "azurerm_virtual_network" "test" { + name = "virtnetname" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.testrg.location}" + resource_group_name = "${azurerm_resource_group.testrg.name}" +} + +resource "azurerm_subnet" "test" { + name = "subnetname" + resource_group_name = "${azurerm_resource_group.testrg.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" + service_endpoints = ["Microsoft.Sql","Microsoft.Storage"] + } + +resource "azurerm_storage_account" "testsa" { + name = "storageaccountname" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + network_rules { + ip_rules = ["127.0.0.1"] + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } + + tags { + environment = "staging" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -70,6 +112,8 @@ The following arguments are supported: * `custom_domain` - (Optional) A `custom_domain` block as documented below. +* `network_rules` - (Optional) A `network_rules` block as documented below. + * `tags` - (Optional) A mapping of tags to assign to the resource. --- @@ -79,6 +123,17 @@ The following arguments are supported: * `name` - (Optional) The Custom Domain Name to use for the Storage Account, which will be validated by Azure. * `use_subdomain` - (Optional) Should the Custom Domain Name be validated by using indirect CNAME validation? +--- + +* `network_rules` supports the following: + +* `bypass` - (Optional) Specifies whether traffic is bypassed for Logging/Metrics/AzureServices. Valid options are +any combination of `Logging`, `Metrics`, `AzureServices`, or `None`. +* `default_access_enabled` - (Optional) Boolean flag to specify the default action of allow or deny when no other rules +match. +* `ip_rules` - (Optional) List of IP or IP ranges in CIDR Format. Only IPV4 addresses are allowed. +* `virtual_network_subnet_ids` - (Optional) A list of resource ids for subnets. + ~> **Note:** [More information on Validation is available here](https://docs.microsoft.com/en-gb/azure/storage/blobs/storage-custom-domain-name) ## Attributes Reference From 781b1b12cf03685f4f005c8acd99ccfd53a85f57 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 1 Jun 2018 14:55:29 -0600 Subject: [PATCH 2/5] Fmting --- azurerm/resource_arm_storage_account.go | 13 ++++++++----- azurerm/resource_arm_storage_account_test.go | 10 +++++----- website/docs/r/storage_account.html.markdown | 10 +++++----- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 015535310769..ef742f04c332 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -145,6 +145,7 @@ func resourceArmStorageAccount() *schema.Resource { Type: schema.TypeList, MaxItems: 1, Optional: true, + Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "bypass": { @@ -165,7 +166,7 @@ func resourceArmStorageAccount() *schema.Resource { "default_access_enabled": { Type: schema.TypeBool, Optional: true, - Default: false, + Computed: true, }, "ip_rules": { Type: schema.TypeSet, @@ -705,10 +706,12 @@ func expandStorageAccountNetworkRules(d *schema.ResourceData) *storage.NetworkRu networkRuleSet.IPRules = expandStorageAccountIPRules(networkRule) networkRuleSet.VirtualNetworkRules = expandStorageAccountVirtualNetworks(networkRule) networkRuleSet.Bypass = expandStorageAccountBypass(networkRule) - if networkRule["default_access_enabled"].(bool) { - networkRuleSet.DefaultAction = storage.DefaultActionAllow - } else { - networkRuleSet.DefaultAction = storage.DefaultActionDeny + if val, ok := networkRule["default_access_enabled"]; ok { + if val.(bool) { + networkRuleSet.DefaultAction = storage.DefaultActionAllow + } else { + networkRuleSet.DefaultAction = storage.DefaultActionDeny + } } return networkRuleSet diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index e1f58b8151e7..ab9360b4da1b 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -803,12 +803,12 @@ resource "azurerm_storage_account" "testsa" { location = "${azurerm_resource_group.testrg.location}" account_tier = "Standard" - account_replication_type = "LRS" + account_replication_type = "LRS" - network_rules { - ip_rules = ["127.0.0.1"] - virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] - } + network_rules { + ip_rules = ["127.0.0.1"] + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } tags { environment = "production" diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 0aefa5668875..ee01fec15290 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -60,12 +60,12 @@ resource "azurerm_storage_account" "testsa" { location = "${azurerm_resource_group.testrg.location}" account_tier = "Standard" - account_replication_type = "LRS" + account_replication_type = "LRS" - network_rules { - ip_rules = ["127.0.0.1"] - virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] - } + network_rules { + ip_rules = ["127.0.0.1"] + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } tags { environment = "staging" From 078445947ff84cf4033ee502a603273e3e8c4955 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 1 Jun 2018 14:57:23 -0600 Subject: [PATCH 3/5] Fmting --- azurerm/resource_arm_storage_account_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index ab9360b4da1b..248365e4f739 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -845,13 +845,13 @@ resource "azurerm_storage_account" "testsa" { location = "${azurerm_resource_group.testrg.location}" account_tier = "Standard" - account_replication_type = "LRS" + account_replication_type = "LRS" - network_rules { - ip_rules = ["127.0.0.1", "127.0.0.2"] - bypass = ["Logging", "Metrics"] - default_access_enabled = true - } + network_rules { + ip_rules = ["127.0.0.1", "127.0.0.2"] + bypass = ["Logging", "Metrics"] + default_access_enabled = true + } tags { environment = "production" From 5aee1eaa0b499c7d9f6efc26601e97ede5871c85 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 4 Jun 2018 12:59:35 -0600 Subject: [PATCH 4/5] Removing default access attribute --- azurerm/import_arm_storage_account_test.go | 25 ++++++++++++++ azurerm/resource_arm_storage_account.go | 29 +++++----------- azurerm/resource_arm_storage_account_test.go | 35 ++++++++++++++++++-- website/docs/r/storage_account.html.markdown | 2 -- 4 files changed, 66 insertions(+), 25 deletions(-) diff --git a/azurerm/import_arm_storage_account_test.go b/azurerm/import_arm_storage_account_test.go index 652d4f73db1e..2dfb535b0970 100644 --- a/azurerm/import_arm_storage_account_test.go +++ b/azurerm/import_arm_storage_account_test.go @@ -155,3 +155,28 @@ func TestAccAzureRMStorageAccount_importEnableHttpsTrafficOnly(t *testing.T) { }, }) } + +func TestAccAzureRMStorageAccount_importNetworkRules(t *testing.T) { + resourceName := "azurerm_storage_account.testsa" + + ri := acctest.RandInt() + rs := acctest.RandString(4) + config := testAccAzureRMStorageAccount_networkRules(ri, rs, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: config, + }, + + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index ef742f04c332..73e208ca48a1 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -145,7 +145,6 @@ func resourceArmStorageAccount() *schema.Resource { Type: schema.TypeList, MaxItems: 1, Optional: true, - Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "bypass": { @@ -163,11 +162,6 @@ func resourceArmStorageAccount() *schema.Resource { }, Set: schema.HashString, }, - "default_access_enabled": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - }, "ip_rules": { Type: schema.TypeSet, Optional: true, @@ -634,8 +628,9 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } } - if networkRules := props.NetworkRuleSet; networkRules != nil { - if err := d.Set("network_rules", flattenStorageAccountNetworkRules(networkRules)); err != nil { + networkRules := props.NetworkRuleSet + if networkRules != nil && len(*networkRules.IPRules) > 0 && len(*networkRules.VirtualNetworkRules) > 0 { + if err := d.Set("network_rules", flattenStorageAccountNetworkRules(d, networkRules)); err != nil { return fmt.Errorf("Error flattening `network_rules`: %+v", err) } } @@ -697,7 +692,8 @@ func flattenStorageAccountCustomDomain(input *storage.CustomDomain) []interface{ func expandStorageAccountNetworkRules(d *schema.ResourceData) *storage.NetworkRuleSet { networkRules := d.Get("network_rules").([]interface{}) if networkRules == nil || len(networkRules) == 0 { - return nil + // Default access is enabled when no network rules are set. + return &storage.NetworkRuleSet{DefaultAction: storage.DefaultActionAllow} } networkRule := networkRules[0].(map[string]interface{}) @@ -706,13 +702,8 @@ func expandStorageAccountNetworkRules(d *schema.ResourceData) *storage.NetworkRu networkRuleSet.IPRules = expandStorageAccountIPRules(networkRule) networkRuleSet.VirtualNetworkRules = expandStorageAccountVirtualNetworks(networkRule) networkRuleSet.Bypass = expandStorageAccountBypass(networkRule) - if val, ok := networkRule["default_access_enabled"]; ok { - if val.(bool) { - networkRuleSet.DefaultAction = storage.DefaultActionAllow - } else { - networkRuleSet.DefaultAction = storage.DefaultActionDeny - } - } + // Default Access is disabled when network rules are set. + networkRuleSet.DefaultAction = storage.DefaultActionDeny return networkRuleSet } @@ -760,15 +751,13 @@ func expandStorageAccountBypass(networkRule map[string]interface{}) storage.Bypa return storage.Bypass(strings.Join(bypassValues, ", ")) } -func flattenStorageAccountNetworkRules(input *storage.NetworkRuleSet) []interface{} { +func flattenStorageAccountNetworkRules(d *schema.ResourceData, input *storage.NetworkRuleSet) []interface{} { networkRules := make(map[string]interface{}, 0) networkRules["ip_rules"] = schema.NewSet(schema.HashString, flattenStorageAccountIPRules(input.IPRules)) networkRules["virtual_network_subnet_ids"] = schema.NewSet(schema.HashString, flattenStorageAccountVirtualNetworks(input.VirtualNetworkRules)) - if input.DefaultAction != "" { - networkRules["default_access_enabled"] = (input.DefaultAction == storage.DefaultActionAllow) - } networkRules["bypass"] = schema.NewSet(schema.HashString, flattenStorageAccountBypass(input.Bypass)) + return []interface{}{networkRules} } diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index 248365e4f739..426fe67f93c0 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -364,7 +364,6 @@ func TestAccAzureRMStorageAccount_networkRules(t *testing.T) { testCheckAzureRMStorageAccountExists(resourceName), resource.TestCheckResourceAttr(resourceName, "network_rules.0.ip_rules.#", "1"), resource.TestCheckResourceAttr(resourceName, "network_rules.0.virtual_network_subnet_ids.#", "1"), - resource.TestCheckResourceAttr(resourceName, "network_rules.0.default_access_enabled", "false"), ), }, { @@ -373,7 +372,6 @@ func TestAccAzureRMStorageAccount_networkRules(t *testing.T) { testCheckAzureRMStorageAccountExists(resourceName), resource.TestCheckResourceAttr(resourceName, "network_rules.0.ip_rules.#", "2"), resource.TestCheckResourceAttr(resourceName, "network_rules.0.virtual_network_subnet_ids.#", "0"), - resource.TestCheckResourceAttr(resourceName, "network_rules.0.default_access_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "network_rules.0.bypass.#", "2"), ), }, @@ -381,6 +379,38 @@ func TestAccAzureRMStorageAccount_networkRules(t *testing.T) { }) } +func TestAccAzureRMStorageAccount_networkRulesDeleted(t *testing.T) { + resourceName := "azurerm_storage_account.testsa" + ri := acctest.RandInt() + rs := acctest.RandString(4) + location := testLocation() + preConfig := testAccAzureRMStorageAccount_networkRules(ri, rs, location) + postConfig := testAccAzureRMStorageAccount_basic(ri, rs, location) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.ip_rules.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_rules.0.virtual_network_subnet_ids.#", "1"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_rules.#", "0"), + ), + }, + }, + }) +} + func testCheckAzureRMStorageAccountExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API @@ -850,7 +880,6 @@ resource "azurerm_storage_account" "testsa" { network_rules { ip_rules = ["127.0.0.1", "127.0.0.2"] bypass = ["Logging", "Metrics"] - default_access_enabled = true } tags { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index ee01fec15290..d04552f55bbd 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -129,8 +129,6 @@ The following arguments are supported: * `bypass` - (Optional) Specifies whether traffic is bypassed for Logging/Metrics/AzureServices. Valid options are any combination of `Logging`, `Metrics`, `AzureServices`, or `None`. -* `default_access_enabled` - (Optional) Boolean flag to specify the default action of allow or deny when no other rules -match. * `ip_rules` - (Optional) List of IP or IP ranges in CIDR Format. Only IPV4 addresses are allowed. * `virtual_network_subnet_ids` - (Optional) A list of resource ids for subnets. From 69c146daf12c1aa66cd7ecc2fca5c0e1a6b2dfb2 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 4 Jun 2018 13:31:39 -0600 Subject: [PATCH 5/5] Removing extra code --- azurerm/resource_arm_storage_account.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 73e208ca48a1..7efa5e747aaf 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -630,7 +630,7 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err networkRules := props.NetworkRuleSet if networkRules != nil && len(*networkRules.IPRules) > 0 && len(*networkRules.VirtualNetworkRules) > 0 { - if err := d.Set("network_rules", flattenStorageAccountNetworkRules(d, networkRules)); err != nil { + if err := d.Set("network_rules", flattenStorageAccountNetworkRules(networkRules)); err != nil { return fmt.Errorf("Error flattening `network_rules`: %+v", err) } } @@ -751,7 +751,7 @@ func expandStorageAccountBypass(networkRule map[string]interface{}) storage.Bypa return storage.Bypass(strings.Join(bypassValues, ", ")) } -func flattenStorageAccountNetworkRules(d *schema.ResourceData, input *storage.NetworkRuleSet) []interface{} { +func flattenStorageAccountNetworkRules(input *storage.NetworkRuleSet) []interface{} { networkRules := make(map[string]interface{}, 0) networkRules["ip_rules"] = schema.NewSet(schema.HashString, flattenStorageAccountIPRules(input.IPRules))