Azure Blob Storage - Street-Level Ops¶
Secure Account Creation¶
rg=rg-sre-lab
location=eastus
account=stsreresearch$RANDOM
az storage account create \
--name "$account" \
--resource-group "$rg" \
--location "$location" \
--sku Standard_ZRS \
--kind StorageV2 \
--min-tls-version TLS1_2 \
--allow-blob-public-access false
# Disable account-key authorization after validating every client supports Entra ID.
az storage account update \
--name "$account" \
--resource-group "$rg" \
--allow-shared-key-access false
az storage container create \
--account-name "$account" \
--name artifacts \
--auth-mode login
Storage account names are globally unique, 3-24 characters, lowercase letters and digits only. (Microsoft Learn: Create a storage account)
Normal Upload/Download Operations¶
az storage blob upload-batch \
--account-name "$account" \
--destination artifacts \
--source ./dist \
--auth-mode login \
--overwrite
az storage blob list \
--account-name "$account" \
--container-name artifacts \
--auth-mode login \
--output table
For high-volume transfer, use AzCopy rather than shell loops around az storage blob upload. AzCopy supports parallelism, resumability, and Entra/SAS authorization.
Application Access Pattern¶
Preferred production pattern:
- Assign a managed identity to the VM, Function, App Service, AKS workload, or automation runner.
- Grant a narrowly scoped data-plane role at the account or container scope.
- Use the Azure SDK default credential chain.
- Disable Shared Key if all dependencies support Entra authentication.
- Use a private endpoint and private DNS when public access is not required.
Example role assignment:
storage_id=$(az storage account show \
--resource-group "$rg" \
--name "$account" \
--query id -o tsv)
principal_id=<managed-identity-principal-object-id>
az role assignment create \
--assignee-object-id "$principal_id" \
--assignee-principal-type ServicePrincipal \
--role "Storage Blob Data Contributor" \
--scope "$storage_id"
Where supported, scope the assignment to a container resource ID rather than the entire account.
Private Endpoint Pattern¶
A hardened storage design commonly uses:
- Public network access disabled or restricted.
- Private endpoint for the blob subresource.
privatelink.blob.core.windows.netPrivate DNS zone.- VNet links and DNS forwarding to on-premises networks.
- Separate private endpoints for
blob,dfs,file, or other subresources as required.
HNS workloads often need both blob and DFS endpoint planning. Creating only one private endpoint can produce confusing partial functionality.
Lifecycle Management¶
Lifecycle policies are JSON rules applied asynchronously to supported blobs. They can:
- Move current versions, previous versions, or snapshots to cooler tiers.
- Delete data after age criteria.
- Filter by prefix or blob index tags.
They cannot rehydrate archive data. Lifecycle operations are not instantaneous and should not be treated as a cron job with an exact completion time. (Microsoft Learn: Lifecycle management)
Example policy fragment:
{
"rules": [
{
"enabled": true,
"name": "archive-old-builds",
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["artifacts/releases/"]
},
"actions": {
"baseBlob": {
"tierToCool": {"daysAfterModificationGreaterThan": 30},
"tierToArchive": {"daysAfterModificationGreaterThan": 180},
"delete": {"daysAfterModificationGreaterThan": 730}
}
}
}
}
]
}
Protection Baseline¶
For general-purpose production object data:
- Enable blob versioning.
- Enable blob and container soft delete with an explicit retention period.
- Use lifecycle rules for old versions and deleted data.
- Enable change feed/point-in-time restore only when the recovery objective justifies cost and feature constraints.
- Use immutable storage for compliance/ransomware-resistant data, with governance around locking policies.
- Test restoration, including restoring prior versions under application load.