From dd804ae945519f6601db82daa7e598726cd8a997 Mon Sep 17 00:00:00 2001 From: kbakker-hanab Date: Mon, 11 May 2026 16:33:12 +0200 Subject: [PATCH 1/5] Change subscription_required type from string to bool --- modules/azure/api_management_api/variables.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/azure/api_management_api/variables.tf b/modules/azure/api_management_api/variables.tf index f8aaa5bc..2b5cd5ab 100644 --- a/modules/azure/api_management_api/variables.tf +++ b/modules/azure/api_management_api/variables.tf @@ -15,7 +15,7 @@ variable "api_settings" { service_url = string, revision = string, basepath = string, - subscription_required = string, + subscription_required = bool, openapi_file_path = optional(string), wsdl_file_path = optional(string) }) @@ -227,4 +227,4 @@ variable "role_assignments" { type = list(string) description = "Roles to validate in the JWT token's 'roles' claim for access control." default = [] -} \ No newline at end of file +} From ef724e45ef3b7e2b4b4d9f540c150660ddc18f5b Mon Sep 17 00:00:00 2001 From: Kelly Faessen Date: Mon, 18 May 2026 11:47:33 +0200 Subject: [PATCH 2/5] refactor: remove unused categories/metrics from loganalytics_diagnostic_setting The diagnostic settings fix (#454/#455) replaced dynamic per-category filtering with static category_group = "allLogs" / category = "AllMetrics". The categories and metrics attributes on loganalytics_diagnostic_setting are no longer read in any module, so they are removed. Affected: event_grid_topic, event_hub, log_analytics_workspace, network_security_group, public_ip, service_plan, storage_account_public (blob/queue/table/file), stream_analytics, virtual_network. Breaking for external callers still passing categories/metrics. --- modules/azure/event_grid_topic/variables.tf | 4 +--- modules/azure/event_hub/variables.tf | 6 ++---- .../azure/log_analytics_workspace/variables.tf | 4 +--- .../azure/network_security_group/variables.tf | 4 +--- modules/azure/public_ip/variables.tf | 4 +--- modules/azure/service_plan/variables.tf | 4 +--- .../azure/storage_account_public/variables.tf | 16 ++++------------ modules/azure/stream_analytics/variables.tf | 4 +--- modules/azure/virtual_network/variables.tf | 4 +--- 9 files changed, 13 insertions(+), 37 deletions(-) diff --git a/modules/azure/event_grid_topic/variables.tf b/modules/azure/event_grid_topic/variables.tf index 33728556..9f2eedd6 100644 --- a/modules/azure/event_grid_topic/variables.tf +++ b/modules/azure/event_grid_topic/variables.tf @@ -25,9 +25,7 @@ variable "source_arm_resource_id" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics + workspace_id = string, // log analytics workspace ID }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/event_hub/variables.tf b/modules/azure/event_hub/variables.tf index 6519b5a8..8a529fb8 100644 --- a/modules/azure/event_hub/variables.tf +++ b/modules/azure/event_hub/variables.tf @@ -50,10 +50,8 @@ variable "consumer_group_name" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics - destination_type = optional(string), // AzureDiagnostics or Dedicated + workspace_id = string, // log analytics workspace ID + destination_type = optional(string), // AzureDiagnostics or Dedicated }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/log_analytics_workspace/variables.tf b/modules/azure/log_analytics_workspace/variables.tf index 73680064..1899f55e 100644 --- a/modules/azure/log_analytics_workspace/variables.tf +++ b/modules/azure/log_analytics_workspace/variables.tf @@ -33,9 +33,7 @@ variable "daily_quota_gb" { variable "loganalytics_diagnostic_setting" { type = object({ - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics - destination_type = optional(string), // AzureDiagnostics or Dedicated + destination_type = optional(string) // AzureDiagnostics or Dedicated }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/network_security_group/variables.tf b/modules/azure/network_security_group/variables.tf index 1c7f1cd9..cba1cc76 100644 --- a/modules/azure/network_security_group/variables.tf +++ b/modules/azure/network_security_group/variables.tf @@ -41,9 +41,7 @@ variable "subnet_ids" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics + workspace_id = string, // log analytics workspace ID }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/public_ip/variables.tf b/modules/azure/public_ip/variables.tf index 0f12f620..70a05ba2 100644 --- a/modules/azure/public_ip/variables.tf +++ b/modules/azure/public_ip/variables.tf @@ -33,9 +33,7 @@ variable "domain_name_label" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics + workspace_id = string, // log analytics workspace ID }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/service_plan/variables.tf b/modules/azure/service_plan/variables.tf index 98dfa568..6404976b 100644 --- a/modules/azure/service_plan/variables.tf +++ b/modules/azure/service_plan/variables.tf @@ -69,9 +69,7 @@ variable "scaling_rules" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics + workspace_id = string, // log analytics workspace ID }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/storage_account_public/variables.tf b/modules/azure/storage_account_public/variables.tf index ca423a35..fb56939d 100644 --- a/modules/azure/storage_account_public/variables.tf +++ b/modules/azure/storage_account_public/variables.tf @@ -120,24 +120,16 @@ variable "loganalytics_diagnostic_setting" { type = object({ workspace_id = string, // log analytics workspace ID blob = optional(object({ - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics - destination_type = optional(string), // AzureDiagnostics or Dedicated + destination_type = optional(string) // AzureDiagnostics or Dedicated })), queue = optional(object({ - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics - destination_type = optional(string), // AzureDiagnostics or Dedicated + destination_type = optional(string) // AzureDiagnostics or Dedicated })), table = optional(object({ - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics - destination_type = optional(string), // AzureDiagnostics or Dedicated + destination_type = optional(string) // AzureDiagnostics or Dedicated })) file = optional(object({ - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics - destination_type = optional(string), // AzureDiagnostics or Dedicated + destination_type = optional(string) // AzureDiagnostics or Dedicated })) }) description = "Specifies the log categories that have to be sent to Log analytics." diff --git a/modules/azure/stream_analytics/variables.tf b/modules/azure/stream_analytics/variables.tf index 58d444c3..4aa34276 100644 --- a/modules/azure/stream_analytics/variables.tf +++ b/modules/azure/stream_analytics/variables.tf @@ -97,9 +97,7 @@ variable "stream_query" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics + workspace_id = string, // log analytics workspace ID }) description = "Specifies the log categories that have to be sent to Log analytics." default = null diff --git a/modules/azure/virtual_network/variables.tf b/modules/azure/virtual_network/variables.tf index f2790cfb..a1b591fd 100644 --- a/modules/azure/virtual_network/variables.tf +++ b/modules/azure/virtual_network/variables.tf @@ -20,9 +20,7 @@ variable "address_space" { variable "loganalytics_diagnostic_setting" { type = object({ - workspace_id = string, // log analytics workspace ID - categories = optional(list(string)), // null list,means send all categories - metrics = optional(list(string)), // null list means send all metrics + workspace_id = string, // log analytics workspace ID }) description = "Specifies the log categories that have to be sent to Log analytics." default = null From b89b57e5299f29e6e970a43f12235b74b6bbfe29 Mon Sep 17 00:00:00 2001 From: Kelly Faessen Date: Mon, 18 May 2026 11:51:09 +0200 Subject: [PATCH 3/5] refactor: remove unused log_analytics_diagnostic_categories from logic_app_standard Same cleanup as the loganalytics_diagnostic_setting change: the diagnostic settings now use a static category_group = "allLogs", so this override variable is no longer read anywhere and is removed. Breaking for external callers still passing log_analytics_diagnostic_categories. --- modules/azure/logic_app_standard/variables.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/azure/logic_app_standard/variables.tf b/modules/azure/logic_app_standard/variables.tf index 1e26ccab..9e1a755d 100644 --- a/modules/azure/logic_app_standard/variables.tf +++ b/modules/azure/logic_app_standard/variables.tf @@ -105,12 +105,6 @@ variable "log_analytics_workspace_id" { default = null } -variable "log_analytics_diagnostic_categories" { - type = list(string) - description = "Optional list of diagnostic categories to override the default categories." - default = [] -} - variable "managed_identity_provider" { type = object({ existing = optional(object({ From 213d8bbfac2c82f3a5de1345a914e5bffcc5acc3 Mon Sep 17 00:00:00 2001 From: Kelly Faessen Date: Mon, 15 Jun 2026 11:55:57 +0200 Subject: [PATCH 4/5] 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 5/5] 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 +}