Azure / terraform-azurerm-avm-res-storage-storageaccount

This Terraform module is designed to create Azure Storage Accounts and its related resources, including blob containers, queues, tables, and file shares. It also supports the creation of a storage account private endpoint which provides secure and direct connectivity to Azure Storage over a private network.
https://registry.terraform.io/modules/Azure/avm-res-storage-storageaccount
MIT License
19 stars 27 forks source link

Add support for deploying azurerm_storage_share_directory #132

Closed CloudPlumber closed 1 month ago

CloudPlumber commented 1 month ago

Is there an existing issue for this?

Description

It would be great if you could add the possibility to deploy share directories with this module also in order to avoid having to grant data plane permissions, when needed.

New or Affected Resource(s)/Data Source(s)

azurerm_storage_share_directory

Potential Terraform Configuration

resource "azurerm_storage_share_directory" "this" {
  name             = "directoryname"
  storage_share_id = azurerm_storage_share.sharename.id
}

It says the following: When using Azure Active Directory Authentication (i.e. setting the provider property storage_use_azuread = true), the principal running Terraform must have the Storage File Data Privileged Contributor IAM role assigned. The Storage File Data SMB Share Contributor does not have sufficient permissions to create directories. Refer to official documentation for more details.

I can't find that function in the docs: https://learn.microsoft.com/en-us/azure/templates/microsoft.storage/storageaccounts/fileservices/shares?pivots=deployment-language-terraform as it stops with the shares themselves and doesn't cover the directories underneath.

References

No response

chinthakaru commented 1 month ago

@CloudPlumber Thank you for your inquiry. This module utilizes AzApi to create Share directories. Could you please provide a more detailed explanation of the request?

CloudPlumber commented 1 month ago

Sure I'm currently working on switching the Palo Alto Network Cloud Firewall to be deployed with AVMs. There is a section called bootstrap, where some storage operations need to be done. So I need a share and within that share I need some nested directories. Currently I use this code as I couldn't find the functionality within the module:

module "bootstrap" { source = "Azure/avm-res-storage-storageaccount/azurerm" version = "0.2.1" resource_group_name = var.resource_group_name location = var.resource_location enable_telemetry = var.enable_telemetry name = "fictivestoragename" account_tier = "Standard" account_replication_type = "LRS"

enable_https_traffic_only = true min_tls_version = "TLS1_2" shared_access_key_enabled = true public_network_access_enabled = true network_rules = { bypass = ["AzureServices"] default_action = "Allow" ip_rules = var.bootstrap_network_whitelist_ips } managed_identities = { system_assigned = true user_assigned_resource_ids = [data.terraform_remote_state.lz_connectivity_sbsc.outputs.uai_id] } role_assignments = { role_assignment_1 = { role_definition_id_or_name = "Storage File Data Privileged Contributor" principal_type = "Group" principal_id = "%principal-id" skip_service_principal_aad_check = false } } shares = { share1 = { name = "bootstrap" quota = 2 access_tier = "Hot" } } }

resource "azurerm_storage_share_directory" "firewalls" { for_each = var.firewalls name = each.key storage_share_id = "https://${module.bootstrap.name}.file.core.windows.net/${module.bootstrap.shares["share1"].name}" }

resource "azurerm_storage_share_directory" "plugins" { for_each = var.firewalls name = "${each.key}/plugins" storage_share_id = "https://${module.bootstrap.name}.file.core.windows.net/${module.bootstrap.shares["share1"].name}"

provisioner "local-exec" { command = "az storage file upload-batch --account-name ${module.bootstrap.name} --account-key ${module.bootstrap.resource.primary_access_key} --destination ${module.bootstrap.shares["share1"].name}/${each.key}/plugins --source bootstrap_files/plugins" }

provisioner "local-exec" { when = destroy command = "az storage file delete-batch --account-name ${self.storage_account_name} --source bootstrap/${each.key}/plugins" on_failure = continue }

depends_on = [ azurerm_storage_share_directory.firewalls, ]

}

resource "azurerm_storage_share_directory" "software" { for_each = var.firewalls name = "${each.key}/software" storage_share_id = "https://${module.bootstrap.name}.file.core.windows.net/${module.bootstrap.shares["share1"].name}"

provisioner "local-exec" { command = "az storage file upload-batch --account-name ${module.bootstrap.name} --account-key ${module.bootstrap.resource.primary_access_key} --destination ${module.bootstrap.shares["share1"].name}/${each.key}/software --source bootstrap_files/software" }

provisioner "local-exec" { when = destroy command = "az storage file delete-batch --account-name ${self.storage_account_name} --source bootstrap/${each.key}/software" on_failure = continue } depends_on = [ azurerm_storage_share_directory.firewalls, ]

}

resource "azurerm_storage_share_directory" "license" { for_each = var.firewalls name = "${each.key}/license" storage_share_id = "https://${module.bootstrap.name}.file.core.windows.net/${module.bootstrap.shares["share1"].name}"


The module produces shares but no further directories within when I read that correctly or am I looking in the wrong location?

resource "azapi_resource" "share" { for_each = var.shares

type = "Microsoft.Storage/storageAccounts/fileServices/shares@2023-01-01" body = { properties = { metadata = each.value.metadata access_tier = each.value.access_tier enabledProtocols = each.value.enabled_protocol shareQuota = each.value.quota rootSquash = each.value.root_squash signedIdentifiers = each.value.signed_identifiers == null ? [] : each.value.signed_identifiers

}

} name = each.value.name parent_id = "${azurerm_storage_account.this.id}/fileServices/default" schema_validation_enabled = false

dynamic "timeouts" { for_each = each.value.timeouts == null ? [] : [each.value.timeouts] content { create = timeouts.value.create delete = timeouts.value.delete read = timeouts.value.read } } }

chinthakaru commented 1 month ago

@CloudPlumber Thank you for the suggestion. However, nested directories are more related to data plane operations rather than control plane actions. At this stage, we do not have any plans to support data plane operations within the module.

CloudPlumber commented 2 weeks ago

@chinthakaru: Alright understandable. Thanks for looking into that. So I'll stick to what I have and keep in mind that the data plane is out of scope.