Azure Key Vault: stop using access policies

RBAC and access policies are NOT compatible, so switch over and leverage the power of managed identities and RBAC instead.

Note: Azure RBAC has been the recommended authorization system for Azure Key Vault since May 2023. It was already in preview since October 2020.

I’ve had the opportunity to give my session on ‘Developer productivity shouldn’t breach security’ at more than a handful of conferences / meetups the past year. One of the topics I touch is Managed Identity and how to use it to securely access resources like Azure Key Vault.

Why use RBAC?

“Because I say so” is typically not the right way to get your team on board, so I’ll hand you a link to the docs comparing RBAC vs access policies. In short:

  • Aligned with the RBAC model for other resources.
  • Fine-grained access management when required (e.g., multiple applications on a single Key Vault can only read their own keys).
  • Integrated with PIM for temporary and on-demand access.

There’s a whole page dedicated to migrate from access policies to RBAC, so I won’t go in detail there. I’d rather tell where it went wrong in one of my teams.

Switching between both breaks things

I was setting up new Azure resources (through Bicep) for a new project, with RBAC ‘as it should be’. One of the team members implementing the backend copied some code over from an existing project to access Azure Key Vault and got stuck. The existing code was still using access policies and rather than reaching out, he changed the Key Vault back to authorize through access policies.

Not soon after his change, I received a message with “I can no longer add/edit keys”. The team was given access through RBAC as well as Key Vault Administrator, and was Owner on the Development environment to test things out (I typically prefer to do this on a Research environment instead). So what happened?

  • When you change Azure Key Vault from RBAC back to Access policies, you break RBAC (see picture below).
  • Even though the team was Owner, this gives them the rights to operate on the Azure control plane, not on the data plane (where secrets live).

Azure Key Vault change to access policies

Accessing Key Vault from an App Service with RBAC

We have a nice tutorial again how to use a managed identity to connect Key Vault to an Azure web app. If you have an existing project, I can shorten it down to the following steps. Here we will also use a system-assigned identity rather than a user assigned.

  1. Go to your Azure App Service > Identity and turn the System assigned idenitity to On. You can take note of the Object ID in case you use IaC to deploy and manage your resources.

Azure Key Vault change to access policies

  1. Go to your Azure Key Vault > Access Control (IAM) and add a new role assignment. Since we want to follow least-privilege, a Key Vault Secrets User role is more than enough. Going through the portal allows you to select the app service itself (rather than messing with guids). You will see the correct Object ID return here.

Azure Key Vault change to access policies

  1. If you want to test from your local machine, repeat the above step but add your own user account (which you also use to login into Visual Studio).

Azure Key Vault change to access policies

  1. Update your code (next paragraph).

Updating your .NET Code

If you would use the tutorial, you can directly skip to this section.

Most of us probably have Visual Studio open if you have an existing project, so you can use following commands for the Package Manager Console instead:

Install-Package Azure.Identity
Install-Package Azure.Security.KeyVault.Secrets

Finally, all that is left to do is call the actual Key Vault to retrieve a secret (with exponential backoff):

SecretClientOptions options = new SecretClientOptions()
{
    Retry =
    {
        Delay= TimeSpan.FromSeconds(2),
        MaxDelay = TimeSpan.FromSeconds(16),
        MaxRetries = 5,
        Mode = RetryMode.Exponential
    }
};
var client = new SecretClient(new Uri("https://<your-unique-key-vault-name>.vault.azure.net/"), new DefaultAzureCredential(),options);

KeyVaultSecret secret = client.GetSecret("<mySecret>");

string secretValue = secret.Value;
Licensed under CC BY-NC-SA 4.0; code samples licensed under MIT.
comments powered by Disqus
Built with Hugo - Based on Theme Stack designed by Jimmy