From 213d8bbfac2c82f3a5de1345a914e5bffcc5acc3 Mon Sep 17 00:00:00 2001 From: Kelly Faessen Date: Mon, 15 Jun 2026 11:55:57 +0200 Subject: [PATCH 1/2] feat: support Entra ID-only storage (AB#7496) - storage_account_public: add shared_access_key_enabled variable (default true) - storage_blob: add storage_blob_url_without_sas output (identity-based run-from-package) - add storage_table_azapi module (manages tables via ARM control plane, no Shared Key) --- modules/azure/storage_account_public/main.tf | 1 + .../azure/storage_account_public/variables.tf | 6 +++++ modules/azure/storage_blob/outputs.tf | 7 ++++++ modules/azure/storage_table_azapi/main.tf | 25 +++++++++++++++++++ modules/azure/storage_table_azapi/outputs.tf | 7 ++++++ .../azure/storage_table_azapi/variables.tf | 9 +++++++ 6 files changed, 55 insertions(+) create mode 100644 modules/azure/storage_table_azapi/main.tf create mode 100644 modules/azure/storage_table_azapi/outputs.tf create mode 100644 modules/azure/storage_table_azapi/variables.tf diff --git a/modules/azure/storage_account_public/main.tf b/modules/azure/storage_account_public/main.tf index c785b1f3..d96575c9 100644 --- a/modules/azure/storage_account_public/main.tf +++ b/modules/azure/storage_account_public/main.tf @@ -28,6 +28,7 @@ resource "azurerm_storage_account" "storage_account" { nfsv3_enabled = var.nfsv3_enabled is_hns_enabled = var.is_hns_enabled sftp_enabled = var.sftp_enabled + shared_access_key_enabled = var.shared_access_key_enabled blob_properties { dynamic "cors_rule" { diff --git a/modules/azure/storage_account_public/variables.tf b/modules/azure/storage_account_public/variables.tf index ca423a35..2d93f1f7 100644 --- a/modules/azure/storage_account_public/variables.tf +++ b/modules/azure/storage_account_public/variables.tf @@ -149,3 +149,9 @@ variable "sftp_enabled" { default = false } +variable "shared_access_key_enabled" { + type = bool + description = "Whether the storage account permits requests to be authorized with the account access key (Shared Key). Set to false to enforce Entra ID (Azure AD) authorization only." + default = true +} + diff --git a/modules/azure/storage_blob/outputs.tf b/modules/azure/storage_blob/outputs.tf index 61393f31..77622f9e 100644 --- a/modules/azure/storage_blob/outputs.tf +++ b/modules/azure/storage_blob/outputs.tf @@ -2,3 +2,10 @@ output "storage_blob_url" { value = "https://${azurerm_storage_blob.storage_blob.storage_account_name}.blob.core.windows.net/${azurerm_storage_blob.storage_blob.storage_container_name}/${azurerm_storage_blob.storage_blob.name}${data.azurerm_storage_account_sas.sas_token.sas}" sensitive = true } + +# Plain blob URL without SAS. Use together with a managed identity that has +# (at least) Storage Blob Data Reader on the account, e.g. for identity-based +# WEBSITE_RUN_FROM_PACKAGE when shared key access is disabled on the account. +output "storage_blob_url_without_sas" { + value = "https://${azurerm_storage_blob.storage_blob.storage_account_name}.blob.core.windows.net/${azurerm_storage_blob.storage_blob.storage_container_name}/${azurerm_storage_blob.storage_blob.name}" +} diff --git a/modules/azure/storage_table_azapi/main.tf b/modules/azure/storage_table_azapi/main.tf new file mode 100644 index 00000000..68ae5fee --- /dev/null +++ b/modules/azure/storage_table_azapi/main.tf @@ -0,0 +1,25 @@ +terraform { + required_version = "~> 1.12" + + required_providers { + azapi = { + source = "Azure/azapi" + version = "~> 1.15" + } + } + + backend "azurerm" {} +} + +provider "azapi" {} + +# Entra ID (Azure AD) native equivalent of the azurerm_storage_table module. +# Manages the table via the ARM control plane (Microsoft.Storage), so it does +# NOT require Shared Key / data-plane access and keeps working when the storage +# account has shared_access_key_enabled = false. +resource "azapi_resource" "storage_table" { + type = "Microsoft.Storage/storageAccounts/tableServices/tables@2023-01-01" + name = var.storage_table_name + parent_id = "${var.storage_account_id}/tableServices/default" + body = jsonencode({}) +} diff --git a/modules/azure/storage_table_azapi/outputs.tf b/modules/azure/storage_table_azapi/outputs.tf new file mode 100644 index 00000000..ed6e221b --- /dev/null +++ b/modules/azure/storage_table_azapi/outputs.tf @@ -0,0 +1,7 @@ +output "name" { + value = azapi_resource.storage_table.name +} + +output "id" { + value = azapi_resource.storage_table.id +} diff --git a/modules/azure/storage_table_azapi/variables.tf b/modules/azure/storage_table_azapi/variables.tf new file mode 100644 index 00000000..c8e49a27 --- /dev/null +++ b/modules/azure/storage_table_azapi/variables.tf @@ -0,0 +1,9 @@ +variable "storage_account_id" { + type = string + description = "Resource ID of the storage account that hosts the table (e.g. azurerm_storage_account.x.id)." +} + +variable "storage_table_name" { + type = string + description = "Name of the storage table." +} From 05707ce4f185efeb3717eaf100fb701ea84d1812 Mon Sep 17 00:00:00 2001 From: Kelly Faessen Date: Mon, 15 Jun 2026 12:03:14 +0200 Subject: [PATCH 2/2] feat: add storage_use_azuread toggle to storage modules (AB#7496) Lets consumers switch blob/queue/container data-plane auth to Entra ID (provider storage_use_azuread) when shared key access is disabled. Default false. --- modules/azure/storage_account_public/main.tf | 4 ++++ modules/azure/storage_account_public/variables.tf | 6 ++++++ modules/azure/storage_blob/main.tf | 4 ++++ modules/azure/storage_blob/variables.tf | 6 ++++++ modules/azure/storage_container/main.tf | 4 ++++ modules/azure/storage_container/variables.tf | 6 ++++++ 6 files changed, 30 insertions(+) diff --git a/modules/azure/storage_account_public/main.tf b/modules/azure/storage_account_public/main.tf index d96575c9..1dcbf395 100644 --- a/modules/azure/storage_account_public/main.tf +++ b/modules/azure/storage_account_public/main.tf @@ -13,6 +13,10 @@ terraform { provider "azurerm" { features {} + + # Use Entra ID (Azure AD) for the Storage data plane instead of Shared Key. + # Required when the target storage account has shared_access_key_enabled = false. + storage_use_azuread = var.storage_use_azuread } resource "azurerm_storage_account" "storage_account" { diff --git a/modules/azure/storage_account_public/variables.tf b/modules/azure/storage_account_public/variables.tf index 2d93f1f7..82f91077 100644 --- a/modules/azure/storage_account_public/variables.tf +++ b/modules/azure/storage_account_public/variables.tf @@ -155,3 +155,9 @@ variable "shared_access_key_enabled" { default = true } +variable "storage_use_azuread" { + type = bool + description = "Authenticate Storage data-plane operations (blob/queue properties) with Entra ID (Azure AD) instead of the account access key. Set to true when shared key access is disabled on the account." + default = false +} + diff --git a/modules/azure/storage_blob/main.tf b/modules/azure/storage_blob/main.tf index 8d9d0d8b..7ab52162 100644 --- a/modules/azure/storage_blob/main.tf +++ b/modules/azure/storage_blob/main.tf @@ -13,6 +13,10 @@ terraform { provider "azurerm" { features {} + + # Use Entra ID (Azure AD) for the Storage data plane instead of Shared Key. + # Required when the target storage account has shared_access_key_enabled = false. + storage_use_azuread = var.storage_use_azuread } resource "azurerm_storage_blob" "storage_blob" { diff --git a/modules/azure/storage_blob/variables.tf b/modules/azure/storage_blob/variables.tf index 68eddf7f..3ee27940 100644 --- a/modules/azure/storage_blob/variables.tf +++ b/modules/azure/storage_blob/variables.tf @@ -30,3 +30,9 @@ variable "local_source" { default = null } +variable "storage_use_azuread" { + type = bool + description = "Authenticate Storage data-plane operations (blob upload/read) with Entra ID (Azure AD) instead of the account access key. Set to true when shared key access is disabled on the account." + default = false +} + diff --git a/modules/azure/storage_container/main.tf b/modules/azure/storage_container/main.tf index 7b16075f..f70cc687 100644 --- a/modules/azure/storage_container/main.tf +++ b/modules/azure/storage_container/main.tf @@ -13,6 +13,10 @@ terraform { provider "azurerm" { features {} + + # Use Entra ID (Azure AD) for the Storage data plane instead of Shared Key. + # Required when the target storage account has shared_access_key_enabled = false. + storage_use_azuread = var.storage_use_azuread } resource "azurerm_storage_container" "storage_container" { diff --git a/modules/azure/storage_container/variables.tf b/modules/azure/storage_container/variables.tf index d2ca6c5b..39f9c2f5 100644 --- a/modules/azure/storage_container/variables.tf +++ b/modules/azure/storage_container/variables.tf @@ -13,3 +13,9 @@ variable "storage_container_access_type" { description = "Access type of the storage account." default = "private" } + +variable "storage_use_azuread" { + type = bool + description = "Authenticate Storage data-plane operations (container create/read) with Entra ID (Azure AD) instead of the account access key. Set to true when shared key access is disabled on the account." + default = false +}