Back to blog
AzureBest PracticesCloud SecurityOperations & ComplianceStorage

Encrypt Azure Recovery Services Vaults With Customer-Managed Keys (BYOK)

Learn why Azure Recovery Services Vaults should use customer-managed keys (BYOK), the risks of default encryption, and how to fix and enforce CMK.

TL;DR

This check flags Azure Recovery Services Vaults that rely on Microsoft-managed keys instead of a customer-managed key (BYOK). Switch the vault to a key stored in Key Vault so you control rotation, revocation, and the audit trail for your backup data at rest.

Recovery Services Vaults hold some of your most sensitive data: backups of VMs, SQL databases, file shares, and on-premises workloads. By default Azure encrypts that data at rest with a platform-managed key, which is fine for baseline protection but leaves Microsoft in control of the key lifecycle. For regulated environments, or anywhere you need to prove key custody, that is not good enough.

The rsv_nobyok check looks at each Recovery Services Vault in your subscription and reports any vault that is still using the default Microsoft-managed key rather than a customer-managed key (CMK) backed by Azure Key Vault.


What this check detects

Azure Recovery Services Vaults support two encryption models for data at rest:

  • Microsoft-managed keys (MMK) — the default. Azure generates, stores, and rotates the encryption key. You never see it and have no control over its lifecycle.
  • Customer-managed keys (CMK / BYOK) — you supply a key from an Azure Key Vault. You control rotation, can revoke access, and every key operation is logged.

The check passes when a vault is configured with a customer-managed encryption key and fails when it falls back to the default platform key. It inspects the vault's encryption properties, specifically whether a keyVaultProperties.keyUri is set and whether the encryption state reflects a customer key.

Note: CMK encryption for Recovery Services Vaults must be enabled before you register or protect any items in the vault. Microsoft does not support converting an existing vault that already has backup items to CMK in all scenarios, so plan this at vault creation time wherever possible.


Why it matters

Backup data is a high-value target. If an attacker or a careless insider can read your vault contents, they get a snapshot of entire systems, databases full of customer records, and credentials baked into VM images. Encryption at rest is the last line of defense when storage layer access controls fail.

With Microsoft-managed keys you cannot:

  • Revoke access in a breach. If you suspect compromise, there is no key to disable. With CMK you can remove the access policy or disable the key and the data becomes unreadable immediately.
  • Control rotation cadence. Compliance frameworks like PCI DSS, HIPAA, and many internal policies require keys to rotate on a defined schedule and to be auditable. MMK rotation is opaque.
  • Separate duties. CMK lets your security team own the key in a Key Vault while the backup team operates the vault, enforcing a real separation between who runs backups and who can decrypt them.
  • Produce an audit trail. Every wrap and unwrap of a customer-managed key shows up in Key Vault diagnostic logs. That evidence is often exactly what an auditor asks for.

Warning: Customer-managed keys protect data at rest, not the integrity of the access controls around the vault. A misconfigured RBAC role or a leaked privileged credential can still expose backups. Treat CMK as one layer, not the whole story.

The business impact is concrete: a failed audit can block a certification renewal, and an unencrypted-by-your-key backup that leaks can turn a contained incident into a reportable breach.


How to fix it

The fix has three parts: prepare a Key Vault and key, give the Recovery Services Vault a managed identity with access to that key, then point the vault at the key.

Step 1: Create or identify a Key Vault with the right settings

The Key Vault must have soft delete and purge protection enabled. Azure requires this so a backup key cannot be permanently destroyed while data depends on it.

az keyvault create \
  --name lensix-backup-kv \
  --resource-group rg-backup \
  --location eastus \
  --enable-soft-delete true \
  --enable-purge-protection true

Create an RSA key (minimum 2048 bits) to use for encryption:

az keyvault key create \
  --vault-name lensix-backup-kv \
  --name rsv-cmk \
  --protection software \
  --kty RSA \
  --size 2048

Step 2: Enable a managed identity on the vault and grant key access

Turn on a system-assigned managed identity for the Recovery Services Vault:

az backup vault identity assign \
  --resource-group rg-backup \
  --name my-recovery-vault \
  --system-assigned

Grant that identity permission to wrap, unwrap, and get the key. Capture the principal ID first:

PRINCIPAL_ID=$(az backup vault show \
  --resource-group rg-backup \
  --name my-recovery-vault \
  --query identity.principalId -o tsv)

az keyvault set-policy \
  --name lensix-backup-kv \
  --object-id "$PRINCIPAL_ID" \
  --key-permissions get wrapKey unwrapKey

