Every Thursday I post SC-500 practice questions. Every Saturday, from this week, I take one exam topic and go deep: the real problem, how it works, the fix, and the exam traps. Week 1: who can really read the secrets in Azure Key Vault.
Lab story, lab names only (contoso.com). Screens are drawings, numbers are invented.
The problem: a "deploy-only" account that read 41 secrets
In my lab, Contoso gave a contractor account, lab.contractor02, the Contributor role on the resource group rg-lab-payments. The reason was simple: "they need to fix a deployment, nothing else". Contributor cannot give roles to anyone, so it felt safe.
Two weeks later a review of the vault kv-lab-pay-01 found something nobody had added:
- a new access policy for
lab.contractor02, with Get and List on secrets - created by
lab.contractor02itself - 41 secrets readable, including the payment API key and the SQL connection string
No alarm fired. Nothing was "hacked". The vault simply used the old permission model, and in that model, Contributor is enough to give yourself the keys.
How it works: two permission models, one vault
A key vault has two layers:
| Layer | What it controls | Example |
|---|---|---|
| Management plane | The vault as an Azure resource | create, delete, change network rules, change the permission model |
| Data plane | What is inside | read a secret, sign with a key, import a certificate |
For the data plane, a vault uses one of two models:
-
Vault access policy (legacy). The permission list lives inside the vault, as a vault property. Anyone who can write the vault can edit that list. Microsoft's built-in roles page says it plainly: Contributor, Key Vault Contributor, or any role with
Microsoft.KeyVault/vaults/writecan add an access policy and give themselves data plane access. - Azure RBAC (recommended). Data access is a normal role assignment, such as Key Vault Secrets User. Only roles that can write role assignments can grant it, such as Owner or User Access Administrator. Contributor and Key Vault Contributor manage the vault but cannot read secrets.
So the same role, Contributor, means "manage the vault" in one model and "manage the vault and read every secret" in the other.
Why it matters right now
Microsoft is making RBAC the default:
- With Key Vault API version 2026-02-01 or later, a new vault uses Azure RBAC by default. If you still want access policies, you must set
enableRbacAuthorizationtofalsewhen you create it. - Existing vaults do not change. A vault created with an older API version keeps using access policies until you switch it.
- All Key Vault control plane API versions before 2026-02-01 retire on 27 February 2027. Azure CLI 2.90.0 and Azure PowerShell 16.3.0 (or later) support the new version.
The trap: a team creates a new vault with the new CLI, their app gets 403 Forbidden because it has no role, and someone "fixes" it by switching the vault back to access policies. Now the problem from my lab is back.
The fix: find, map, switch, lock
1. Find every vault still on access policies
Azure Resource Graph, across all subscriptions you can see:
resources
| where type == "microsoft.keyvault/vaults"
| extend rbac = tobool(properties.enableRbacAuthorization)
| where isnull(rbac) or rbac == false
| project name, resourceGroup, subscriptionId, policies = array_length(properties.accessPolicies)
In my lab: 9 vaults, 3 still on access policies.
2. List who is in each access policy today
az keyvault show --name kv-lab-pay-01 --query "properties.accessPolicies[].{objectId:objectId, secrets:join(',', permissions.secrets)}" -o table
Remove anyone who should not be there (in my lab: lab.contractor02). Then write down what each real user or app needs.
3. Give the same access with RBAC roles, before you switch
Map each access policy to the smallest built-in role:
| Access policy today | RBAC role |
|---|---|
| Secrets: Get, List (an app reads secrets) | Key Vault Secrets User |
| Secrets: all (a team manages secrets) | Key Vault Secrets Officer |
| Keys: Get, Wrap, Unwrap (encryption at rest) | Key Vault Crypto Service Encryption User |
| Everything (vault admins) | Key Vault Administrator |
| Reads names only, not values | Key Vault Reader |
Assign at the vault scope, not the resource group:
KV_ID=$(az keyvault show --name kv-lab-pay-01 --query id -o tsv)
az role assignment create --role "Key Vault Secrets User" --assignee "$APP_ID" --scope "$KV_ID"
For people, make the role eligible in Privileged Identity Management instead of permanent. PIM works with RBAC roles. It does not work with access policies.
4. Switch the vault to RBAC
az keyvault update --name kv-lab-pay-01 --enable-rbac-authorization true
The moment you switch, all access policies stop working. That is why step 3 comes first. Role assignments can take a few minutes to apply, so switch in a quiet hour and test the app right after.
5. Lock it so it cannot come back
- Assign the built-in Azure Policy "Azure Key Vault should use RBAC permission model" at the management group, first in Audit, then Deny.
- Watch for changes. In Microsoft Sentinel (Azure Activity connector):
AzureActivity
| where OperationNameValue in~ ("MICROSOFT.KEYVAULT/VAULTS/ACCESSPOLICIES/WRITE", "MICROSOFT.KEYVAULT/VAULTS/WRITE")
| project TimeGenerated, Caller, ResourceGroup, _ResourceId, ActivityStatusValue
| order by TimeGenerated desc
An access policy write on any vault after the switch is either a mistake or someone trying the old trick. Both deserve a ticket.
SC-500 exam traps
Key Vault permission questions were a classic in AZ-500 and they are still in scope for SC-500. Watch for these:
- "The user has Contributor. Can they read the secret?" The answer depends on the permission model. Access policy vault: they can give themselves access. RBAC vault: no.
- "Key Vault Contributor" sounds like data access. It is not. It manages the vault resource only.
- "Grant the least privilege for an app that reads one secret." Key Vault Secrets User, scoped to the vault (or to that one secret), not Key Vault Administrator, not Contributor.
- "You switch the vault to RBAC. What happens to existing access policies?" They stop applying. Assign roles first.
- "Who can grant data access on an RBAC vault?" Roles with role assignment write permission, such as Owner and User Access Administrator. Not Contributor.
Before and after in my lab
| Before | After | |
|---|---|---|
| Vaults on access policies | 3 of 9 | 0 of 9 |
| People who could read payment secrets | 7 (incl. the contractor) | 2 eligible admins + 1 app |
| Access policy changes alerted | No | Yes, Sentinel rule |
| New vaults with access policies | Allowed | Denied by Azure Policy |
Coming next
Next deep dive: managed identities, and why "no secrets at all" beats "secrets in a well-locked vault". On Thursday: SC-500 practice questions, as usual.
Sources
- Azure RBAC vs. access policies
- Plan for Azure RBAC as the default access control model in Key Vault
- Migrate to Azure RBAC from access policies
- Grant access to Key Vault keys, certificates, and secrets with Azure RBAC
- Azure built-in roles for Security (Key Vault roles)
Thanks for reading! I'm Cuong, and on CD Security Lab I rebuild real Microsoft security cases in a safe lab and explain them simply. Follow along:
- ▶️ YouTube (daily Shorts + explainers): CD Security Lab
- 💼 LinkedIn: Cuong Do
- 📘 Facebook: CD Security Lab
- 📸 Instagram: @cdsecuritylab
- 📝 More posts like this: Dev.to
Got a question about your own tenant? Drop it in the comments.




Top comments (0)