Skip to content

Commit

Permalink
Support for private_link_access in azurerm_storage_account (#11629)
Browse files Browse the repository at this point in the history
Fix #11628

=== RUN TestAccStorageAccount_resourceAccessRules
=== PAUSE TestAccStorageAccount_resourceAccessRules
=== CONT TestAccStorageAccount_resourceAccessRules
--- PASS: TestAccStorageAccount_resourceAccessRules (465.11s)

=== RUN TestAccStorageAccountNetworkRules_resourceAccessRules
=== PAUSE TestAccStorageAccountNetworkRules_resourceAccessRules
=== CONT TestAccStorageAccountNetworkRules_resourceAccessRules
--- PASS: TestAccStorageAccountNetworkRules_resourceAccessRules (381.65s)
  • Loading branch information
yupwei68 authored May 12, 2021
1 parent d64c84b commit 8e2dbce
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
"strings"
"time"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"

"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-01-01/storage"
"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/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks"
networkValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)
Expand Down Expand Up @@ -93,11 +93,33 @@ func resourceStorageAccountNetworkRules() *schema.Resource {
string(storage.DefaultActionDeny),
}, false),
},

"private_link_access": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"endpoint_resource_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: networkValidate.PrivateEndpointID,
},

"endpoint_tenant_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.IsUUID,
},
},
},
},
},
}
}

