This check flags Azure Service Bus namespaces that rely on Microsoft-managed keys instead of a customer-managed key (CMK). Without a CMK you lose control over the encryption key lifecycle and the ability to revoke access to your message data. Fix it by enabling a CMK from Azure Key Vault on a Premium namespace.
Service Bus is where a lot of sensitive data quietly flows through your architecture: order events, payment instructions, PII updates, internal commands between microservices. All of that data sits at rest inside the namespace, and by default Azure encrypts it with platform-managed keys. That is fine for many workloads, but if you operate under compliance frameworks like PCI DSS, HIPAA, or anything with strict key custody requirements, "Microsoft holds the key" is not an acceptable answer.
This Lensix check (servicebus_nocmk) identifies namespaces that have not been configured with a customer-managed key.
What this check detects
The check inspects each Azure Service Bus namespace and verifies whether encryption at rest is backed by a customer-managed key stored in Azure Key Vault. If the namespace uses the default Microsoft-managed key, the check fails.
Concretely, it looks at the namespace's encryption property. A namespace with CMK enabled exposes a keyVaultProperties block pointing at a specific key. A namespace without it returns null or a default keySource of Microsoft.ServiceBus.
Note: Customer-managed key encryption for Service Bus is only available on the Premium tier. Basic and Standard namespaces cannot use a CMK at all, so if a namespace must hold sensitive data under strict key custody rules, it needs to be Premium first.
Why it matters
Encryption at rest is on by default either way, so this is not about whether your data is encrypted. It is about who controls the key and what you can do with that control.
With a customer-managed key, you gain three capabilities that a platform-managed key does not give you:
- Revocation. If you suspect a key or namespace is compromised, you can disable or revoke the key in Key Vault and immediately cut off access to the encrypted data, including Microsoft's own access.
- Rotation on your schedule. You decide when keys rotate and can enforce rotation policies that match your compliance window rather than the platform default.
- Auditability. Every use of the key generates Key Vault audit logs, so you have a clear record of when and how the encryption key was accessed.
From a real-world risk angle, consider an incident response scenario. A workload identity gets compromised and an attacker gains read access to a Service Bus namespace carrying queued financial transactions. With a CMK, your IR team can revoke the key and freeze the data while you investigate. Without one, you have no key-level kill switch.
There is also a straightforward compliance driver. PCI DSS requirement 3 and several HIPAA safeguards expect organizations to control and document their cryptographic key management. "We let the cloud provider manage it" rarely satisfies an auditor who is reviewing controls over cardholder data or PHI.
Warning: CMK requires Premium tier, which is significantly more expensive than Standard. Premium is billed per messaging unit, so enabling CMK on a namespace that does not actually need it is a real cost increase, not a free toggle. Apply CMK where the data sensitivity justifies it.
How to fix it
Enabling a CMK has a few moving parts: a Key Vault with the right settings, a managed identity for the namespace, an access grant, and finally the encryption configuration on the namespace itself.
Step 1: Confirm the namespace is Premium
az servicebus namespace show \
--resource-group my-rg \
--name my-namespace \
--query "sku.tier" -o tsv
If this returns anything other than Premium, you cannot enable CMK without recreating the namespace at the Premium tier. There is no in-place upgrade from Standard to Premium.
Step 2: Prepare the Key Vault
The Key Vault holding your key must have soft delete and purge protection enabled. Service Bus refuses to bind a CMK to a vault without purge protection, because losing the key would make the data permanently unrecoverable.
# Create a vault with soft delete and purge protection, or update an existing one
az keyvault update \
--name my-keyvault \
--resource-group my-rg \
--enable-purge-protection true
# Create the encryption key
az keyvault key create \
--vault-name my-keyvault \
--name servicebus-cmk \
--protection software
Step 3: Give the namespace a managed identity
The namespace needs an identity that Key Vault can authorize. A system-assigned identity is the simplest choice.
az servicebus namespace identity assign \
--resource-group my-rg \
--name my-namespace \
--system-assigned
Step 4: Grant the identity access to the key
Grab the principal ID of the namespace identity, then grant it the permissions to wrap and unwrap the key.
PRINCIPAL_ID=$(az servicebus namespace show \
--resource-group my-rg \
--name my-namespace \
--query "identity.principalId" -o tsv)
az keyvault set-policy \
--name my-keyvault \
--object-id "$PRINCIPAL_ID" \
--key-permissions get wrapKey unwrapKey
Note: If your vault uses Azure RBAC for its permission model instead of access policies, assign the Key Vault Crypto Service Encryption User role to the principal instead of using set-policy.
Step 5: Enable encryption on the namespace
KEY_URI="https://my-keyvault.vault.azure.net/keys/servicebus-cmk"
az servicebus namespace encryption add \
--resource-group my-rg \
--namespace-name my-namespace \
--encryption-config \
key-name=servicebus-cmk \
key-vault-uri=https://my-keyvault.vault.azure.net \
key-version=""
Leaving key-version empty tells Service Bus to always use the latest version of the key, which means key rotation in Key Vault is picked up automatically without reconfiguring the namespace.
Verify the result
az servicebus namespace show \
--resource-group my-rg \
--name my-namespace \
--query "encryption" -o json
You should see a keySource of Microsoft.KeyVault and a keyVaultProperties array referencing your key.
Doing it in Terraform
If you manage infrastructure as code, configure the CMK directly on the namespace resource so it is enforced from day one.
resource "azurerm_servicebus_namespace" "main" {
name = "my-namespace"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
sku = "Premium"
capacity = 1
identity {
type = "SystemAssigned"
}
}
resource "azurerm_key_vault_access_policy" "sb" {
key_vault_id = azurerm_key_vault.main.id
tenant_id = azurerm_servicebus_namespace.main.identity[0].tenant_id
object_id = azurerm_servicebus_namespace.main.identity[0].principal_id
key_permissions = ["Get", "WrapKey", "UnwrapKey"]
}
resource "azurerm_servicebus_namespace_customer_managed_key" "main" {
namespace_id = azurerm_servicebus_namespace.main.id
key_vault_key_id = azurerm_key_vault_key.sb.id
infrastructure_encryption_enabled = true
depends_on = [azurerm_key_vault_access_policy.sb]
}
Tip: Set infrastructure_encryption_enabled = true to add a second layer of encryption (double encryption) underneath the CMK. It is a low-effort addition that satisfies stricter compliance baselines requiring defense in depth on data at rest.
How to prevent it from happening again
Fixing one namespace is easy. Stopping the next one from shipping without a CMK is the part that actually moves your security posture.
Enforce with Azure Policy
Azure provides a built-in policy that audits or denies Service Bus namespaces without a CMK. Assign it at the subscription or management group scope so it applies to everything, including resources created outside your IaC pipeline.
# Built-in: "Service Bus namespaces should use a customer-managed key for encryption"
az policy assignment create \
--name "sb-require-cmk" \
--scope "/subscriptions/<subscription-id>" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/295fc8b1-dc9f-4f53-9c61-3f313ceab40a" \
--params '{"effect": {"value": "Audit"}}'
Warning: Start the policy effect on Audit before switching to Deny. A Deny effect applied broadly can block legitimate Standard-tier namespaces that have no need for CMK, breaking deployments for teams that did nothing wrong. Audit first, scope deliberately, then tighten.
Gate it in CI/CD
Catch the misconfiguration before it reaches Azure. Run a policy-as-code scan against your Terraform plans in the pipeline so a namespace missing its CMK block fails the build.
# Example using Checkov against a Terraform plan
checkov -d ./infra --framework terraform \
--check CKV_AZURE_201
Pair this with Lensix continuous scanning so that drift, like someone toggling encryption off through the portal, is caught even when it bypasses your IaC entirely.
Best practices
- Reserve a dedicated key for Service Bus. Do not share one CMK across every service. A per-service or per-environment key makes revocation surgical instead of catastrophic.
- Always pin to the latest key version. Leave the key version unset so rotation in Key Vault flows through automatically and you do not end up with stale references.
- Set a rotation policy on the key. Define an automatic rotation interval in Key Vault that matches your compliance requirement rather than rotating manually and forgetting.
- Keep purge protection on. Without it, an accidental or malicious key deletion can render your message data permanently unreadable. This is non-negotiable for CMK.
- Log and alert on key access. Send Key Vault diagnostic logs to a Log Analytics workspace and alert on key disable or delete events, since those directly affect data availability.
- Use managed identities, not secrets. The namespace should authenticate to Key Vault through a managed identity. Never wire up a service principal secret for this.
Danger: Deleting or disabling the CMK in Key Vault makes the Service Bus namespace inaccessible, and any messages sitting at rest become unreadable until the key is restored. Never delete a key that is actively bound to a namespace. Confirm no namespace references the key before any cleanup.
Customer-managed keys are not free and they are not for every workload, but for any namespace carrying regulated or sensitive data, they turn encryption at rest from a checkbox into a control you actually own.

