Back to blog
AzureBest PracticesCloud SecurityMonitoring & LoggingOperations & Compliance

Key Vault Has No Diagnostic Settings: Why It Matters and How to Fix It

Learn why an Azure Key Vault without diagnostic settings is a blind spot, and how to enable AuditEvent logging with CLI, Terraform, and Azure Policy.

TL;DR

This check flags any Azure Key Vault that has no diagnostic settings configured, which means access to your secrets, keys, and certificates is not being logged. Without those logs you have no audit trail during an incident. Fix it by routing the AuditEvent and AllMetrics categories to a Log Analytics workspace or storage account.

Azure Key Vault is where a lot of your most sensitive material lives: TLS certificates, database connection strings, API keys, encryption keys for storage and disks. It is also one of the first places an attacker goes once they have a foothold. If a Key Vault has no diagnostic settings, every read, write, and delete against those secrets happens silently. You will not know who pulled a certificate, when, or from where.

The keyvault_nodiagnostics check catches exactly that gap: a vault that is not emitting its audit and metrics data anywhere.


What this check detects

Lensix inspects each Azure Key Vault in scope and looks at its diagnostic settings. A vault passes when at least one diagnostic setting is configured that ships log data to a destination. It fails when the diagnostic settings collection is empty.

Diagnostic settings are the mechanism Azure uses to export a resource's logs and metrics to one of three places:

  • A Log Analytics workspace (for querying with KQL and alerting)
  • An Azure Storage account (for cheap long-term retention)
  • An Event Hub (for streaming to a SIEM like Sentinel, Splunk, or Datadog)

For Key Vault, the most important category is AuditEvent. It records every authenticated operation against the vault: secret reads, key wraps and unwraps, certificate retrievals, policy changes, and more. There is also a newer AzurePolicyEvaluationDetails category and an AllMetrics bucket for performance data.

Note: Key Vault has its own audit logging through diagnostic settings, separate from the Azure Activity Log. The Activity Log only captures control-plane operations like "vault created" or "access policy changed." It does not record data-plane access such as "secret X was read." That data-plane visibility is exactly what diagnostic settings give you.


Why it matters

The whole point of a Key Vault is to centralize secrets so they are not scattered across config files and environment variables. That centralization is a security win, but it also makes the vault a high-value target. If logging is off, three things go wrong.

You cannot investigate an incident

Say a developer's credentials get phished and the attacker enumerates your subscription. They find a Key Vault, request access, and start pulling secrets. Months later you discover a leaked database. The first question your incident response team asks is: which secrets were accessed, and when? Without AuditEvent logs, that question has no answer. You are forced to assume every secret in the vault is compromised and rotate all of them, which can mean hours of downtime across many services.

You miss the early warning signs

With logs flowing into Log Analytics, you can alert on anomalies: a spike in SecretGet calls, access from an unexpected service principal, or a sudden batch of certificate exports. No logs means no alerts, so the first sign of trouble is usually the breach itself.

You fail your audits

Most compliance frameworks expect audit trails on systems that hold cryptographic material. PCI DSS, SOC 2, ISO 27001, and HIPAA all have controls that map to logging access to sensitive data. An auditor who finds a Key Vault with no diagnostic settings will write it up, and rightly so.

Warning: Diagnostic logs are not retroactive. If you turn them on today, you will not get any history for access that happened yesterday. This is why the check matters before an incident, not after.


How to fix it

You need to create a diagnostic setting on the vault that sends, at minimum, the AuditEvent logs to a destination. A Log Analytics workspace is the most useful target because it supports KQL queries and alerting. Below are three ways to do it.

Option 1: Azure Portal

  1. Open the Key Vault in the Azure Portal.
  2. Under Monitoring, select Diagnostic settings.
  3. Click Add diagnostic setting.
  4. Give it a name like kv-audit-to-loganalytics.
  5. Under Logs, check audit (or select allLogs) and AllMetrics.
  6. Under Destination details, tick Send to Log Analytics workspace and pick your workspace.
  7. Click Save.

Option 2: Azure CLI

First grab the resource ID of the vault and your target workspace, then create the setting.

VAULT_ID=$(az keyvault show \
  --name my-keyvault \
  --query id -o tsv)

WORKSPACE_ID=$(az monitor log-analytics workspace show \
  --resource-group monitoring-rg \
  --workspace-name central-logs \
  --query id -o tsv)

az monitor diagnostic-settings create \
  --name kv-audit-to-loganalytics \
  --resource "$VAULT_ID" \
  --workspace "$WORKSPACE_ID" \
  --logs '[{"category":"AuditEvent","enabled":true},{"category":"AzurePolicyEvaluationDetails","enabled":true}]' \
  --metrics '[{"category":"AllMetrics","enabled":true}]'

If you would rather keep logs cheaply in a storage account for long retention, swap the workspace flag for a storage account:

