Securing CosmosDB keys with Azure KeyVault

Working with CosmosDB in your applcation is pretty easy. There are tons of tutorials and sample code that shows how you can easily connect your code to ComsosDb and start coding. However, most if not all of them, will at somepoint say [Insert your CosmosDB Key here]. Which means you are essentially taking your most critical piece of defense (your authentication key) and copying it somewhere in your code or configuration. Invariably, at some point it will get into your source control, and that’s just asking for trouble down the line because it’s way harder to restrict access to sensitive information in source control.

Fortunately, there’s an easy (?) way to deal with this problem and it involves a few built-in Azure features like Azure KeyVault and Managed Identity.

The KeyVault

First up, Azure KeyVault. Azure KeyVault is a service backed up by dedicated Hardware Security Modules (HSM) that keep your secrets, secret.
To get to those secrets, you need to have a valid directory account, and have permissions to read data from KeyVault.

Let’s create a KeyVault, and add the secrets in the ‘Secrets’ section.

I usually store the CosmosDB Key and the endpoint in the Keyvault because these are the most sensitive pieces of information. The database and collection can live as simple config settings as they are more likely to change across environments and by themselves they usually don’t provide any information if exposed.

We will get back to the KeyVault later, to assign the required permissions.

The App Service

The sencond piece we’ll configure is the App service that we will deploy the application on. Essentially, when the code is running, the application will need to access the keyvault to read the secrets - in our case the CosmosDB access key - in order to establish a connection to the database.
Only directory accounts can access the keyvault so we will need to create that. We achieve that though the ‘Managed Identity’ feature found in the Web App (also available for Azure Functions).

When you enable Managed Service Identity, you are essentially creating a managed Azure Active Directory identity and associate it to your serivce. You can set appropriate permsissions for that identity in the Keyvault so that code running on that app service will be able to access secrets in the KeyVault

To do that, you need to go back to the KeyVault and use the Access Policies blade to assign permissions.

The Code

It’s really simple to retrieve the values from the vault in code.
First install the Microsoft.Azure.Services.AppAuthentication NuGet package then use some simple code to connect and retrieve a value from your KeyVault
(I did not go into the weeds of storing the Uri as a configration because that will depend on the framework you choose).

var secretUri = "";
var keyVaultTokenProvider = new AzureServiceTokenProvider().KeyVaultTokenCallback;
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(keyVaultTokenProvider));

var mySecret = await keyVaultClient.GetSecretAsync(secretUri);
var mySecretValue = mySecret.Value;

You can get your secretUri by browsing your secrets in the azure portal:

Notice how I didn’t have to hide my secretUri because unless the application running the code is authorized with the keyvault, you won’t be able to read the value so that Uri is somewhat harmless to sit in a configuration file in your code.

If you publish this code to your Azure Web App that has been granted access to the KeyVault, you will be able to get your value with those 4 lines of code.

Debugging in Visual Studio

So now everytihng is working when deployed to our Azure App, but how do we debug our code locally when running from Visual Studio, since that’s not running under an authorized app service?

Luckily, there’s a way to authenticate into Visual Studio with a directory account that will be used as a principal when running the code in deubug mode. You can find that setting under Tools - Options - Azure Service Authentication

Note that you can set up multiple accounts here, and it is totally independent of the account you use to login to Visual Studio (for licensing or other services purposes). But the most important thing, the account that is selected is the one that will be used in the debugging sessions.

And with that, you now have a solution to easily write, debug and deploy code that does not contain any sensitive information and you can be sure that your CosmosDB account is protected as best as you can.

Share Comments