Storage - Access Patterns
Prerequisites for Granting Storage Access
⚠️ Important: To assign storage roles to managed identities, you need:
- User Access Administrator or Owner role on the Storage Account (or parent resource group/subscription)
- The role must include the
Microsoft.Authorization/roleAssignments/writepermission
Common scenarios:
- Granting Storage Blob Data Owner to a Web App or Function App's managed identity (System Assigned or User Assigned)
- Adding read/write access to blobs, queues, and tables for application workloads
- Allowing user identities (developers, data admins) access in dev/test environments
- Allowing applications to access storage using managed identity instead of connection strings
Scope best practices:
- Grant roles at the smallest scope possible (e.g., specific storage account, not resource group or subscription)
- Avoid broad scopes (Resource Group, Subscription, Tenant) unless absolutely necessary
- Prefer resource-level assignments for production workloads
Managed identity types:
- System Assigned: Automatically created with the resource (Web App, Function). Default when using
DefaultAzureCredential. - User Assigned: Standalone identity that can be shared across resources. Requires additional configuration:
- Set
AZURE_CLIENT_IDapp setting to the User Assigned Managed Identity's client ID - Configure identity in Bicep with both
type: 'SystemAssigned, UserAssigned'anduserAssignedIdentities
If you encounter AuthorizationFailed errors when assigning roles, ensure you have User Access Administrator or Owner permissions at the target scope.
Managed Identity Role Assignment
resource storageRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(storageAccount.id, principalId, 'Storage Blob Data Contributor')
scope: storageAccount
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
principalId: principalId
principalType: 'ServicePrincipal'
}
}Storage Roles
| Role | Permissions |
|---|---|
| Storage Blob Data Reader | Read blobs |
| Storage Blob Data Contributor | Read/write blobs |
| Storage Queue Data Contributor | Read/write queues |
| Storage Table Data Contributor | Read/write tables |
SDK Connection Patterns
Node.js
const { BlobServiceClient } = require("@azure/storage-blob");
const blobServiceClient = BlobServiceClient.fromConnectionString(
process.env.AZURE_STORAGE_CONNECTION_STRING
);
const containerClient = blobServiceClient.getContainerClient("uploads");Python
from azure.storage.blob import BlobServiceClient
blob_service_client = BlobServiceClient.from_connection_string(
os.environ["AZURE_STORAGE_CONNECTION_STRING"]
)
container_client = blob_service_client.get_container_client("uploads").NET
var blobServiceClient = new BlobServiceClient(
Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING")
);
var containerClient = blobServiceClient.GetBlobContainerClient("uploads");Managed Identity Access
Use DefaultAzureCredential for local development (in production, use ManagedIdentityCredential — see auth-best-practices.md):
const { DefaultAzureCredential } = require("@azure/identity");
const { BlobServiceClient } = require("@azure/storage-blob");
const client = new BlobServiceClient(
`https://${accountName}.blob.core.windows.net`,
new DefaultAzureCredential()
);