Azure Managed Application restricted customer access blocks UAMI listKeys despite Microsoft.Storage/storageAccounts/* in deny assignment notActions

Antonieta Pinto Rebelo 0 Reputation points
2026-06-30T11:53:00.76+00:00

Hi Microsoft team,

I am testing an Azure Marketplace Managed Application that deploys an Azure Machine Learning workspace, ACR, storage account, Key Vault, user-assigned managed identity, and AML compute cluster inside the managed resource group.

I am trying to restrict customer access using the Marketplace Managed Application Customer Access = Restricted option, while still allowing the customer to submit Azure ML training jobs.

Scenario

The Managed Application deploys:

  • Azure ML workspace

AML compute cluster

Azure Container Registry

Storage account

Key Vault

User-assigned managed identity attached to the AML compute

The UAMI has the following role assignments:

  • AcrPull on the ACR Image

Reader on the storage account

Storage Account Contributor on the storage account

Storage Blob Data Contributor on the storage account

Contributor on the Azure ML workspace

Reader on Key Vault

Key Vault Secrets User on Key Vault

Inside the Azure ML training container, I run Python code that uses the UAMI to call:

from azure.identity import ManagedIdentityCredential
from azure.mgmt.storage import StorageManagementClient

credential = ManagedIdentityCredential(client_id=UAMI_CLIENT_ID)

client = StorageManagementClient(
    credential,
    subscription_id=SUBSCRIPTION_ID,
)

keys = client.storage_accounts.list_keys(
    resource_group_name=RESOURCE_GROUP,
    account_name=STORAGE_ACCOUNT_NAME,
)

The purpose of this test is to confirm whether the UAMI can access the storage account keys and then write outputs/logs to Blob Storage.

Important finding

When I deploy the Managed Application with Customer Access = Full, the Azure ML training job works successfully. The job can write the output files and logs to the storage account.

However, when I deploy the same Managed Application with Customer Access = Restricted, the same training job fails on list_keys, even though the UAMI has Storage Account Contributor and the generated deny assignment appears to allow storage account actions.

Marketplace allowed actions configured

For testing, I made the allowed actions broad:

Allowed control actions:

Microsoft.MachineLearningServices/workspaces/*;Microsoft.Storage/storageAccounts/*

Allowed data actions:

Microsoft.Storage/storageAccounts/*

Actual deny assignment JSON

I checked the actual deny assignment created on the managed resource group using:

az rest \
  --method get \
  --url "https://management.azure.com${RG_ID}/providers/Microsoft.Authorization/denyAssignments?api-version=2022-04-01" \
  -o jsonc

The deny assignment contains:

{
  "permissions": [
    {
      "actions": [
        "*"
      ],
      "dataActions": [
        "*"
      ],
      "notActions": [
        "*/read",
        "Microsoft.MachineLearningServices/workspaces/*",
        "Microsoft.Storage/storageAccounts/*"
      ],
      "notDataActions": [
        "*/read",
        "Microsoft.Storage/storageAccounts/*"
      ]
    }
  ],
  "principals": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "type": "SystemDefined"
    }
  ],
  "condition": "@Subject[ResourceId] StringNotStartsWithIgnoreCase '/subscriptions/<subscription-id>/resourceGroups/<managed-resource-group>' && @Subject[tid] StringNotEqualsAnyOfIgnoreCase {'<publisher-tenant-id>'}",
  "scope": "/subscriptions/<subscription-id>/resourceGroups/<managed-resource-group>"
}

So the actual deny assignment does include:

