The Problem: Controlling Who Can Reach Your Data
Every organization storing data in the cloud faces a fundamental question: how do you let authorized users and applications access that data while keeping everyone else out? Azure storage accounts hold business-critical data, from virtual machine disks to application logs to customer documents. Unlike compute resources that are controlled primarily through the management plane (ARM), storage accounts have a rich data plane that applications interact with directly through REST APIs. This means access control for storage must address both management operations (creating containers, setting policies) and data operations (reading blobs, writing files).
Azure provides five complementary layers to control access to storage. Each layer works independently, and an incoming request must pass every applicable layer to succeed.
Layer 1: Storage Account Keys
When you create an Azure storage account, Azure generates two 512-bit access keys, called key1 and key2. These keys function as root passwords: any client holding a valid key has unrestricted access to every service and every piece of data in that storage account. A storage account key is a symmetric key used to authenticate requests to the Azure Storage REST API by constructing an HMAC-SHA256 signature over the request headers.
Two keys exist so you can rotate one while the other remains active. The recommended rotation procedure is:
- Update all applications to use key2.
- Regenerate key1 in the Azure portal (or via CLI/PowerShell).
- Update all applications to use the newly regenerated key1.
- Regenerate key2.
# List storage account keys
az storage account keys list \
--account-name mystorageacct \
--resource-group myRG \
--output table
# Regenerate key1
az storage account keys renew \
--account-name mystorageacct \
--resource-group myRG \
--key key1
# List storage account keys
Get-AzStorageAccountKey -ResourceGroupName "myRG" -Name "mystorageacct"
# Regenerate key1
New-AzStorageAccountKey -ResourceGroupName "myRG" -Name "mystorageacct" -KeyName "key1"
💡 Exam Trap: Regenerating a storage account key immediately invalidates every SAS token and every connection string that was signed with that key. If applications use SAS tokens signed with key1 and you regenerate key1, those tokens become invalid instantly, even if they have not expired yet.
Because account keys grant unlimited access, Microsoft recommends avoiding their use in production applications. Instead, prefer Azure AD authentication (covered below) or scoped shared access signatures.
Layer 2: Shared Access Signatures (SAS)
A shared access signature (SAS) is a URI query string appended to a storage resource URL that grants constrained access for a limited time. A SAS encodes the permissions, the resource scope, the start and expiry times, the allowed IP addresses, and the allowed protocol (HTTPS only or HTTPS and HTTP) directly into the token string. The storage service validates these fields on every request.
Azure supports three types of SAS:
User Delegation SAS
A user delegation SAS is signed using Azure AD credentials rather than an account key. The caller obtains a user delegation key from Azure AD, and this key is used to sign the SAS token. Because it relies on Azure AD, a user delegation SAS carries the identity and RBAC permissions of the requesting principal. It can only be used with Blob storage and Azure Data Lake Storage Gen2.
# Get user delegation key (valid for up to 7 days)
az storage blob generate-sas \
--account-name mystorageacct \
--container-name mycontainer \
--name myblob.txt \
--permissions r \
--expiry 2026-05-01T00:00:00Z \
--auth-mode login \
--as-user \
--output tsv
💡 Exam Trap: User delegation SAS is supported only for Blob storage (and Data Lake Storage Gen2). You cannot create a user delegation SAS for Azure Files, Table storage, or Queue storage. The exam may present a scenario requiring a SAS for an Azure file share and offer "user delegation SAS" as a distractor answer.
Service SAS
A service SAS is signed with one of the two storage account keys and grants access to resources in a single service: Blob, Queue, Table, or File. The token specifies which service, container or share, and which operations are allowed. Because it is signed with the account key, anyone who obtains the token can use it until it expires or until the signing key is regenerated.
Account SAS
An account SAS is also signed with an account key but grants access across one or more services within the storage account. It can authorize service-level operations that a service SAS cannot, such as listing containers or file shares.
SAS Best Practices
| Practice | Reason |
|---|---|
| Prefer user delegation SAS | Eliminates account key exposure; uses Azure AD identity |
| Set the shortest practical expiry | Limits the window of risk if the token leaks |
| Grant minimum permissions | Follow least-privilege; do not grant write if only read is needed |
| Use HTTPS only (spr=https) | Prevents token interception on the wire |
| Use stored access policies when possible | Allows revocation without regenerating the account key |
Stored Access Policies
A stored access policy is a named policy defined on a container, queue, table, or file share that specifies start time, expiry time, and permissions. A service SAS can reference a stored access policy by name instead of embedding these values directly in the token. This gives you a revocation mechanism: modifying or deleting the stored access policy immediately invalidates every SAS that references it.
Each container, queue, table, or file share supports a maximum of 5 stored access policies.
# Create a stored access policy on a blob container
az storage container policy create \
--container-name mycontainer \
--name readpolicy \
--permissions r \
--expiry 2026-06-01T00:00:00Z \
--account-name mystorageacct \
--account-key <key>
# Generate a service SAS referencing the stored access policy
az storage blob generate-sas \
--account-name mystorageacct \
--container-name mycontainer \
--name myblob.txt \
--policy-name readpolicy \
--output tsv
💡 Exam Trap: Stored access policies are not supported for user delegation SAS or account SAS. They only work with service SAS. If the exam asks how to revoke a user delegation SAS, the correct answer is to revoke the user delegation key (which invalidates all user delegation SAS tokens signed with that key), not to modify a stored access policy.
💡 Exam Trap: You can have a maximum of 5 stored access policies per container, queue, table, or file share. The exam may test this limit.
Layer 3: Azure AD Authentication for Storage (Azure RBAC on the Data Plane)
Chapter 1 introduced Azure RBAC as the authorization system for management plane operations. The same RBAC mechanism extends to the storage data plane through a set of built-in data roles. When Azure AD authentication is used, the caller presents an OAuth 2.0 token issued by Azure AD, and the storage service checks the caller's role assignments at the appropriate scope (storage account, container, queue).
Key built-in data roles for storage:
| Role | Description |
|---|---|
| Storage Blob Data Owner | Full access to blob containers and data, including setting POSIX ACLs |
| Storage Blob Data Contributor | Read, write, and delete blob containers and blobs |
| Storage Blob Data Reader | Read blob containers and blobs |
| Storage Blob Delegator | Obtain a user delegation key (required for creating user delegation SAS) |
| Storage File Data SMB Share Contributor | Read, write, and delete in Azure file shares over SMB |
| Storage File Data SMB Share Reader | Read access to Azure file shares over SMB |
| Storage File Data SMB Share Elevated Contributor | Read, write, delete, and modify ACLs in Azure file shares over SMB |
| Storage File Data Privileged Contributor | Read, write, delete, and modify NTFS permissions in Azure file shares |
| Storage File Data Privileged Reader | Read access with NTFS permission bypass in Azure file shares |
| Storage Queue Data Contributor | Read, write, and delete queues and queue messages |
| Storage Queue Data Reader | Read and peek queue messages |
| Storage Queue Data Message Processor | Peek, retrieve, and delete queue messages |
| Storage Queue Data Message Sender | Add messages to a queue |
| Storage Table Data Contributor | Read, write, and delete table entities |
| Storage Table Data Reader | Read table entities |
💡 Exam Trap: The classic "Contributor" or "Owner" roles grant management plane access (they can manage the storage account itself, including reading account keys). However, these roles do NOT automatically grant data plane access. A user with the "Contributor" role can manage the storage account but cannot read a blob unless they also have a data role like "Storage Blob Data Reader" or use the account keys. The exam frequently tests this distinction.
# Assign the Storage Blob Data Reader role at the container scope
az role assignment create \
--assignee user@contoso.com \
--role "Storage Blob Data Reader" \
--scope "/subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.Storage/storageAccounts/mystorageacct/blobServices/default/containers/mycontainer"
# Same assignment in PowerShell
New-AzRoleAssignment `
-SignInName "user@contoso.com" `
-RoleDefinitionName "Storage Blob Data Reader" `
-Scope "/subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.Storage/storageAccounts/mystorageacct/blobServices/default/containers/mycontainer"
Recall from Chapter 1 that managed identities eliminate the need for credentials in application code. An Azure VM or App Service with a system-assigned managed identity can authenticate to storage using Azure AD, with the required data roles assigned to the managed identity's service principal.
Layer 4: Network Access Controls
Network-level controls determine which networks can reach your storage account endpoint. By default, storage accounts accept connections from all networks. You can restrict this by configuring the storage account firewall.
Firewall and Virtual Network Rules
The storage account firewall lets you allow or deny access from specific IP addresses, IP ranges, and Azure virtual network subnets. When you add a virtual network rule, the storage account accepts traffic only from the specified subnets (using service endpoints or private endpoints).
A service endpoint (formally, a virtual network service endpoint) is a feature that extends a virtual network's private address space to Azure services over a direct route on the Azure backbone. When you enable a service endpoint for Microsoft.Storage on a subnet, traffic from that subnet to Azure Storage travels over the Azure backbone network rather than over the public internet. The storage account firewall recognizes the source subnet and permits the traffic.
# Set default action to Deny (block all traffic not explicitly allowed)
az storage account update \
--name mystorageacct \
--resource-group myRG \
--default-action Deny
# Allow a specific virtual network subnet
az storage account network-rule add \
--account-name mystorageacct \
--resource-group myRG \
--vnet-name myVNet \
--subnet mySubnet
# Allow a specific public IP address
az storage account network-rule add \
--account-name mystorageacct \
--resource-group myRG \
--ip-address 203.0.113.5
💡 Exam Trap: When the default action is set to Deny, you must explicitly add network rules for any client that needs access, including Azure services. The "Allow trusted Microsoft services" exception (discussed below) covers only a specific list of first-party Azure services; it does not cover your own VMs or App Services unless they are in an allowed subnet.
Trusted Microsoft Services
Some Azure services operate from IP addresses that cannot be predicted or added to firewall rules. Azure provides a checkbox, "Allow trusted Microsoft services to access this storage account," that bypasses the firewall for a defined list of first-party services such as Azure Backup, Azure Site Recovery, Azure Event Grid, Azure Monitor (diagnostic logs), and several others.
Private Endpoints
A private endpoint is a network interface in your virtual network that receives a private IP address and maps to a specific Azure resource (in this case, a storage account sub-resource such as blob, file, queue, or table). Traffic to the storage account goes over the virtual network and the Microsoft backbone, never traversing the public internet.
Unlike service endpoints (which keep the storage account's public endpoint active and simply add a network rule), private endpoints create a dedicated private IP within your VNet. You can disable the storage account's public endpoint entirely and force all access through private endpoints.
# Create a private endpoint for the blob sub-resource
az network private-endpoint create \
--name myBlobPE \
--resource-group myRG \
--vnet-name myVNet \
--subnet myPESubnet \
--private-connection-resource-id $(az storage account show --name mystorageacct --resource-group myRG --query id -o tsv) \
--group-ids blob \
--connection-name myBlobConnection
Decision Tree: Choosing the Right Network Access Method
Layer 5: Encryption
Azure Storage encrypts all data at rest using 256-bit AES encryption. This is called Storage Service Encryption (SSE) and it is always on; you cannot disable it. By default, Microsoft manages the encryption keys (Microsoft-managed keys). You can alternatively use customer-managed keys (CMK) stored in Azure Key Vault or Azure Key Vault Managed HSM, or customer-provided keys where the client includes the encryption key with each request.
| Key management option | Supported services | Key storage |
|---|---|---|
| Microsoft-managed keys | Blob, File, Queue, Table | Microsoft managed |
| Customer-managed keys (CMK) | Blob, File, Queue, Table | Azure Key Vault or Managed HSM |
| Customer-provided keys | Blob only | Client manages; key sent per-request |
💡 Exam Trap: Customer-provided keys (where the client sends the key with each request header) are supported only for Blob storage. Do not confuse this with customer-managed keys (CMK) stored in Key Vault, which support all four storage services.
Infrastructure Encryption (Double Encryption)
You can enable infrastructure encryption on a storage account for an additional layer of encryption using a different encryption algorithm. When enabled, data is encrypted twice: once at the service level (SSE) and once at the infrastructure level, each with a different key. Infrastructure encryption must be enabled at storage account creation time; it cannot be added later.
Anonymous (Public) Access to Blobs
Azure Blob Storage supports configuring containers for anonymous public read access, allowing anyone with the URL to read data without authentication. This is controlled at two levels:
- Storage account level: The property
allowBlobPublicAccesscontrols whether any container in the account can enable public access. If set to false, no container can be made public regardless of its own setting. - Container level: Each container has a public access setting: Private (no anonymous access), Blob (anonymous read access for blobs only), or Container (anonymous read access for blobs and container listing).
💡 Exam Trap: Even if a container is set to "Blob" or "Container" public access, the storage account's
allowBlobPublicAccessproperty must also betrue. If the account-level setting isfalse, all containers are private regardless of their individual settings. New storage accounts default toallowBlobPublicAccess = false.
# Disable public blob access at the account level
az storage account update \
--name mystorageacct \
--resource-group myRG \
--allow-blob-public-access false
Bringing It All Together: How Layers Interact
When a request arrives at a storage account, the following checks occur in order:
- Network layer: Is the request coming from an allowed network (IP rule, VNet rule, private endpoint, or trusted service exception)? If not, the request is denied with 403.
- Authentication: Is the request authenticated? The caller must present one of: an account key, a valid SAS token, or an Azure AD OAuth token. Anonymous access is only valid for containers with public access enabled.
- Authorization: Does the authenticated identity have the necessary permissions? For RBAC, the role assignment must include the required data action. For SAS, the token must include the required permission character. For account keys, all operations are authorized.
- Encryption: Data is decrypted on read and encrypted on write transparently.
With the mechanisms for securing storage access now in place, the next section covers how to create and configure the storage accounts that these access controls protect.
