Cyber Intelligence
Cloud Security17 min read

Azure Key Vault Best Practices 2026: Access Policies, RBAC, and Rotation

Most teams configured Key Vault with access policies in 2019-2021 and never revisited. RBAC became the default authorization model in 2021 and the gap between those legacy configurations and current security requirements is now a real audit finding. This guide covers the migration, rotation automation, network hardening, and detection queries that close it.

I
Microsoft Cloud Solution Architect
Azure Key VaultRBACSecret RotationAzure SecurityZero TrustPrivate EndpointMicrosoft SentinelKQLBicep

The Access Policy Sprawl That Is Probably in Your Tenant Right Now

Run this query against your tenant and count the results:

az keyvault list --query "[].{name:name, enableRbacAuthorization:properties.enableRbacAuthorization}" \
  --output table

If more than a third of your Key Vaults show enableRbacAuthorization: false or null, you are looking at a configuration gap that dates to before 2021. That is when Microsoft changed the default authorization model for new Key Vaults to RBAC. Before that, access policies were the only option, and every vault provisioned through 2020 still uses them unless someone deliberately migrated.

The practical consequence: access policies have no conditional access integration, no Privileged Identity Management (PIM) eligibility, no conditions-based scoping, and no deny assignments. A service principal granted Get and List on secrets through an access policy will retain that access permanently, even if the principal is compromised, until someone manually removes the policy entry. There is no time-bound activation, no MFA step-up trigger, and no session condition you can attach.

In a post-incident review of a 2024 Azure tenant compromise, the attack chain relied on a rotated service principal credential that retained Key Vault access policy permissions for 11 days after the rotation because the access policy referenced the object ID directly and was never updated. The policy should have been removed; it was not. RBAC with managed identities would have made that entire attack chain impossible.

This article covers the migration from access policies to RBAC, how to configure automatic secret rotation with Event Grid and Azure Functions, the network controls that matter (and the common misconfiguration that negates them), KQL detection queries for Key Vault anomaly monitoring, and the soft delete and purge protection configuration that turns Key Vault into a recoverable system rather than a single point of deletion.

---

Access Policies vs RBAC: What Actually Changed

Access policies and RBAC both control who can read and write Key Vault objects, but they operate at fundamentally different abstraction levels.

DimensionAccess PoliciesAzure RBAC
Scope granularityVault-level onlyManagement group, subscription, resource group, vault, or individual secret/key/certificate
PIM integrationNoneFull eligibility and time-bound activation
Conditional AccessNot supportedSupported via Entra ID Conditional Access
Deny assignmentsNot supportedSupported
Secret-level permissionsNot supported (vault-level only)Supported with Key Vault Secrets User scoped to a specific secret ID
Audit trailAzure Activity Log (coarse)Azure Activity Log + RBAC change events
Maximum entries1024 per vaultStandard Azure RBAC limits (2000 per scope, 500 deny assignments)
Object type targetedObject ID of principalRole assignment to principal; role defines permissions
The 1024 access policy limit per vault is a hard constraint that most teams only discover when automation hits it. Vaults used by large CI/CD environments accumulate access policies for every service principal ever granted access, including pipelines for decommissioned projects. RBAC does not have this problem in the same way, but it does require that you clean up role assignments actively.

The deeper architectural difference is control plane vs data plane authorization. With access policies, a principal that has Contributor on the vault resource can modify access policies, which means they can grant themselves data plane access without going through RBAC role assignment. With --enable-rbac-authorization true, control plane and data plane are separated: Contributor can manage vault configuration but cannot assign roles or access secrets unless explicitly granted Key Vault Secrets Officer or higher.

This separation is the primary reason to migrate. It is not a cosmetic change.

The Specific Risk with Access Policy Vaults

When enableRbacAuthorization is false, an attacker who compromises a principal with Contributor on the resource group can call az keyvault set-policy to grant themselves --secret-permissions get list and then read every secret in the vault. The operation appears in the Activity Log as a routine policy change, not as a privilege escalation, and it will not trigger alerts scoped to RBAC role assignment events.

With RBAC authorization enabled, the same attacker would need to call az role assignment create with the Key Vault Secrets User role. That action requires Microsoft.Authorization/roleAssignments/write at the vault scope, which Contributor does not have. The privilege escalation path is blocked by the Azure authorization model itself, not by a detection rule.

