Back to Checks
azure

Azure Storage account uses customer-managed keys (CMKs) for encryption

storage_ensure_encryption_with_customer_managed_keys
Service: storageSeverity: high
OfficialBuilt-inVerified
Categories:encryption
Resource Type:microsoft.storage/storageaccounts

Azure Storage accounts use customer-managed keys (CMK) from Key Vault/Managed HSM for service-side encryption of data at rest, rather than platform-managed keys (encryption_type=Microsoft.Keyvault).

Prowler logoProwlerprowler-provider-azure

Risk

Without CMK, keys are provider-controlled, reducing confidentiality and governance.

  • Cannot promptly revoke access during incidents
  • No custom rotation or separation of duties
  • Limited key-use auditing This weakens data sovereignty and hinders effective crypto-shredding.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks storage_ensure_encryption_with_customer_managed_keys

Recommendation

Adopt CMK with keys in Key Vault or Managed HSM. Enforce least privilege for the storage identity, regular key rotation, and separation of duties between key custodians and operators. Audit key usage, enable tamper-resistant key protection (soft-delete/purge protection), and plan for key revocation/crypto-shredding.

Remediation

CLI

az storage account update --name <STORAGE_ACCOUNT_NAME> --resource-group <RESOURCE_GROUP> --encryption-key-name <KEY_NAME> --encryption-key-source Microsoft.Keyvault --encryption-key-vault <KEY_VAULT_URI>

Terraform

# Configure a Storage Account to use Customer-Managed Keys (CMK)
resource "azurerm_storage_account" "<example_resource_name>" {
  name                     = "<example_resource_name>"
  resource_group_name      = "<example_resource_name>"
  location                 = "<location>"
  account_tier             = "Standard"
  account_replication_type = "LRS"

  identity {
    type = "SystemAssigned" # CRITICAL: allow storage account to access Key Vault
  }

  customer_managed_key {
    key_vault_key_id = "<example_resource_id>" # CRITICAL: Key Vault key ID enabling CMK (passes the check)
  }
}

NativeIaC

// Configure a Storage Account to use Customer-Managed Keys (CMK)
resource sa 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: '<example_resource_name>'
  location: '<location>'
  sku: { name: 'Standard_LRS' }
  kind: 'StorageV2'
  identity: {
    type: 'SystemAssigned' // CRITICAL: required so the storage account can access the key vault
  }
  properties: {
    encryption: {
      keySource: 'Microsoft.Keyvault' // CRITICAL: switches encryption to CMK (Prowler checks for this)
      keyVaultProperties: {
        keyName: '<key_name>' // required key name
        keyVaultUri: 'https://<example_resource_name>.vault.azure.net/' // required Key Vault URI
      }
    }
  }
}

Other

1In the Azure portal, open your Storage account
2Go to Settings > Encryption (or Security + networking > Encryption)
3Select Customer-managed keys
4Click Select a key vault and key, choose your Key Vault and key
5If prompted, enable System-assigned managed identity and grant the key permissions get, wrapKey, unwrapKey
6Click Save

Check Code

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.storage.storage_client import storage_client


class storage_ensure_encryption_with_customer_managed_keys(Check):
    def execute(self) -> Check_Report_Azure:
        findings = []
        for subscription, storage_accounts in storage_client.storage_accounts.items():
            subscription_name = storage_client.subscriptions.get(
                subscription, subscription
            )
            for storage_account in storage_accounts:
                report = Check_Report_Azure(
                    metadata=self.metadata(), resource=storage_account
                )
                report.subscription = subscription
                report.status = "PASS"
                report.status_extended = f"Storage account {storage_account.name} from subscription {subscription_name} ({subscription}) encrypts with CMKs."

                if storage_account.encryption_type != "Microsoft.Keyvault":
                    report.status = "FAIL"
                    report.status_extended = f"Storage account {storage_account.name} from subscription {subscription_name} ({subscription}) does not encrypt with CMKs."

                findings.append(report)

        return findings