Azure Key Vault | Access Policies Removed On Deployment


⚠️ NOTE

Microsoft guidance is clear that Azure RBAC should be used for data plane authorization moving forward, instead of legacy access policies


Problem Space

When multiple applications share a single Azure Key Vault, access policy management can become an unexpected source of deployment risk → and the root cause is easy to miss.

// BICEP
resource KeyVaultDeploy 'Microsoft.KeyVault/vaults@2025-05-01' = {
  name: ''
  location: ''
  properties: {
    ...
    accessPolicies: []
    ...
  }
}

The accessPolicies property on the Microsoft.KeyVault/vaults ARM resource is a required field. In a shared Key Vault scenario, where the vault is owned and deployed by one application, the natural thing to do is set this to an empty array as the application does not own the other applications access policies, so it does not declare them.

This is where the problem begins.

When ARM deploys the Key Vault resource with accessPolicies set to an empty array [], it treats that as the desired state for the vault. Any access policies that existed previously (including those belonging to other applications) are removed.

Here is how the failure pattern plays out in practice:

  1. Application A owns the Key Vault and deploys it with accessPolicies: [].
  2. Immediately after, Application A’s IaC deploys its own access policies via a separate step (for example, using the Microsoft.KeyVault/vaults/accessPolicies child resource). Access is restored for Application A without apparent issue.
  3. Application B’s access policies have been silently removed — it never re-deploys the key vault, only its own access policy step.
  4. Application B fails at runtime when attempting secret, key, or certificate operations — authorization errors with no obvious cause.
  5. Application B is re-deployed, its access policies are restored, and both applications work again — until the next time Application A’s pipeline runs.

This cycle repeats silently. Each Application A deployment is an outage for Application B, and the connection between the two is not obvious unless you know to look for it.

This can happen if you have the following setup:

  • Multiple applications or pipelines sharing a Key Vault
  • The Key Vault instance deployed as part of one application’s IaC
  • Access configured through Key Vault access policies
  • Each application’s pipeline independently managing only its own policy entries

Workarounds (Still Using Access Policies)

If moving to RBAC immediately is not possible, the following workarounds address the underlying coupling problem — but each comes with trade-offs.

1. Move the Key Vault to a Core Resources Deployment

Extract the Key Vault resource into a dedicated core infrastructure deployment, separate from any application pipeline. Application pipelines then only manage their own access policy entries against the pre-existing vault.

Benefits:

  • The vault is no longer redeployed as part of application changes
  • Eliminates the empty accessPolicies overwrite problem
  • Makes ownership of the shared resource explicit

Trade-off:

  • When the core resources deployment runs (for environment rebuilds, configuration changes, or disaster recovery), all dependent applications will need to be re-deployed afterwards to restore their access policy entries. This creates an operational dependency that must be planned for and communicated clearly across teams.

2. Provision a Separate Key Vault Per Application

Give each application its own dedicated Key Vault, eliminating the shared resource entirely.

Benefits:

  • No cross-application policy coupling — each key vault is fully owned by one application
  • Reduces blast radius of deployment mistakes
  • Cleaner isolation and tenancy boundaries

Trade-offs:

  • More key vaults to provision, monitor, rotate secrets in, and govern
  • Increases operational overhead for certificate and secret lifecycle management
  • Harder to get a unified view of secrets across the estate

This option improves isolation but does not solve the root-cause pattern; it just limits the blast radius per key vault.

The Real Solution: Move to Azure RBAC

The correct long-term fix is to stop using access policies for Key Vault data plane authorization entirely and adopt Azure RBAC role assignments.

With RBAC:

  • Role assignments are additive and independently managed — assigning a role for Application B does not affect Application A’s assignments
  • Authorization state is managed through Azure’s centralized RBAC model, consistent with the rest of the Azure platform
  • Microsoft explicitly recommends RBAC over access policies for new and migrating workloads

The deployment pattern becomes:

  1. Deploy the Key Vault resource. The accessPolicies field becomes irrelevant.
  2. Each application independently deploys Microsoft.Authorization/roleAssignments scoped to the vault for its own managed identity or service principal.
  3. An application deployment wont affect another application’s authorization.
  4. A redeploy of the Key Vault resource won’t remove existing application’s authorizations.

Practical migration approach:

  1. Enable the RBAC permission model on the Key Vault IaC (enableRbacAuthorization: true).
  2. Map existing access policy permissions to the appropriate built-in Key Vault RBAC roles (for example Key Vault Secrets User, Key Vault Certificates User).
    • Assign roles to the required identities at the appropriate scope (Key Vault, Key Vault Secret/Certificate).
  3. Remove legacy access policy configuration from all IaC templates.
  4. Deploy IaC and Validate application behavior against the new authorization model.

Useful Microsoft documentation:

Closing Thoughts

The empty accessPolicies: [] pattern is easy to arrive at — the field is required, the application does not own the other policies, so an empty array seems reasonable. In a single-application setup it causes no problems. In a shared-vault, multi-application setup it causes silent, repeating outages that are hard to diagnose without knowing where to look.

The workarounds described here reduce the risk while a migration is planned, but neither fully resolves the underlying problem.

The right answer is Azure RBAC. Role assignments are independent, additive, and do not interfere with each other across application boundaries. Moving to RBAC removes this class of problem entirely.

For the original version of this post see Andrew Wilson's personal blog at Azure Key Vault | Access Policies Removed On Deployment