---

RBAC Migration: The Correct Sequence

Migrating a production vault from access policies to RBAC without causing an outage requires following the right sequence. Flipping the flag first and creating role assignments second will cause an access gap.

Step 1: Inventory Existing Access Policies

# Export current access policies to a file before migration
az keyvault show --name <vault-name> --resource-group <rg-name> \
  --query "properties.accessPolicies" \
  --output json > access-policies-backup.json

Review the output. For each entry, identify:

  • The objectId and what principal it maps to (az ad sp show --id or az ad user show --id )
  • The exact permissions granted (separate lists for keys, secrets, certificates)
  • Whether the principal is still active and the permission is still needed

Step 2: Create Equivalent RBAC Role Assignments

Map access policy permission sets to RBAC roles before touching the vault configuration:

Access Policy PermissionsEquivalent RBAC Role
get, list on secretsKey Vault Secrets User
get, list, set, delete on secretsKey Vault Secrets Officer
get, list on keysKey Vault Crypto User
get, list, sign, verify, wrapKey, unwrapKey on keysKey Vault Crypto Service Encryption User
get, list, set, delete, backup, restore, recover, purge on keysKey Vault Crypto Officer
Full access to all object typesKey Vault Administrator
Management operations onlyKey Vault Contributor (control plane only, no data access)
Create the role assignments at the appropriate scope. Where possible, scope to an individual secret rather than the vault to follow least privilege:
# Scope a role assignment to an individual secret
VAULT_ID=$(az keyvault show --name <vault-name> --resource-group <rg-name> --query id -o tsv)
SECRET_ID="$VAULT_ID/secrets/<secret-name>"

az role assignment create \ --role "Key Vault Secrets User" \ --assignee <object-id-or-principal-id> \ --scope "$SECRET_ID"

# Vault-level assignment (for principals that need broad access) az role assignment create \ --role "Key Vault Secrets Officer" \ --assignee <object-id-or-principal-id> \ --scope "$VAULT_ID"

Step 3: Enable RBAC Authorization

Only after all role assignments are in place:

az keyvault update \
  --name <vault-name> \
  --resource-group <rg-name> \
  --enable-rbac-authorization true

This is the point of no return. Once RBAC authorization is enabled, access policies are ignored for data plane operations. Any principal not yet covered by a role assignment will immediately lose access.

The Gotcha: Legacy Access Policies Are Not Deleted

Enabling RBAC authorization does not delete the existing access policies. They remain stored on the vault resource but are no longer evaluated. If you later disable RBAC authorization (reverting the flag), the old access policies become active again immediately. This creates a latent risk: if someone disables RBAC authorization during troubleshooting, dormant access policies that were never cleaned up will re-activate.

Clean up legacy access policies after confirming the RBAC migration is stable:

# Remove all access policies after RBAC migration is verified
az keyvault update \
  --name <vault-name> \
  --resource-group <rg-name> \
  --remove-all-policies

Bicep Configuration for New Vaults

For new vaults, enforce RBAC authorization in your Bicep templates from day one. Never provision a vault without it:

param vaultName string
param location string = resourceGroup().location
param tenantId string = subscription().tenantId

resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = { name: vaultName location: location properties: { sku: { family: 'A' name: 'standard' } tenantId: tenantId enableRbacAuthorization: true // RBAC authorization (not access policies) enableSoftDelete: true softDeleteRetentionInDays: 90 // 90 days for regulated workloads enablePurgeProtection: true // Prevent permanent deletion during retention period publicNetworkAccess: 'Disabled' // Private endpoint only networkAcls: { defaultAction: 'Deny' bypass: 'AzureServices' ipRules: [] virtualNetworkRules: [] } } }

// Assign Key Vault Secrets User to a managed identity param secretsReaderPrincipalId string

resource secretsUserAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(keyVault.id, secretsReaderPrincipalId, 'Key Vault Secrets User') scope: keyVault properties: { roleDefinitionId: subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6' // Key Vault Secrets User ) principalId: secretsReaderPrincipalId principalType: 'ServicePrincipal' } }

For non-human identities accessing Key Vault secrets, see the NHI security guide for the managed identity vs workload identity federation decision and the federated credentials guide for GitHub Actions and Terraform patterns.

---

Secret Rotation: Event Grid and Azure Functions Pattern

Manual secret rotation is not a rotation strategy. It is a policy document that gets ignored. Automatic rotation requires two things: a trigger when secrets are approaching expiration, and a function that performs the rotation and updates the vault.

Azure Key Vault emits an Microsoft.KeyVault.SecretNearExpiry event to Event Grid when a secret's expiration is within 30 days. The exact event schema:

{
  "id": "00000000-0000-0000-0000-000000000000",
  "topic": "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault>",
  "subject": "<secret-name>",
  "eventType": "Microsoft.KeyVault.SecretNearExpiry",
  "eventTime": "2026-05-01T00:00:00.0000000Z",
  "data": {
    "Id": "https://<vault>.vault.azure.net/secrets/<secret-name>/<version>",
    "VaultName": "<vault>",
    "ObjectType": "Secret",
    "ObjectName": "<secret-name>",
    "Version": "<version>",
    "NBF": null,
    "EXP": 1777000000
  },
  "dataVersion": "1",
  "metadataVersion": "1"
}

Configure the rotation policy on the secret itself so Key Vault generates expiry events automatically:

# Set a rotation policy on a secret (expires in 90 days, notify at 30 days before expiry)
az keyvault secret set-attributes \
  --vault-name <vault-name> \
  --name <secret-name> \
  --expires "$(date -u -d '+90 days' '+%Y-%m-%dT%H:%M:%SZ')"

# Configure the rotation policy for automatic event generation az keyvault secret rotation-policy update \ --vault-name <vault-name> \ --name <secret-name> \ --value '{ "lifetimeActions": [ { "trigger": { "timeBeforeExpiry": "P30D" }, "action": { "type": "Notify" } }, { "trigger": { "timeBeforeExpiry": "P7D" }, "action": { "type": "Notify" } } ], "attributes": { "expiryTime": "P90D" } }'

The Notify action type triggers the Event Grid event. The Rotate action type (available for Key Vault-managed certificate and key rotation) triggers automatic rotation within Key Vault itself. For secrets backed by external systems (database passwords, API keys, storage account keys), you must use the Notify type and handle the actual rotation logic in an external function.

Azure Function Rotation Handler

Wire an Event Grid-triggered Azure Function to the SecretNearExpiry event. The function pattern:

  1. Receive the Event Grid event for the expiring secret
  2. Generate a new credential at the source system (SQL, storage, third-party API)
  3. Store the new credential as a new version in Key Vault
  4. Update the consuming application's reference if it uses secret versions explicitly (or rely on the latest-version reference)
  5. Invalidate the old credential at the source system after a grace period

The Event Grid subscription that routes SecretNearExpiry events to the function:

# Create Event Grid subscription routing SecretNearExpiry to an Azure Function
az eventgrid event-subscription create \
  --name "secret-rotation-trigger" \
  --source-resource-id "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault>" \
  --endpoint-type azurefunction \
  --endpoint "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/sites/<function-app>/functions/<function-name>" \
  --included-event-types "Microsoft.KeyVault.SecretNearExpiry" \
  --event-delivery-schema EventGridSchema \
  --deadletter-endpoint "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<sa>/blobServices/default/containers/deadletter"

Always configure a dead-letter endpoint. A rotation function that silently fails is worse than no rotation, because the secret expires without anyone noticing. The dead-letter container gives you a durable record of failed rotation events that Sentinel can alert on.

Grant the Azure Function's managed identity the Key Vault Secrets Officer role on the vault (to write new secret versions) and the Key Vault Secrets User role on the specific secret (to read the current version). Never grant Key Vault Administrator to a rotation function.

---

Network Controls: Private Endpoint and the Trusted Services Trap

Private Endpoint for Key Vault

Every production Key Vault should have public network access disabled and a private endpoint deployed. The CLI sequence:

# Disable public network access on an existing vault
az keyvault update \
  --name <vault-name> \
  --resource-group <rg-name> \
  --public-network-access Disabled \
  --default-action Deny \
  --bypass AzureServices

# Create private endpoint az network private-endpoint create \ --name "pe-<vault-name>" \ --resource-group <rg-name> \ --vnet-name <vnet-name> \ --subnet <subnet-name> \ --private-connection-resource-id $(az keyvault show --name <vault-name> --resource-group <rg-name> --query id -o tsv) \ --group-id vault \ --connection-name "conn-<vault-name>"

# Create DNS zone for private endpoint resolution az network private-dns zone create \ --resource-group <rg-name> \ --name "privatelink.vaultcore.azure.net"

az network private-dns link vnet create \ --resource-group <rg-name> \ --zone-name "privatelink.vaultcore.azure.net" \ --name "dns-link-<vnet-name>" \ --virtual-network <vnet-name> \ --registration-enabled false

az network private-endpoint dns-zone-group create \ --resource-group <rg-name> \ --endpoint-name "pe-<vault-name>" \ --name "dns-zone-group" \ --private-dns-zone "privatelink.vaultcore.azure.net" \ --zone-name "vault"

Private endpoint resolution requires that clients in the VNet use the Azure-provided DNS or a DNS forwarder that resolves privatelink.vaultcore.azure.net. If your VNet uses a custom DNS server that does not forward to Azure DNS, Key Vault calls from resources in the VNet will resolve to the public IP and be blocked by the firewall, producing a 403 Forbidden from a resource that appears to be correctly configured.

The --bypass AzureServices Trap

The --bypass AzureServices flag (or bypass: 'AzureServices' in Bicep) is widely misunderstood. It does not mean "allow all Azure services." It means "allow Azure trusted services" which is a specific, documented list. That list includes Azure Backup, Azure Site Recovery, Azure Event Grid, and a few others. It does not include Azure Functions, Azure Kubernetes Service, Azure Container Instances, App Service, or most of the services you are probably deploying.

The implication: setting --bypass AzureServices and --default-action Deny does not mean your function app can reach the vault over the public endpoint. It means the vault is locked down except for a narrow set of Microsoft infrastructure services. Your function app needs to either be in the same VNet as the private endpoint (via VNet integration) or be granted access through an explicit IP rule.

The common mistake is deploying a function app, enabling the Key Vault firewall, setting --bypass AzureServices, and expecting it to work. It will not. The function app will receive 403 on every Key Vault API call. The fix is to enable VNet integration on the function app and route its outbound traffic through the VNet containing the private endpoint.

For Azure DevOps pipelines and GitHub Actions workflows that need to access a firewall-protected vault during deployments, use a self-hosted agent or runner on a VNet with a private endpoint rather than opening the vault's public IP rules to Microsoft-hosted agent IP ranges (which rotate frequently and are a maintenance burden).

---

Monitoring and Detection: KQL Queries for Key Vault Anomalies

Key Vault diagnostic logs must be routed to a Log Analytics workspace. Enable the AuditEvent log category and the AllMetrics category on every vault:

az monitor diagnostic-settings create \
  --name "kv-diagnostics" \
  --resource $(az keyvault show --name <vault-name> --resource-group <rg-name> --query id -o tsv) \
  --workspace <log-analytics-workspace-id> \
  --logs '[{"category":"AuditEvent","enabled":true,"retentionPolicy":{"days":90,"enabled":true}}]' \
  --metrics '[{"category":"AllMetrics","enabled":true,"retentionPolicy":{"days":30,"enabled":true}}]'

With diagnostic logs flowing, these KQL queries cover the primary detection use cases in Microsoft Sentinel or any Log Analytics-backed SIEM.

Detect High-Volume Secret Access (Exfiltration Pattern)

AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName == "SecretGet"
| where ResultType == "Success"
| summarize SecretAccessCount = count(), SecretNames = make_set(id_s) by CallerIPAddress, identity_claim_oid_g, bin(TimeGenerated, 1h)
| where SecretAccessCount > 50
| project TimeGenerated, CallerIPAddress, PrincipalObjectId = identity_claim_oid_g, SecretAccessCount, SecretNames
| order by SecretAccessCount desc

This query surfaces any principal that reads more than 50 secrets in a single hour window, which is the primary indicator of programmatic bulk exfiltration. Tune the threshold to your environment: a secret scanning or rotation function may legitimately read many secrets, but should be identified and excluded by principal object ID rather than by raising the threshold globally.

Detect Access Policy or RBAC Changes

AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName in ("VaultPatch", "VaultPut", "VaultAccessPoliciesSet")
| where ResultType == "Success"
| extend ChangedBy = identity_claim_unique_name_s
| extend VaultName = Resource
| project TimeGenerated, VaultName, OperationName, ChangedBy, CallerIPAddress, requestUri_s
| order by TimeGenerated desc

This surfaces control plane changes to vault configuration. Combine it with an alert rule that fires whenever VaultAccessPoliciesSet appears outside of a change window, which catches unauthorized access policy modifications even on vaults that have not yet migrated to RBAC.

Detect Authentication Failures (Possible Credential Stuffing or Misconfiguration)

AzureDiagnostics
| where ResourceType == "VAULTS"
| where ResultType != "Success"
| where OperationName in ("SecretGet", "SecretList", "KeyDecrypt", "KeySign")
| summarize FailureCount = count(), ErrorCodes = make_set(ResultSignature) by CallerIPAddress, identity_claim_oid_g, bin(TimeGenerated, 15m)
| where FailureCount > 10
| project TimeGenerated, CallerIPAddress, PrincipalObjectId = identity_claim_oid_g, FailureCount, ErrorCodes
| order by FailureCount desc

A spike in Forbidden errors from a specific principal often indicates a service principal whose access was removed but whose consuming application was not updated. A spike from multiple principals often indicates a misconfigured network change (the private endpoint DNS issue described above) or a certificate expiration on a managed identity.

Detect Soft Delete or Purge Operations

AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName in ("SecretDelete", "SecretPurge", "KeyDelete", "KeyPurge", "VaultDelete")
| project TimeGenerated, OperationName, Resource, identity_claim_unique_name_s, CallerIPAddress, ResultType
| order by TimeGenerated desc

Alert on any Purge operation unconditionally. Purge operations permanently destroy objects and bypass soft delete recovery. In environments with purge protection enabled, purge operations will return Conflict errors, but the attempt itself is still worth alerting on as it indicates either an authorized operator making a mistake or an attacker attempting irreversible damage.

For a broader CSPM view of Key Vault configuration across your tenant, see the CSPM tools comparison for how Defender for Cloud, Wiz, and Orca surface Key Vault misconfiguration findings.

---

Soft Delete and Purge Protection: Compliance Requirements

Both enableSoftDelete and enablePurgeProtection are now required by most compliance frameworks for any vault storing regulated data. As of February 1, 2025, Microsoft enforces soft delete on all new Key Vaults automatically and cannot be disabled on existing vaults that were created after that date. However, purge protection remains opt-in and is not enforced by the platform.

What These Controls Actually Do

Soft delete retains deleted vault objects (secrets, keys, certificates) and the vault itself in a recoverable state for a configurable retention period. The minimum retention period is 7 days; the maximum is 90 days. For PCI DSS and SOC 2 Type II environments, configure 90 days explicitly:
az keyvault update \
  --name <vault-name> \
  --resource-group <rg-name> \
  --enable-soft-delete true \
  --retention-days 90
Purge protection prevents permanent deletion of soft-deleted objects and the vault itself until the retention period expires. Without purge protection, an operator or attacker can call the purge API to permanently destroy a soft-deleted secret immediately, bypassing the retention period entirely. With purge protection enabled, that call returns:
(Conflict) The vault 'vault-name' has purge protection enabled and cannot be deleted.

Enable purge protection on every vault that holds production secrets:

az keyvault update \
  --name <vault-name> \
  --resource-group <rg-name> \
  --enable-purge-protection true

Purge protection, once enabled, cannot be disabled. This is intentional: allowing it to be disabled would allow an attacker with sufficient permissions to disable it and then purge secrets before the retention period expires.

Recovery Procedure

When a secret or vault needs to be recovered from the soft-deleted state:

# List soft-deleted secrets in a vault
az keyvault secret list-deleted \
  --vault-name <vault-name> \
  --output table

# Recover a specific soft-deleted secret az keyvault secret recover \ --vault-name <vault-name> \ --name <secret-name>

# List soft-deleted vaults in a subscription az keyvault list-deleted \ --output table

# Recover a soft-deleted vault az keyvault recover \ --name <vault-name> \ --resource-group <rg-name> \ --location <region>

Recovery restores the object with its original properties and all versions. The recovered secret is immediately accessible to principals with the appropriate RBAC role.

One operational consideration: if you delete a vault and then try to create a new vault with the same name, the creation will fail with (Conflict) Vault name is already taken until either the soft-delete retention period expires or you explicitly purge the deleted vault. In environments where vault names are generated by Bicep using a consistent naming convention, this conflict is a common cause of deployment failures after a teardown.

---

Azure Policy for Continuous Compliance

Point-in-time hardening is not sufficient. Enforce Key Vault configuration with Azure Policy so that deviations are caught at deployment time rather than during the next audit cycle.

The built-in policy initiatives relevant to Key Vault:

Policy IDDisplay NameEffect
55615ac9-af46-4a59-874e-391cc3dfb490Key vaults should have soft delete enabledAudit / Deny
a27a6a49-20d4-4b08-bb84-e3d562eed4c6Key vaults should have purge protection enabledAudit / Deny
55f3eceb-5573-4f18-99ec-4a4924a8a5f8Key Vault should use RBAC permission modelAudit / Deny
ac673a9a-f77d-4846-b2d8-a57f8e1c01dcKey vaults should have firewall enabledAudit / Deny
8b0f9a6a-3dff-4c16-bb73-2da9e60d3a31Private endpoint should be configured for Key VaultAudit / Deny
Apply these in Deny mode on production subscriptions. This prevents any Key Vault from being deployed without the required configuration, which eliminates the drift that created the current backlog of misconfigured vaults.
# Assign the Key Vault RBAC policy in Deny mode at subscription scope
az policy assignment create \
  --name "deny-kv-without-rbac" \
  --display-name "Deny Key Vault without RBAC authorization" \
  --policy "55f3eceb-5573-4f18-99ec-4a4924a8a5f8" \
  --scope "/subscriptions/<subscription-id>" \
  --params '{"effect": {"value": "Deny"}}' \
  --enforcement-mode Default

For existing non-compliant vaults, the policy will show Audit findings but will not block operations on the vault itself. Remediation of existing vaults requires the manual migration steps described in the RBAC migration section above.

---

Hardening Checklist

Apply each item to every Key Vault in production. For vaults identified by the initial audit query as still using access policies, the RBAC migration steps are the priority.

  • [ ] RBAC authorization enabled (enableRbacAuthorization: true) on all vaults; access policies not in use
  • [ ] Legacy access policies removed after RBAC migration (az keyvault update --remove-all-policies)
  • [ ] All secrets have expiration dates configured; no secrets with expires: null
  • [ ] Rotation policy configured on all secrets with timeBeforeExpiry: P30D notification trigger
  • [ ] Event Grid subscription routing SecretNearExpiry events to a rotation function with dead-letter endpoint configured
  • [ ] Managed identities used for all application and service access; no service principals with client secrets for Key Vault authentication
  • [ ] publicNetworkAccess: Disabled on all production vaults
  • [ ] Private endpoint deployed with correct DNS zone (privatelink.vaultcore.azure.net) and VNet link
  • [ ] --bypass AzureServices configured correctly; no VNet rules or IP rules used as a substitute for private endpoint
  • [ ] Diagnostic logs (AuditEvent category) routed to Log Analytics workspace with 90-day retention
  • [ ] Sentinel alert rules active for: high-volume secret access, access policy changes, purge operations, and bulk authentication failures
  • [ ] enableSoftDelete: true with softDeleteRetentionInDays: 90 on all vaults
  • [ ] enablePurgeProtection: true on all vaults holding production secrets
  • [ ] Azure Policy assignments in Deny mode enforcing RBAC, soft delete, purge protection, and firewall on new vault deployments
  • [ ] PIM eligibility configured for Key Vault Administrator role; no standing assignments for privileged roles
  • [ ] Key Vault access reviewed in quarterly access review campaigns in Entra ID Identity Governance
N

Recommended tool: Nordpass

Up to 40% commission

Get weekly security insights

Cloud security, zero trust, and identity guides — straight to your inbox.

I

Microsoft Cloud Solution Architect

Cloud Solution Architect with deep expertise in Microsoft Azure and a strong background in systems and IT infrastructure. Passionate about cloud technologies, security best practices, and helping organizations modernize their infrastructure.

Share this article

Questions & Answers

Related Articles

Need Help with Your Security?

Our team of security experts can help you implement the strategies discussed in this article.

Contact Us