diff --git a/internal/services/netapp/netapp_volume_data_source.go b/internal/services/netapp/netapp_volume_data_source.go index 6c070b6ac794..49b7d826c0c5 100644 --- a/internal/services/netapp/netapp_volume_data_source.go +++ b/internal/services/netapp/netapp_volume_data_source.go @@ -5,6 +5,7 @@ package netapp import ( "fmt" + "strings" "time" "github.com/hashicorp/go-azure-helpers/lang/pointer" @@ -129,6 +130,16 @@ func dataSourceNetAppVolume() *pluginsdk.Resource { Type: pluginsdk.TypeString, Computed: true, }, + + "smb_non_browsable_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "smb_access_based_enumeration_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, }, } } @@ -174,6 +185,18 @@ func dataSourceNetAppVolumeRead(d *pluginsdk.ResourceData, meta interface{}) err d.Set("encryption_key_source", string(pointer.From(props.EncryptionKeySource))) d.Set("key_vault_private_endpoint_id", props.KeyVaultPrivateEndpointResourceId) + smbNonBrowsable := false + if props.SmbNonBrowsable != nil { + smbNonBrowsable = strings.EqualFold(string(*props.SmbNonBrowsable), string(volumes.SmbNonBrowsableEnabled)) + } + d.Set("smb_non_browsable_enabled", smbNonBrowsable) + + smbAccessBasedEnumeration := false + if props.SmbAccessBasedEnumeration != nil { + smbAccessBasedEnumeration = strings.EqualFold(string(*props.SmbAccessBasedEnumeration), string(volumes.SmbAccessBasedEnumerationEnabled)) + } + d.Set("smb_access_based_enumeration_enabled", smbAccessBasedEnumeration) + protocolTypes := make([]string, 0) if prtclTypes := props.ProtocolTypes; prtclTypes != nil { protocolTypes = append(protocolTypes, *prtclTypes...) diff --git a/internal/services/netapp/netapp_volume_resource.go b/internal/services/netapp/netapp_volume_resource.go index f31c9b9cbd23..7dfe48d51d74 100644 --- a/internal/services/netapp/netapp_volume_resource.go +++ b/internal/services/netapp/netapp_volume_resource.go @@ -301,6 +301,18 @@ func resourceNetAppVolume() *pluginsdk.Resource { ValidateFunc: azure.ValidateResourceID, RequiredWith: []string{"encryption_key_source"}, }, + + "smb_non_browsable_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "smb_access_based_enumeration_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -344,6 +356,16 @@ func resourceNetAppVolumeCreate(d *pluginsdk.ResourceData, meta interface{}) err } networkFeatures = volumes.NetworkFeatures(networkFeaturesString) + smbNonBrowsable := volumes.SmbNonBrowsableDisabled + if d.Get("smb_non_browsable_enabled").(bool) { + smbNonBrowsable = volumes.SmbNonBrowsableEnabled + } + + smbAccessBasedEnumeration := volumes.SmbAccessBasedEnumerationDisabled + if d.Get("smb_access_based_enumeration_enabled").(bool) { + smbAccessBasedEnumeration = volumes.SmbAccessBasedEnumerationEnabled + } + protocols := d.Get("protocols").(*pluginsdk.Set).List() if len(protocols) == 0 { protocols = append(protocols, "NFSv3") @@ -455,16 +477,18 @@ func resourceNetAppVolumeCreate(d *pluginsdk.ResourceData, meta interface{}) err parameters := volumes.Volume{ Location: location, Properties: volumes.VolumeProperties{ - CreationToken: volumePath, - ServiceLevel: &serviceLevel, - SubnetId: subnetID, - NetworkFeatures: &networkFeatures, - ProtocolTypes: utils.ExpandStringSlice(protocols), - SecurityStyle: &securityStyle, - UsageThreshold: storageQuotaInGB, - ExportPolicy: exportPolicyRule, - VolumeType: utils.String(volumeType), - SnapshotId: utils.String(snapshotID), + CreationToken: volumePath, + ServiceLevel: &serviceLevel, + SubnetId: subnetID, + NetworkFeatures: &networkFeatures, + SmbNonBrowsable: &smbNonBrowsable, + SmbAccessBasedEnumeration: &smbAccessBasedEnumeration, + ProtocolTypes: utils.ExpandStringSlice(protocols), + SecurityStyle: &securityStyle, + UsageThreshold: storageQuotaInGB, + ExportPolicy: exportPolicyRule, + VolumeType: utils.String(volumeType), + SnapshotId: utils.String(snapshotID), DataProtection: &volumes.VolumePropertiesDataProtection{ Replication: dataProtectionReplication.Replication, Snapshot: dataProtectionSnapshotPolicy.Snapshot, @@ -582,6 +606,26 @@ func resourceNetAppVolumeUpdate(d *pluginsdk.ResourceData, meta interface{}) err update.Properties.ThroughputMibps = utils.Float(throughputMibps.(float64)) } + if d.HasChange("smb_non_browsable_enabled") { + shouldUpdate = true + smbNonBrowsable := volumes.SmbNonBrowsableDisabled + update.Properties.SmbNonBrowsable = &smbNonBrowsable + if d.Get("smb_non_browsable_enabled").(bool) { + smbNonBrowsable := volumes.SmbNonBrowsableEnabled + update.Properties.SmbNonBrowsable = &smbNonBrowsable + } + } + + if d.HasChange("smb_access_based_enumeration_enabled") { + shouldUpdate = true + smbAccessBasedEnumeration := volumes.SmbAccessBasedEnumerationDisabled + update.Properties.SmbAccessBasedEnumeration = &smbAccessBasedEnumeration + if d.Get("smb_access_based_enumeration_enabled").(bool) { + smbAccessBasedEnumeration := volumes.SmbAccessBasedEnumerationEnabled + update.Properties.SmbAccessBasedEnumeration = &smbAccessBasedEnumeration + } + } + if d.HasChange("tags") { shouldUpdate = true tagsRaw := d.Get("tags").(map[string]interface{}) @@ -651,6 +695,18 @@ func resourceNetAppVolumeRead(d *pluginsdk.ResourceData, meta interface{}) error d.Set("encryption_key_source", string(pointer.From(props.EncryptionKeySource))) d.Set("key_vault_private_endpoint_id", props.KeyVaultPrivateEndpointResourceId) + smbNonBrowsable := false + if props.SmbNonBrowsable != nil { + smbNonBrowsable = strings.EqualFold(string(*props.SmbNonBrowsable), string(volumes.SmbNonBrowsableEnabled)) + } + d.Set("smb_non_browsable_enabled", smbNonBrowsable) + + smbAccessBasedEnumeration := false + if props.SmbAccessBasedEnumeration != nil { + smbAccessBasedEnumeration = strings.EqualFold(string(*props.SmbAccessBasedEnumeration), string(volumes.SmbAccessBasedEnumerationEnabled)) + } + d.Set("smb_access_based_enumeration_enabled", smbAccessBasedEnumeration) + avsDataStore := false if props.AvsDataStore != nil { avsDataStore = strings.EqualFold(string(*props.AvsDataStore), string(volumes.AvsDataStoreEnabled)) diff --git a/website/docs/d/netapp_volume.html.markdown b/website/docs/d/netapp_volume.html.markdown index b19af556d80f..7feb86e4b7d0 100644 --- a/website/docs/d/netapp_volume.html.markdown +++ b/website/docs/d/netapp_volume.html.markdown @@ -63,6 +63,9 @@ The following attributes are exported: * `volume_path` - The unique file path of the volume. +* `smb_non_browsable_enabled` - Limits clients from browsing for an SMB share. + +* `smb_access_based_enumeration_enabled` - Limits enumeration of files and folders (that is, listing the contents) in SMB only to users with allowed access on the share. --- A `data_protection_replication` block exports the following: diff --git a/website/docs/r/netapp_volume.html.markdown b/website/docs/r/netapp_volume.html.markdown index 1f2c166fa335..b882e68d1c4d 100644 --- a/website/docs/r/netapp_volume.html.markdown +++ b/website/docs/r/netapp_volume.html.markdown @@ -147,6 +147,10 @@ The following arguments are supported: * `key_vault_private_endpoint_id` - (Optional) The Private Endpoint ID for Key Vault, which is required when using customer-managed keys. This is required with `encryption_key_source`. +* `smb_non_browsable_enabled` - (Optional) Limits clients from browsing for an SMB share by hiding the share from view in Windows Explorer or when listing shares in "net view." Only end users that know the absolute paths to the share are able to find the share. Defaults to `false`. For more information, please refer to [Understand NAS share permissions in Azure NetApp Files](https://learn.microsoft.com/en-us/azure/azure-netapp-files/network-attached-storage-permissions#:~:text=Non%2Dbrowsable%20shares,find%20the%20share.) + +* `smb_access_based_enumeration_enabled` - (Optional) Limits enumeration of files and folders (that is, listing the contents) in SMB only to users with allowed access on the share. For instance, if a user doesn't have access to read a file or folder in a share with access-based enumeration enabled, then the file or folder doesn't show up in directory listings. Defaults to `false`. For more information, please refer to [Understand NAS share permissions in Azure NetApp Files](https://learn.microsoft.com/en-us/azure/azure-netapp-files/network-attached-storage-permissions#:~:text=security%20for%20administrators.-,Access%2Dbased%20enumeration,in%20an%20Azure%20NetApp%20Files%20SMB%20volume.%20Only%20contosoadmin%20has%20access.,-In%20the%20below) + * `tags` - (Optional) A mapping of tags to assign to the resource. -> **Note:** It is highly recommended to use the **lifecycle** property as noted in the example since it will prevent an accidental deletion of the volume if the `protocols` argument changes to a different protocol type.