This check flags Azure Storage accounts that do not have encryption fully enabled across blob and file services. Unencrypted data at rest exposes you to compliance gaps and breach risk. Enable Microsoft-managed or customer-managed keys with a single CLI command or a Terraform property and you are covered.
Encryption at rest is one of those controls that sounds boring until an auditor asks about it or a disk image walks out the door. Azure makes encryption straightforward, but storage accounts can still end up in a state where it is partially or improperly configured, especially in older subscriptions or hand-built resources. This check looks for any Azure Storage account where full encryption is not enabled and tells you exactly where to look.
What this check detects
The storage_encryption check inspects each Azure Storage account in your subscription and verifies that Storage Service Encryption (SSE) is active for all supported services, namely blob and file storage. It looks at the encryption configuration returned by the storage account API and flags accounts where encryption is disabled or not covering all expected services.
Note: Azure has encrypted all new storage accounts at rest with platform-managed keys by default since 2017. The reason this check still matters is that encryption settings can be altered, customer-managed key (CMK) configurations can break when a Key Vault key is rotated or deleted, and infrastructure-as-code can drift from the intended state. "Encrypted by default" is not the same as "verified encrypted right now."
In practice the check surfaces accounts in a few problematic states:
- Encryption services explicitly disabled for blob or file (rare, but possible through API calls or legacy templates).
- A customer-managed key configuration that points to a Key Vault key that has been disabled, deleted, or is no longer accessible.
- Accounts where infrastructure code does not assert encryption, leaving the posture undocumented and subject to drift.
Why it matters
Encryption at rest protects the physical layer. If a disk is decommissioned improperly, an Azure backend component is compromised, or someone gains access to the underlying storage media, encryption is what stands between an attacker and your raw data. Without it, the bytes on disk are readable plaintext.
The business impact lands in a few concrete places:
- Compliance failures. PCI DSS, HIPAA, SOC 2, ISO 27001, and GDPR all expect encryption at rest for sensitive data. An unencrypted storage account is a finding an auditor will write up, and remediation under audit pressure is never fun.
- Breach blast radius. When encryption is in place, a stolen snapshot or backup is far less useful to an attacker. Without it, exfiltrated data is immediately exploitable.
- Key management gaps. A broken CMK setup can mean your data is either inaccessible or silently falling back to platform keys, neither of which matches your intended control model.
Encryption at rest will not save you from a misconfigured public container or a leaked SAS token. It is one layer in a defense-in-depth strategy, not a substitute for access control.
How to fix it
First, confirm the current encryption state of the account. Replace the placeholders with your account and resource group names.
az storage account show \
--name mystorageaccount \
--resource-group my-resource-group \
--query encryption \
--output json
You will see a block describing which services are encrypted and which key source is in use. A healthy result looks something like this:
{
"keySource": "Microsoft.Storage",
"services": {
"blob": { "enabled": true, "keyType": "Account" },
"file": { "enabled": true, "keyType": "Account" }
}
}
Option 1: Microsoft-managed keys (default)
If you simply want platform-managed encryption restored or confirmed, set the key source back to Microsoft.Storage:
az storage account update \
--name mystorageaccount \
--resource-group my-resource-group \
--encryption-key-source Microsoft.Storage
Option 2: Customer-managed keys (CMK)
If your compliance requirements call for control over the key lifecycle, use a key stored in Azure Key Vault. First make sure the storage account has a managed identity and that identity has get, wrapKey, and unwrapKey permissions on the vault.
# Assign a system-managed identity to the storage account
az storage account update \
--name mystorageaccount \
--resource-group my-resource-group \
--assign-identity
# Point the account at your Key Vault key
az storage account update \
--name mystorageaccount \
--resource-group my-resource-group \
--encryption-key-source Microsoft.Keyvault \
--encryption-key-vault https://myvault.vault.azure.net \
--encryption-key-name my-storage-key \
--encryption-key-version <key-version>
Warning: If you use a pinned key version and that version is rotated or expires, the storage account can lose access to the key and become unreadable. Either omit the version to enable automatic rotation following the latest key, or pair CMK with a soft-delete and purge-protection policy on the Key Vault so a key cannot be permanently lost.
Danger: Never delete a Key Vault key that is currently encrypting a storage account. Doing so renders all data in that account permanently inaccessible. Enable purge protection on the vault before adopting CMK in production.
Console steps
- Open the storage account in the Azure portal.
- Under Security + networking, select Encryption.
- Choose Microsoft-managed keys or Customer-managed keys.
- For CMK, select the Key Vault and key, then save.
Tip: For bulk remediation, list every storage account that is not using your intended key source and pipe it into an update loop. This is far faster than clicking through the portal account by account.
az storage account list \
--query "[?encryption.keySource!='Microsoft.Keyvault'].{name:name, rg:resourceGroup}" \
--output table
How to prevent it from happening again
The fastest way to stop this recurring is to encode the requirement in your infrastructure and enforce it before deployment.
Define encryption in Terraform
An azurerm_storage_account resource has encryption applied by default, but you should still make intent explicit and, for CMK, declare the key relationship:
resource "azurerm_storage_account" "secure" {
name = "mystorageaccount"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "GRS"
infrastructure_encryption_enabled = true
identity {
type = "SystemAssigned"
}
}
resource "azurerm_storage_account_customer_managed_key" "cmk" {
storage_account_id = azurerm_storage_account.secure.id
key_vault_id = azurerm_key_vault.main.id
key_name = azurerm_key_vault_key.storage.name
}
Setting infrastructure_encryption_enabled = true adds a second layer of encryption at the infrastructure level, which is often a requirement for the most sensitive workloads.
Enforce with Azure Policy
Azure Policy can audit or deny storage accounts that do not meet your encryption standard. Assign the built-in policy that requires customer-managed keys, or a custom policy that denies creation of accounts without CMK:
az policy assignment create \
--name "require-storage-cmk" \
--display-name "Storage accounts must use customer-managed keys" \
--policy "6fac406b-40ca-413b-bf8e-0bf964659c25" \
--scope "/subscriptions/<subscription-id>"
Gate it in CI/CD
Run a policy-as-code scan against your Terraform plan before it merges. Tools like Checkov, tfsec, or Conftest can fail a pull request when a storage account lacks the encryption properties you require. A blocked merge is cheaper than a remediation ticket.
Tip: Pair a pre-deploy IaC scan with a continuous posture check in Lensix. The scan catches problems at the gate, and the runtime check catches drift, manual portal changes, and broken CMK references that bypassed your pipeline entirely.
Best practices
- Decide on a key strategy and apply it consistently. Microsoft-managed keys are fine for most workloads. Reserve CMK for data with regulatory requirements that mandate key control, since it adds operational overhead.
- Always enable Key Vault soft delete and purge protection before using CMK. This is the single most common cause of irreversible data loss with customer-managed keys.
- Turn on infrastructure encryption for highly sensitive accounts to get double encryption at rest.
- Monitor CMK health. A rotated, disabled, or expired key can quietly break access. Alert on key vault events tied to keys used by storage.
- Do not treat encryption at rest as your only control. Combine it with private endpoints, disabled public blob access, scoped SAS tokens, and Azure AD authentication for a real defense-in-depth posture.
Encryption at rest on Azure Storage is low effort and high value. Get it asserted in code, enforce it with policy, and watch for drift, and this check stays green without anyone having to think about it again.

