Microsoft Defender for Cloud · Azure Container Registry
Container registries should be encrypted with a customer-managed key (CMK)
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Container registries should be encrypted with a customer-managed key (CMK)" check?
Flags any Azure Container Registry whose contents are encrypted at rest with the default platform-managed key rather than a customer-managed key (CMK) held in your own Azure Key Vault. It checks only that a CMK is configured on the registry; it does not verify that the backing key is rotated, that the key vault has purge protection and soft delete enabled, or that the registry's network and access controls are sound. It is also opt-in: by default this assessment is not evaluated, so until you set the policy effect to Audit or Deny for your scope, a registry without CMK will not be reported.
Why does "Container registries should be encrypted with a customer-managed key (CMK)" matter?
Registry images at rest are always encrypted, but a platform-managed key sits entirely inside Microsoft's control plane, so you cannot revoke it, scope its access, or prove independent custody to an auditor. A CMK moves that authority to a key vault you own: you can rotate it, gate it behind RBAC, and disable it to render the registry's layers unreadable if a key is suspected compromised. For organisations bound by regulatory regimes that mandate customer-controlled key custody, a registry on the default key is a direct compliance gap, and remediating it later is costly because CMK cannot be retrofitted onto an existing registry.
How do I fix "Container registries should be encrypted with a customer-managed key (CMK)"?
- Provision the prerequisites once: a user-assigned managed identity, plus an Azure Key Vault with soft delete and purge protection enabled holding an RSA key. Grant the identity the 'Key Vault Crypto Service Encryption User' role at the vault scope so the registry can wrap and unwrap with that key.
- Create the registry with CMK at provisioning time, because it cannot be added afterwards: az acr create --resource-group <rg> --name <registry> --sku Premium --identity <identity-resource-id> --key-encryption-key <key-vault-key-id>. The Premium tier is required for customer-managed keys. In Bicep, set the Microsoft.ContainerRegistry/registries 'encryption' property with keyVaultProperties.keyIdentifier and the identity reference.
- Enforce the standard going forward by assigning the built-in policy so new registries are caught. Look the definition up by display name rather than pasting a GUID: pid=$(az policy definition list --query "[?displayName=='Container registries should be encrypted with a customer-managed key (CMK)'].name" -o tsv); az policy assignment create --name acr-cmk --policy "$pid" --scope <scope>.
Remediation script · bash
# 1. Lock down an existing Premium registry: add a private endpoint, then close the public door.
RG=platform-rg
ACR=prodimagesacr
VNET=hub-vnet
SUBNET=registry-subnet
# Create the private endpoint into your VNet (registry must be Premium).
ACR_ID=$(az acr show --name "$ACR" --query id -o tsv)
az network private-endpoint create \
--resource-group "$RG" --name "${ACR}-pe" \
--vnet-name "$VNET" --subnet "$SUBNET" \
--private-connection-resource-id "$ACR_ID" \
--group-id registry \
--connection-name "${ACR}-conn"
# Close the public door but keep trusted services (Defender, ACR Tasks, import) reaching it.
az acr update --name "$ACR" \
--default-action Deny \
--public-network-enabled false \
--allow-trusted-services true
# 2. Create a NEW registry encrypted with a customer-managed key (CMK is create-time only).
# Prereqs already in place: user-assigned identity granted 'Key Vault Crypto Service
# Encryption User' on a key vault with soft-delete + purge protection, and an RSA key.
az acr create --resource-group "$RG" --name regulatedacr --sku Premium \
--identity "$identityID" --key-encryption-key "$keyID"
# 3. Ratchet it shut estate-wide: audit any registry that allows unrestricted network access.
pid=$(az policy definition list \
--query "[?displayName=='Container registries should not allow unrestricted network access'].name" -o tsv)
az policy assignment create \
--name audit-acr-network \
--policy "$pid" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure Container Registry.
Is "Container registries should be encrypted with a customer-managed key (CMK)" a false positive?
A registry created without CMK and now holding live images is sometimes left on the platform-managed key on purpose, because CMK cannot be enabled on an existing registry and rebuilding it would mean re-pushing every image and repointing every pipeline and pull secret. If a service-managed key meets your regulatory obligations, this is a defensible exception: document it, and reserve CMK for the next new registry where you can set it at creation. Because the assessment is opt-in, an unconfigured policy effect is not itself a finding.