func resourceStorageAccountNetworkRulesCreateUpdate(d *schema.ResourceData, meta interface{}) error {
tenantId := meta.(*clients.Client).Account.TenantId
client := meta.(*clients.Client).Storage.AccountsClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()
Expand Down Expand Up @@ -136,6 +158,7 @@ func resourceStorageAccountNetworkRulesCreateUpdate(d *schema.ResourceData, meta
rules.Bypass = expandStorageAccountNetworkRuleBypass(d.Get("bypass").(*schema.Set).List())
rules.IPRules = expandStorageAccountNetworkRuleIpRules(d.Get("ip_rules").(*schema.Set).List())
rules.VirtualNetworkRules = expandStorageAccountNetworkRuleVirtualRules(d.Get("virtual_network_subnet_ids").(*schema.Set).List())
rules.ResourceAccessRules = expandStorageAccountPrivateLinkAccess(d.Get("private_link_access").([]interface{}), tenantId)

opts := storage.AccountUpdateParameters{
AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{
Expand Down Expand Up @@ -184,6 +207,9 @@ func resourceStorageAccountNetworkRulesRead(d *schema.ResourceData, meta interfa
return fmt.Errorf("Error setting `bypass`: %+v", err)
}
d.Set("default_action", string(rules.DefaultAction))
if err := d.Set("private_link_access", flattenStorageAccountPrivateLinkAccess(rules.ResourceAccessRules)); err != nil {
return fmt.Errorf("setting `private_link_access`: %+v", err)
}
}

return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,35 @@ func TestAccStorageAccountNetworkRules_update(t *testing.T) {
})
}

func TestAccStorageAccountNetworkRules_privateLinkAccess(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_account_network_rules", "test")
r := StorageAccountNetworkRulesResource{}

data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.disablePrivateLinkAccess(data),
Check: resource.ComposeTestCheckFunc(
check.That("azurerm_storage_account.test").ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.privateLinkAccess(data),
Check: resource.ComposeTestCheckFunc(
check.That("azurerm_storage_account.test").ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.disablePrivateLinkAccess(data),
Check: resource.ComposeTestCheckFunc(
check.That("azurerm_storage_account.test").ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccStorageAccountNetworkRules_empty(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_account_network_rules", "test")
r := StorageAccountNetworkRulesResource{}
Expand Down Expand Up @@ -236,3 +265,64 @@ resource "azurerm_storage_account_network_rules" "test" {
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func (r StorageAccountNetworkRulesResource) disablePrivateLinkAccess(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_storage_account" "test" {
name = "unlikely23exst2acct%s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
tags = {
environment = "production"
}
}
resource "azurerm_storage_account_network_rules" "test" {
resource_group_name = azurerm_resource_group.test.name
storage_account_name = azurerm_storage_account.test.name
default_action = "Deny"
bypass = ["None"]
ip_rules = []
virtual_network_subnet_ids = []
}
`, StorageAccountResource{}.networkRulesPrivateEndpointTemplate(data), data.RandomString)
}

func (r StorageAccountNetworkRulesResource) privateLinkAccess(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_storage_account" "test" {
name = "unlikely23exst2acct%s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
tags = {
environment = "production"
}
}
resource "azurerm_storage_account_network_rules" "test" {
resource_group_name = azurerm_resource_group.test.name
storage_account_name = azurerm_storage_account.test.name
default_action = "Deny"
ip_rules = ["127.0.0.1"]
virtual_network_subnet_ids = [azurerm_subnet.test.id]
private_link_access {
endpoint_resource_id = azurerm_private_endpoint.blob.id
}
private_link_access {
endpoint_resource_id = azurerm_private_endpoint.table.id
}
}
`, StorageAccountResource{}.networkRulesPrivateEndpointTemplate(data), data.RandomString)
}
78 changes: 74 additions & 4 deletions azurerm/internal/services/storage/storage_account_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"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/network"
networkValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/migration"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
Expand Down Expand Up @@ -287,6 +288,27 @@ func resourceStorageAccount() *schema.Resource {
string(storage.DefaultActionDeny),
}, false),
},

"private_link_access": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"endpoint_resource_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: networkValidate.PrivateEndpointID,
},

"endpoint_tenant_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.IsUUID,
},
},
},
},
},
},
},
Expand Down Expand Up @@ -737,6 +759,7 @@ func resourceStorageAccount() *schema.Resource {

func resourceStorageAccountCreate(d *schema.ResourceData, meta interface{}) error {
envName := meta.(*clients.Client).Account.Environment.Name
tenantId := meta.(*clients.Client).Account.TenantId
client := meta.(*clients.Client).Storage.AccountsClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()
Expand Down Expand Up @@ -780,7 +803,7 @@ func resourceStorageAccountCreate(d *schema.ResourceData, meta interface{}) erro
Kind: storage.Kind(accountKind),
AccountPropertiesCreateParameters: &storage.AccountPropertiesCreateParameters{
EnableHTTPSTrafficOnly: &enableHTTPSTrafficOnly,
NetworkRuleSet: expandStorageAccountNetworkRules(d),
NetworkRuleSet: expandStorageAccountNetworkRules(d, tenantId),
IsHnsEnabled: &isHnsEnabled,
EnableNfsV3: &nfsV3Enabled,
},
Expand Down Expand Up @@ -964,6 +987,7 @@ func resourceStorageAccountCreate(d *schema.ResourceData, meta interface{}) erro

func resourceStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error {
envName := meta.(*clients.Client).Account.Environment.Name
tenantId := meta.(*clients.Client).Account.TenantId
client := meta.(*clients.Client).Storage.AccountsClient
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()
Expand Down Expand Up @@ -1126,12 +1150,12 @@ func resourceStorageAccountUpdate(d *schema.ResourceData, meta interface{}) erro
if d.HasChange("network_rules") {
opts := storage.AccountUpdateParameters{
AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{
NetworkRuleSet: expandStorageAccountNetworkRules(d),
NetworkRuleSet: expandStorageAccountNetworkRules(d, tenantId),
},
}

if _, err := client.Update(ctx, resourceGroupName, storageAccountName, opts); err != nil {
return fmt.Errorf("Error updating Azure Storage Account network_rules %q: %+v", storageAccountName, err)
return fmt.Errorf("updating Azure Storage Account network_rules %q: %+v", storageAccountName, err)
}
}

Expand Down Expand Up @@ -1646,7 +1670,7 @@ func expandArmStorageAccountRouting(input []interface{}) *storage.RoutingPrefere
}
}

func expandStorageAccountNetworkRules(d *schema.ResourceData) *storage.NetworkRuleSet {
func expandStorageAccountNetworkRules(d *schema.ResourceData, tenantId string) *storage.NetworkRuleSet {
networkRules := d.Get("network_rules").([]interface{})
if len(networkRules) == 0 {
// Default access is enabled when no network rules are set.
Expand All @@ -1658,6 +1682,7 @@ func expandStorageAccountNetworkRules(d *schema.ResourceData) *storage.NetworkRu
IPRules: expandStorageAccountIPRules(networkRule),
VirtualNetworkRules: expandStorageAccountVirtualNetworks(networkRule),
Bypass: expandStorageAccountBypass(networkRule),
ResourceAccessRules: expandStorageAccountPrivateLinkAccess(networkRule["private_link_access"].([]interface{}), tenantId),
}

if v := networkRule["default_action"]; v != nil {
Expand Down Expand Up @@ -1710,6 +1735,25 @@ func expandStorageAccountBypass(networkRule map[string]interface{}) storage.Bypa
return storage.Bypass(strings.Join(bypassValues, ", "))
}

func expandStorageAccountPrivateLinkAccess(inputs []interface{}, tenantId string) *[]storage.ResourceAccessRule {
privateLinkAccess := make([]storage.ResourceAccessRule, 0)
if len(inputs) == 0 {
return &privateLinkAccess
}
for _, input := range inputs {
accessRule := input.(map[string]interface{})
if v := accessRule["endpoint_tenant_id"].(string); v != "" {
tenantId = v
}
privateLinkAccess = append(privateLinkAccess, storage.ResourceAccessRule{
TenantID: utils.String(tenantId),
ResourceID: utils.String(accessRule["endpoint_resource_id"].(string)),
})
}

return &privateLinkAccess
}

func expandBlobProperties(input []interface{}) *storage.BlobServiceProperties {
props := storage.BlobServiceProperties{
BlobServicePropertiesProperties: &storage.BlobServicePropertiesProperties{
Expand Down Expand Up @@ -2036,6 +2080,7 @@ func flattenStorageAccountNetworkRules(input *storage.NetworkRuleSet) []interfac
networkRules["virtual_network_subnet_ids"] = schema.NewSet(schema.HashString, flattenStorageAccountVirtualNetworks(input.VirtualNetworkRules))
networkRules["bypass"] = schema.NewSet(schema.HashString, flattenStorageAccountBypass(input.Bypass))
networkRules["default_action"] = string(input.DefaultAction)
networkRules["private_link_access"] = flattenStorageAccountPrivateLinkAccess(input.ResourceAccessRules)

return []interface{}{networkRules}
}
Expand Down Expand Up @@ -2074,6 +2119,31 @@ func flattenStorageAccountVirtualNetworks(input *[]storage.VirtualNetworkRule) [
return virtualNetworks
}

func flattenStorageAccountPrivateLinkAccess(inputs *[]storage.ResourceAccessRule) []interface{} {
if inputs == nil || len(*inputs) == 0 {
return []interface{}{}
}

accessRules := make([]interface{}, 0)
for _, input := range *inputs {
var resourceId, tenantId string
if input.ResourceID != nil {
resourceId = *input.ResourceID
}

if input.TenantID != nil {
tenantId = *input.TenantID
}

accessRules = append(accessRules, map[string]interface{}{
"endpoint_resource_id": resourceId,
"endpoint_tenant_id": tenantId,
})
}

return accessRules
}

func flattenBlobProperties(input storage.BlobServiceProperties) []interface{} {
if input.BlobServicePropertiesProperties == nil {
return []interface{}{}
Expand Down
Loading

0 comments on commit 8e2dbce

Please sign in to comment.