Hi Manu,
The trick is to run Terraform with two provider blocks—one pointing at the AKS subscription (where the principal lives) and a second, aliased provider that points at the storage-account subscription (where the scope lives).
- Declare the default provider for the AKS subscription, then add
provider "azurerm" { alias = "storage" subscription_id = var.storage_subscription_id … }
. - Read the identities you need (
data "azurerm_kubernetes_cluster" "aks"
to grabkubelet_identity[0].object_id
for a managed-identity cluster). - Look up the storage account through the storage provider (
data "azurerm_storage_account" "sa" { … provider = azurerm.storage }
). - Create the cross-subscription role assignment with that same provider alias so the request lands in the storage subscription:
resource "azurerm_role_assignment" "aks_blob_reader" { scope = data.azurerm_storage_account.sa.id # /subscriptions/<B>/resourceGroups/…/storageAccounts/… role_definition_name = "Storage Blob Data Reader" principal_id = data.azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id provider = azurerm.storage # <— executes against sub-B }
Terraform just needs whoever is running it to hold User Access Administrator or Owner on the storage subscription; the principal ID can come from any other subscription in the same tenant without extra setup. Behind the scenes this does the same thing you’d get in the CLI—az role assignment create --assignee <aks-object-id> --role "Storage Blob Data Reader" --scope /subscriptions/<sub-B>/…—only expressed as code so it lives in state and can be destroyed later.
- terraform apply, and AKS now has read access to blobs even though the account sits in a different subscription. (Cross-subscription role assignments are valid as long as both subscriptions share the same Microsoft Entra tenant.)
Best Regards,
Jerald Felix