Microsoft.Storage/storageAccounts/*

under notActions.

Error

Despite that, the training job fails with:

azure.core.exceptions.HttpResponseError: (AuthorizationFailed)
The client '<UAMI_CLIENT_ID>' with object id '<UAMI_PRINCIPAL_ID>' does not have authorization to perform action
'Microsoft.Storage/storageAccounts/listKeys/action'
over scope '/subscriptions/<subscription-id>/resourceGroups/<managed-resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account-name>'
or the scope is invalid. If access was recently granted, please refresh your credentials.

Code: AuthorizationFailed
Message: The client '<UAMI_CLIENT_ID>' with object id '<UAMI_PRINCIPAL_ID>' does not have authorization to perform action
'Microsoft.Storage/storageAccounts/listKeys/action'

Why this is confusing

I expected this to work because:

The UAMI has Storage Account Contributor on the exact storage account.

The action being denied is:

Microsoft.Storage/storageAccounts/listKeys/action

The deny assignment has this exception in notActions:

Microsoft.Storage/storageAccounts/*

The exact same training job works when the Managed Application is deployed with Customer Access = Full.

The issue only appears when the Managed Application uses restricted customer access.

Questions

Is this expected behavior for Azure Marketplace Managed Applications with restricted customer access?

Should Microsoft.Storage/storageAccounts/* in notActions allow:

Microsoft.Storage/storageAccounts/listKeys/action

Or does listKeys/action need to be explicitly added, even when the wildcard is present?

For example, should the allowed control actions include:

Microsoft.Storage/storageAccounts/listKeys/action

separately?

Also, does the Managed Application deny assignment apply to user-assigned managed identities created inside the managed resource group, even if those identities have explicit Azure RBAC roles on the storage account?

Finally, for Azure ML training jobs that need to write models/logs to Storage using managed identity, what are the recommended allowed control actions and allowed data actions for a restricted-customer-access Managed Application?

The main point I am trying to understand is:

Why does the UAMI fail Microsoft.Storage/storageAccounts/listKeys/action only under restricted customer access, even though the actual deny assignment includes Microsoft.Storage/storageAccounts/* in notActions, and the same deployment works with Customer Access = Full?Title: Azure Managed Application restricted customer access blocks UAMI listKeys despite Microsoft.Storage/storageAccounts/* in deny assignment notActions

Azure Machine Learning

2 answers

Sort by: Newest
  1. Sridevi Machavarapu 33,820 Reputation points Microsoft External Staff Moderator
    2026-08-05T05:59:54.2966667+00:00

    Hello Antonieta Pinto Rebelo,

    Thank you for the update and for sharing your findings.

    I understand the change in approach. Given the behavior you observed with listKeys under Restricted Customer Access, providing the container image and having the customer manage their own Azure ML environment is a reasonable workaround.

    For the original design, one option to consider in the future is to avoid listKeys altogether. Storage Account Contributor does include Microsoft.Storage/storageAccounts/listkeys/action, but Blob data access can be handled separately through Microsoft Entra ID and Azure RBAC. Since your UAMI already has Storage Blob Data Contributor, the training workload can access Blob Storage directly using the managed identity without retrieving the storage account keys.

    Microsoft recommends using Microsoft Entra ID with managed identities for Blob Storage access where possible.

    For reference:

    Thanks again for documenting the scenario and the workaround.

    Was this answer helpful?

    0 comments No comments

  2. Christos Panagiotidis 3,551 Reputation points
    2026-07-15T07:50:43.9266667+00:00

    Microsoft.Storage/storageAccounts/* should match Microsoft.Storage/storageAccounts/listKeys/action; adding the exact action separately should not change wildcard matching. listKeys is a management-plane action: Blob Data Contributor does not grant it, while Storage Account Contributor normally does.

    A deny assignment overrides RBAC, and its "All Principals" target includes managed identities. But with the condition shown, a UAMI whose resource is in the managed resource group should be excluded. Confirm that the object ID in the error is the UAMI’s principal ID (not its client ID), then check the deny assignments effective for that principal. If it is still denied despite that condition, this points to the generated managed-application deny assignment; open an Azure/Marketplace support request with its JSON and the correlation ID.

    For AML model and log output, avoid listKeys altogether. Use Entra ID data-plane Blob access (or an AML datastore) with Storage Blob Data Contributor. Request account keys only for a workflow that genuinely requires shared-key access.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.