Note: If your Key Vault uses Azure RBAC instead of access policies, assign the Key Vault Crypto Service Encryption User role to the managed identity rather than running set-policy.

Step 3: Point the vault at the customer-managed key

Grab the key URI and apply it as the vault's encryption key:

KEY_URI=$(az keyvault key show \
  --vault-name lensix-backup-kv \
  --name rsv-cmk \
  --query key.kid -o tsv)

az backup vault encryption update \
  --resource-group rg-backup \
  --name my-recovery-vault \
  --encryption-key-id "$KEY_URI"

Verify the change took effect:

az backup vault encryption show \
  --resource-group rg-backup \
  --name my-recovery-vault \
  --output json

You should see encryptionAtRestType set to CustomerManaged and the key URI populated.

Danger: Never delete the Key Vault, the key, or the key's enabled state while the Recovery Services Vault depends on it. Doing so makes your backups unrecoverable. Purge protection blocks permanent key deletion, but disabling a key or removing the vault's access policy will break restore operations until you reverse it.

Terraform example

For infrastructure as code, configure encryption at creation time so the vault is never exposed with the default key:

resource "azurerm_recovery_services_vault" "this" {
  name                = "my-recovery-vault"
  location            = azurerm_resource_group.backup.location
  resource_group_name = azurerm_resource_group.backup.name
  sku                 = "Standard"

  identity {
    type = "SystemAssigned"
  }
}

resource "azurerm_recovery_services_vault_resource_group" "placeholder" {}

resource "azurerm_key_vault_access_policy" "rsv" {
  key_vault_id = azurerm_key_vault.backup.id
  tenant_id    = azurerm_recovery_services_vault.this.identity[0].tenant_id
  object_id    = azurerm_recovery_services_vault.this.identity[0].principal_id

  key_permissions = ["Get", "WrapKey", "UnwrapKey"]
}

resource "azurerm_recovery_services_vault" "cmk" {
  # apply encryption after identity + access policy exist
  encryption {
    key_id                            = azurerm_key_vault_key.rsv_cmk.id
    infrastructure_encryption_enabled = true
  }
}

Tip: Set infrastructure_encryption_enabled = true to add a second layer of platform encryption underneath your customer key. It is a one-time decision made at vault creation and cannot be changed later, so enable it now if your compliance posture calls for double encryption.


How to prevent it from happening again

Fixing one vault is easy. Stopping the next team from spinning up a default-encrypted vault is the real win. Use Azure Policy to enforce CMK across every subscription.

Azure Policy

Assign a policy that audits or denies Recovery Services Vaults without a customer-managed key. A custom policy definition checks the encryption properties:

{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.RecoveryServices/vaults"
      },
      {
        "field": "Microsoft.RecoveryServices/vaults/encryption.keyVaultProperties.keyUri",
        "exists": "false"
      }
    ]
  },
  "then": {
    "effect": "audit"
  }
}

Start with audit to measure your blast radius, then move to deny once new vaults are reliably created with CMK. Assign it at the management group level so it covers every subscription beneath it.

CI/CD gates

If you provision with Terraform or Bicep, fail the pipeline when a vault definition lacks an encryption block. A quick check with Checkov catches it before deploy:

checkov -d ./infra --framework terraform \
  --check CKV_AZURE_206

Tip: Wire the rsv_nobyok check into your Lensix scan schedule and route failures to the same channel your backup team uses. Continuous scanning catches vaults created out-of-band through the portal that never went through your IaC pipeline.


Best practices

  • Enable CMK at vault creation. Converting an existing vault with protected items is restricted, so bake encryption into your standard vault template from day one.
  • Use a dedicated Key Vault for backup keys. Keep backup encryption keys separate from application secrets so access can be governed independently.
  • Turn on key auto-rotation. Recovery Services Vaults follow the latest version of the key when you enable auto-rotation, so you get scheduled rotation with no manual re-pointing.
  • Lock down the Key Vault. Restrict network access, enable purge protection, and audit access policies regularly. The key is only as safe as the vault holding it.
  • Log Key Vault operations. Send Key Vault diagnostic logs to a Log Analytics workspace so every wrap and unwrap is captured for your auditors.
  • Document recovery dependencies. Make sure runbooks note which Key Vault and key each Recovery Services Vault depends on, so no one accidentally deletes a key that backups rely on.

Customer-managed keys move the control of your backup encryption from Microsoft to you. That control is exactly what regulators, auditors, and incident responders expect, and it costs little beyond a Key Vault and a few minutes of setup. Get it in place at vault creation, enforce it with policy, and the rsv_nobyok check stays green.