How to Fix: Azure Storage Account Access Denied

Azure403High severity

The Scenario

You’re deploying a new microservice on a Friday afternoon that needs to read blobs from a storage account. The CI/CD pipeline completes successfully, but the application immediately starts throwing 403 errors when trying to access the storage account from your AKS cluster.

Symptoms

Root Cause

Azure Storage accounts have multiple security layers that must all be satisfied simultaneously. The most common cause is a mismatch between the identity being used (managed identity, service principal, or SAS token) and the RBAC permissions on the storage account, combined with network restrictions that block the request before authentication is even checked.

Resolution (Step-by-Step)

  1. Check if the storage account has public network access disabled

    az storage account show --name <storage-account> --resource-group <rg> --query "networkRuleSet.defaultAction"

    If this returns Deny, you need to either enable a service endpoint or private endpoint for your client.

  2. Add a service endpoint for your subnet

    az network vnet subnet update \
      --resource-group <rg> \
      --vnet-name <vnet> \
      --name <subnet> \
      --service-endpoints Microsoft.Storage
  3. Add the subnet to the storage account firewall

    az storage account network-rule add \
      --resource-group <rg> \
      --account-name <storage-account> \
      --vnet <vnet> \
      --subnet <subnet>
  4. Verify RBAC permissions for the managed identity

    az role assignment list --assignee <managed-identity-principal-id> --scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage-account>

    Ensure the role is Storage Blob Data Contributor or Storage Blob Data Reader, not just Contributor.

  5. If using SAS tokens, regenerate and validate

    az storage account keys list --account-name <storage-account> --resource-group <rg>
    az storage container generate-sas --account-name <storage-account> --name <container> --permissions r --expiry 2026-12-31 --account-key <key>

Why This Sometimes Doesn’t Work

The biggest gotcha is that RBAC roles are evaluated after network rules. If your network rule blocks the request, you’ll get a 403 even with the correct RBAC permissions. Also, managed identities in AKS require az aks update --enable-managed-identity to be explicitly enabled on the cluster — just assigning the role isn’t enough if the cluster itself isn’t configured for managed identity.

Verification

az storage blob exists --account-name <storage-account> --container-name <container> --name test.txt --auth-mode login

Expected output: True

Common Follow-up Questions

Why does the Azure portal work but my app doesn’t? The portal uses your user identity which may have different RBAC permissions than your application’s managed identity or service principal.

Do I need both RBAC and network rules? No, network rules are separate from RBAC. You need either public access with RBAC, or private/service endpoint access with RBAC. Both layers must pass.

Can I just allow all networks temporarily? Yes, but only for debugging. Set defaultAction to Allow with az storage account update --default-action Allow. Revert immediately after testing.

Prevent This in the Future

The most common cause of this error is a missing network rule or RBAC assignment that isn’t caught until deployment. Set up monitoring with Better Stack to alert on 403 errors from your storage account before they become production incidents.

Set up uptime monitoring and alerts with Better Stack