Blob Storage Security in Azure
By default, an Azure storage account is reachable from the public internet. Default encryption is enabled, but access controls require active configuration to lock things down properly. This page walks through the full security model for Blob Storage — from network rules to encryption key management to immutability.
The security layers
Blob Storage security works in layers. Each layer stops a different class of threat:
- Network rules — controls which networks or IPs can reach the storage account at all
- Authentication and authorization — controls who can access what, after reaching the account
- Encryption — protects data at rest and in transit
- Data protection — versioning, soft delete, and immutability policies prevent data loss and tampering
A well-secured storage account uses all four layers together.
Network access rules
By default, Azure storage accounts allow traffic from all networks. The first hardening step is to restrict this.
# Set the default network action to Deny (block all by default)
az storage account update \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--default-action Deny
# Allow a specific IP address or CIDR range
az storage account network-rule add \
--account-name mystorageaccount123 \
--resource-group my-storage-rg \
--ip-address 203.0.113.50
# Allow a subnet in a virtual network
az storage account network-rule add \
--account-name mystorageaccount123 \
--resource-group my-storage-rg \
--vnet-name my-vnet \
--subnet my-app-subnet
# View current network rules
az storage account show \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--query "networkRuleSet"When you set the default action to Deny, Azure Portal access to the storage account is also blocked unless your browser’s IP is in the allow list. Adding the —bypass AzureServices flag allows Azure’s own management services (like the Portal) to still access the account: az storage account update —bypass AzureServices Logging Metrics.
Private endpoints
A private endpoint creates a network interface inside your VNet with a private IP address mapped to your storage account. All traffic flows through the VNet rather than over the public internet. The public endpoint can be disabled entirely.
# Get the storage account resource ID
STORAGE_ID=$(az storage account show \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--query "id" --output tsv)
# Create a private endpoint for blob storage
az network private-endpoint create \
--name storage-private-endpoint \
--resource-group my-storage-rg \
--vnet-name my-vnet \
--subnet my-private-subnet \
--private-connection-resource-id $STORAGE_ID \
--group-id blob \
--connection-name blob-private-connection
# Disable the public endpoint entirely
az storage account update \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--public-network-access DisabledAfter disabling the public endpoint, only resources inside the VNet (or connected via VPN/ExpressRoute) can access the storage account. This is the strongest network isolation you can configure.
Encryption at rest and in transit
Azure encrypts all blob data at rest automatically using AES-256 with Microsoft-managed keys. No configuration is needed for this baseline.
For organizations that need to control their own encryption keys (for compliance or key rotation requirements), Azure supports customer-managed keys (CMK) stored in Azure Key Vault:
# Create a Key Vault and a key for storage encryption
az keyvault create \
--name my-storage-keyvault \
--resource-group my-storage-rg \
--location eastus \
--sku Standard
az keyvault key create \
--vault-name my-storage-keyvault \
--name storage-encryption-key \
--kty RSA \
--size 2048
# Assign the storage account a system-assigned managed identity
az storage account update \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--assign-identity
# Get the identity's principal ID
PRINCIPAL_ID=$(az storage account show \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--query "identity.principalId" --output tsv)
# Grant Key Vault crypto permissions to the storage account identity
az keyvault set-policy \
--name my-storage-keyvault \
--object-id $PRINCIPAL_ID \
--key-permissions get wrapKey unwrapKey
# Configure the storage account to use the customer-managed key
KEY_ID=$(az keyvault key show \
--vault-name my-storage-keyvault \
--name storage-encryption-key \
--query "key.kid" --output tsv)
az storage account update \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--encryption-key-source Microsoft.Keyvault \
--encryption-key-vault https://my-storage-keyvault.vault.azure.net \
--encryption-key-name storage-encryption-key \
--encryption-key-version ""For encryption in transit, Azure Storage enforces HTTPS by default. You can verify and enforce the minimum TLS version:
az storage account update \
--name mystorageaccount123 \
--resource-group my-storage-rg \
--min-tls-version TLS1_2Immutability policies
Immutability policies prevent blobs from being modified or deleted for a specified period. This is important for regulatory compliance (SEC 17a-4, HIPAA, GDPR) and protection against ransomware — even an attacker with storage account keys cannot delete immutable blobs during the lock period.
There are two types:
- Time-based retention policy — blobs cannot be deleted or overwritten for the specified number of days after creation
- Legal hold — blobs are locked indefinitely until the hold is explicitly removed
# Set a 365-day immutability policy on a container
az storage container immutability-policy create \
--account-name mystorageaccount123 \
--container-name compliance-records \
--period 365
# Lock the policy (makes it irreversible — cannot be shortened once locked)
# First get the ETag from the policy
ETAG=$(az storage container immutability-policy show \
--account-name mystorageaccount123 \
--container-name compliance-records \
--query "etag" --output tsv)
az storage container immutability-policy lock \
--account-name mystorageaccount123 \
--container-name compliance-records \
--if-match "$ETAG"Once an immutability policy is locked, it cannot be shortened or removed before the retention period expires — not by you, not by Microsoft. Only extend it or wait for it to expire. Do not lock a policy in production until you are certain the retention period is correct. Test thoroughly in dev/staging first.
Common mistakes
- Leaving the default network action set to Allow. Every new storage account allows traffic from any IP by default. If you’re storing anything sensitive, the first thing you should do after creating an account is set the default action to Deny and add specific exceptions for your VNets and IPs.
- Treating encryption as something you need to configure. Azure encrypts everything at rest by default. Many beginners spend time looking for an encryption toggle that’s already on. Focus your effort on key management (CMK vs Microsoft-managed) and in-transit controls instead.
- Locking an immutability policy with the wrong retention period. A locked policy is irreversible. If you lock a policy with a 7-year retention period and later realize you only needed 1 year, you cannot shorten it. That data is stored for 7 years minimum, and you pay for it. Double-check your retention requirements before locking.
- Relying on network rules alone for authorization. Network rules control who can reach the account, but not what authenticated users can do once they connect. Use RBAC roles and SAS tokens to enforce least-privilege access in addition to network restrictions.
Summary
- Blob Storage security works in layers: network rules, authentication and authorization, encryption, and data protection features.
- Set the default network action to Deny and allow only specific VNets or IP ranges; use private endpoints to eliminate public endpoint exposure entirely.
- AES-256 encryption at rest is always on; use customer-managed keys in Key Vault only if your compliance requirements demand key control.
- Immutability policies prevent deletion and modification for compliance scenarios — but once locked, they cannot be shortened, so verify retention periods before locking.
Frequently asked questions
Is Azure Blob Storage encrypted by default?
Yes. Azure encrypts all data at rest using AES-256 by default with Microsoft-managed keys. You do not need to configure anything for encryption to be active. If you need to control your own keys, you can configure customer-managed keys via Azure Key Vault.
What is a private endpoint for storage?
A private endpoint gives your storage account a private IP address inside your virtual network. Traffic between Azure services and your storage account flows through the VNet backbone rather than the public internet. This prevents data from being accessible via the public storage URL, even accidentally.
Can I block all public access to a storage account?
Yes. Setting the storage account network rules to "Deny" with no exceptions blocks all public internet access. Only requests from explicitly allowed virtual networks, subnets, or IP ranges (or via private endpoints) will succeed. This is the recommended configuration for production storage accounts holding sensitive data.