STORAGE_ID=$(az storage account show \
  --name kvauditlogs \
  --resource-group monitoring-rg \
  --query id -o tsv)

az monitor diagnostic-settings create \
  --name kv-audit-to-storage \
  --resource "$VAULT_ID" \
  --storage-account "$STORAGE_ID" \
  --logs '[{"category":"AuditEvent","enabled":true}]'

Tip: You can send to a workspace, a storage account, and an event hub all at once by adding them to a single diagnostic setting, or by creating multiple settings. A common pattern is Log Analytics for 30 to 90 days of hot queryable data, plus a storage account with a lifecycle policy for cheap multi-year retention to satisfy compliance.

Option 3: Terraform

If you manage infrastructure as code, define the diagnostic setting alongside the vault so it can never drift out of existence.

resource "azurerm_monitor_diagnostic_setting" "kv_audit" {
  name                       = "kv-audit-to-loganalytics"
  target_resource_id         = azurerm_key_vault.main.id
  log_analytics_workspace_id = azurerm_log_analytics_workspace.central.id

  enabled_log {
    category = "AuditEvent"
  }

  enabled_log {
    category = "AzurePolicyEvaluationDetails"
  }

  metric {
    category = "AllMetrics"
  }
}

And the Bicep equivalent for teams on ARM-native tooling:

resource kvDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'kv-audit-to-loganalytics'
  scope: keyVault
  properties: {
    workspaceId: logAnalyticsWorkspace.id
    logs: [
      {
        category: 'AuditEvent'
        enabled: true
      }
    ]
    metrics: [
      {
        category: 'AllMetrics'
        enabled: true
      }
    ]
  }
}

How to prevent it from happening again

Fixing one vault by hand is fine. The real goal is making sure the next vault someone spins up gets logging automatically. The cleanest way is Azure Policy, specifically a DeployIfNotExists policy that creates the diagnostic setting whenever a vault appears without one.

Azure ships a built-in policy for this. Assign the definition named "Configure diagnostic settings for Azure Key Vaults to Log Analytics workspace" at the subscription or management group level. You can do it from the CLI:

az policy assignment create \
  --name kv-diag-autodeploy \
  --display-name "Auto-deploy Key Vault diagnostics" \
  --policy "951af2fa-529b-416e-ab6e-066fd85ac459" \
  --scope "/subscriptions/" \
  --location eastus \
  --mi-system-assigned \
  --role "Contributor" \
  --params '{"logAnalytics":{"value":"/subscriptions//resourceGroups/monitoring-rg/providers/Microsoft.OperationalInsights/workspaces/central-logs"}}'

Warning: A DeployIfNotExists policy needs a managed identity with permission to write diagnostic settings and to write to the target workspace. The --mi-system-assigned flag creates that identity, but you still need to confirm it has the right role assignments, or the remediation task will fail silently. Run a remediation task after assignment to cover existing vaults.

Gate it in CI/CD

For teams using Terraform or Bicep, add a check to your pipeline that fails the build when a Key Vault resource has no associated diagnostic setting. With Open Policy Agent and Conftest you can write a rule against the plan output, or use checkov, which already has a relevant policy:

checkov -d ./infra --check CKV_AZURE_111

Tip: Combine both layers. Use CI/CD checks to catch issues before merge, and Azure Policy as the safety net for anything created outside your pipelines, such as a vault someone clicks together in the portal during an outage.


Best practices

  • Always enable AuditEvent. It is the category that records data-plane access. Everything else is secondary.
  • Centralize logs. Send every vault's diagnostics to a small number of shared workspaces rather than one workspace per vault. It makes cross-vault queries and alerting far easier.
  • Set retention deliberately. Log Analytics retention defaults can be short. Decide how long you need queryable data, and archive the rest to storage with a lifecycle policy.
  • Alert on suspicious patterns. Once logs flow into Log Analytics, build alerts for unusual access. A simple KQL starting point:
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.KEYVAULT"
| where OperationName in ("SecretGet", "CertificateGet", "KeyGet")
| summarize count() by CallerIPAddress, identity_claim_appid_g, bin(TimeGenerated, 1h)
| where count_ > 100
  • Pair logging with least privilege. Diagnostics tell you who accessed what, but tight RBAC and access policies limit who can in the first place. Use Azure RBAC for Key Vault rather than legacy access policies where you can.
  • Treat the logging config as code. A diagnostic setting created by hand can be deleted by hand. One defined in Terraform or enforced by policy comes back.

Note: If you have hundreds of vaults across many subscriptions, fixing them one at a time is not realistic. Use the Azure Policy approach with a remediation task to bring everything into compliance at once, then let Lensix confirm the gap is closed across your estate.

Logging on a Key Vault is one of those controls that costs almost nothing to turn on and saves you enormous pain the day something goes wrong. If this check is failing, it is a quick fix, and well worth doing before you need the logs rather than after.