Azure Key Vault can store username and password and manage sensitive information in Azure. Once Azure Key Vaults stores the information, Azure services that you specify (and ONLY Azure services that you specify) can access it
In this blog post, Iâm going to show you how to use Azure Key Vault to store Couchbase Server credentials and access them from an Azure Function.
This blog post on how to store database credentials and passwords in Azure Key Vault will be building on earlier blog posts about Couchbase on Azure, so you may want to review them before proceeding:
- Azure: Getting Started is Easy and Free
- Azure Functions and Lazy Initialization with Couchbase Server
- Azure Functions with Couchbase Server (video)
- Those should be enough to get you up to speed, but there are many more blog posts involving Azure
As always, if you want to follow along, you can find the completed source on GitHub.
Installation and Setup of Couchbase Server
The rest of this post assumes you have a Couchbase Server setup on Azure. You can follow the above links to learn about this process (itâs easy!).
In my setup for this blog post, I created a cluster (which required you to create administrator credentials) and a single bucket called “mybucket”.
Iâm using Couchbase Enterprise Edition 5.5.2 since thatâs the easiest to setup on Azure. The Community edition and older versions of Couchbase should work just fine as well.
Creating an Azure Key Vault
An Azure Key Vault can be created with the Azure Portal UI, or you can create it with the command line. In an earlier post on using the Couchbase Kubernetes Operator with Azure, I also used the command line. You may want to review that if youâve not used the Azure command line utility before.
The first step only needs executed once per Azure subscription. Assuming your command line is set to the subscription you want, register the Azure Key Vault with that subscription with this command:
1 |
PS C:\> az provider register -n Microsoft.KeyVault |
The next step is to create a vault. With this command you need to specify a resource group. I created a resource group in advance called “KeyVaultDemo”. I also decided to use the North Central US region of Azure.
1 |
PS C:\> az keyvault create --name 'MyCouchbaseKeyVault' --resource-group KeyVaultDemo --location 'North Central US' |
Azure will take a few moments to finish (but the process is asynchronous, so the command line prompt will appear immediately). The command line will tell you how to check on the progress.
Now that you have created the store username and password in Azure Key Vault created, you can start putting your secrets in it. Iâm going to store 4 pieces of information in my vault with these 4 commands:
1 2 3 4 |
PS C:\> az keyvault secret set --vault-name 'MyCouchbaseKeyVault' --name 'cbUsername' --value 'cbAdminUsername' PS C:\> az keyvault secret set --vault-name 'MyCouchbaseKeyVault' --name 'cbPassword' --value 'r6#Y%2^XXXXX' PS C:\> az keyvault secret set --vault-name 'MyCouchbaseKeyVault' --name 'cbBucketName' --value 'mybucket' PS C:\> az keyvault secret set --vault-name 'MyCouchbaseKeyVault' --name 'cbClusterUri' --value 'http://52.162.XXX.XXX:8091' |
(Note: I redacted some of the secret information using Xâs)
You can browse your secrets in the Azure Portal.
Benefits of Azure Key Vault
Before we go any further, letâs talk about why youâd want to use Azure Key Vault.
In previous blog posts, I stored the Couchbase credentials as app settings. Compared to app settings, Azure Key Vault gives you the following credentials capabilities:
- App Settings stores values as plain text. Azure Key Vault stores them encrypted.
- Each application has its own app settings. With Azure Key Vault, each of your applications can share a single key vault.
- Azure Key Vault stores a version history of values, and each secret has an (optional) activation date and expiration date.
Azure Key Vault doesnât replace app settings. Use of Azure Key Vault is best when you want to securely store sensitive information (like credentials/passwords/API keys) and/or use them across multiple services.
Getting Azure Functions ready for Azure Key Vault
In a previous blog post on Azure Functions, I stored the Couchbase credentials in app settings. Now that I have those credentials in an Azure Key Vault, Iâm going to change my Azure Functions code to use the Azure Key Vault instead.
First, I created an Azure Functions service. You can create this from the Azure Portal UI, or from Visual Studio or Visual Studio Code directly. This time, I used Visual Studio Code (for more information, check out the Azure Functions extension). I happened to name my Azure Functions service cbkeyvaultdemo.
Next, I made note of the URIs for each of the secrets that I created. I have 4 secrets, so I need 4 URIs (“Secret Identifier” as in this screenshot):
I created 4 constants and pasted these values into my code. (You may want to eventually store these in the app settings).
1 2 3 4 |
const string Vault_Bucketname_Uri = "https://mycouchbasekeyvault.vault.azure.net/secrets/cbBucketName/1bda709e1372465a8f03b6e8c3fb6014"; const string Vault_Clusteruri_Uri = "https://mycouchbasekeyvault.vault.azure.net/secrets/cbClusterUri/48605e696b3645a6a7c396a15d636dc2"; const string Vault_Username_Uri = "https://mycouchbasekeyvault.vault.azure.net/secrets/cbUsername/7d73ef5fa2174e5491d4a50a42bb0800"; const string Vault_Password_Uri = "https://mycouchbasekeyvault.vault.azure.net/secrets/cbPassword/d6f61ff7e41a4fdcbe17de0b1fe1f115"; |
The next step is to install a couple of packages with NuGet: Microsoft.Azure.Services.AppAuthentication and Microsoft.Azure.KeyVault. Hereâs an example of installing those packages with the command line:
1 2 |
C:\> dotnet add package Microsoft.Azure.Services.AppAuthentication C:\> dotnet add package Microsoft.Azure.KeyVault |
Getting Secrets from Azure Key Vault
The next step is to write some code to fetch the secret values from the Azure Key Vault. I created a small helper function that I could reuse:
1 2 3 4 5 6 7 8 9 |
private static string GetSecret(string url) { var azureServiceTokenProvider = new AzureServiceTokenProvider(); var kvClient = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback( azureServiceTokenProvider.KeyVaultTokenCallback), client); var secret = kvClient.GetSecretAsync(url).Result.Value; return secret; } |
As before, Iâll be using Lazy initialization in this Azure function. Hereâs what it looks like when using app settings (before):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
private static readonly Lazy<IBucket> Bucket = new Lazy<IBucket>(() => { var uri = Environment.GetEnvironmentVariable("couchbaseUri"); var bucketName = Environment.GetEnvironmentVariable("couchbaseBucketName"); var username = Environment.GetEnvironmentVariable("couchbaseUsername"); var password = Environment.GetEnvironmentVariable("couchbasePassword"); var cluster = new Cluster(new ClientConfiguration { Servers = new List<Uri> { new Uri(uri) } }); cluster.Authenticate(username, password); return cluster.OpenBucket(bucketName); }); |
And hereâs how it looks when I switch it to use the GetBucket
helper method (after):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
private static readonly Lazy<IBucket> Bucket = new Lazy<IBucket>(() => { var uri = GetSecret(Vault_Clusteruri_Uri); var bucketName = GetSecret(Vault_Bucketname_Uri); var username = GetSecret(Vault_Username_Uri); var password = GetSecret(Vault_Password_Uri); var cluster = new Cluster(new ClientConfiguration { Servers = new List<Uri> { new Uri(uri) } }); cluster.Authenticate(username, password); return cluster.OpenBucket(bucketName); }); |
One important thing to note about this helper function. Getting secrets from Azure Key Vault is an asynchronous operation. However, Lazy
expects a synchronous lambda. One option is to use Stephen Clearyâs AsyncLazy. Another option (which is what I did) is to call an asynchronous method synchronously by using .Result
.
Where did client
come from? Easy, I added private static HttpClient client = new HttpClient();
to the class. You can check out the full source code on GitHub.
I mainly followed this excellent blog post by Jeff Hollan called Getting Key Vault Secrets in Azure Functions (except he stored an EventHub connection string and Iâm storing Couchbase credentials).
Authorization
You might be asking: Matt, why did you publish the real URIs in your sample code?
Itâs because the URIs themselves are not sensitive secrets. Only services that are authorized by Azure can actually get useful information from these URIs.
To authorize this Azure Function service, you need to do two things:
- Enable a managed service identity for the Azure Functions service. This is as easy as clicking “Managed service identity” in the Azure portal and changing an “off” to an “on”.
- Add an access policy to your Azure Key Vault. Simply find the Azure Key Vault in the Azure portal UI, click “Access policies” under settings, and add a new access policy. You can define fine-grained permissions for accessing Key, Secret, and Certificates (which Azure Key Vault can also store, by the way). I only needed “Get” permissions, so my access policy was very simple:
Thatâs it. But without this important step, the key vault will allow no person or application to fetch a key.
Summary and Next Steps
Instead of deploying Azure Functions (or other application services) with Couchbase credentials stored in the application settings, we can now put those credentials (and any other sensitive information) into an Azure Key Vault.
We give application(s) permission to access the secrets in the vault, and Azure will prevent anyone else from getting those secrets.
The application(s) pull the secrets from the Azure Key Vault.
If you have any questions about this blog post, feel free to leave a comment below or find me on Twitter @mgroves.
If you are using Couchbase with Azure, the entire Couchbase Community would love to hear from your experience. Or, if you are just getting into Couchbase with Azure, you can also find and ask other community members for their advice or high-level recommendations.
If you have a specific technical question about Couchbase, please check out the Couchbase Forums.