Test Driving The Azure Key Vault Client Samples

In my previous post I wrote a brief introduction on how to get started with Azure Key Vault. As an exercise for myself, I wanted to dive in a bit more detail about what is involved in setting up the Microsoft Azure Key Vault Client Sample Code. So let's dive in and see what the process looks like.

Setting Up

First things first, make sure you download the code, if you haven't already done so, if you want to follow along. Here is the link:

Configure Sample Application With Azure

I will be setting up a new Key Vault to connect with the sample code, however, I won't go into detail on the setup as this was already covered in the previous post.

Since you will be working with your Azure account, go ahead and launch a PowerShell 5 console session, make sure you you launch the session as an Administrator. Once your session is up and running log into Azure by issuing this command:

Login-AzureRmAccount

Once are you are logged in, the next thing to do is to create a new Key Vault to test with the sample code. As you recall from the previous post, creating a new Key Vault is pretty straight forward using Azure PowerShell cmdlets. Here we create a new Azure Resource Manager (ARM) Group and a new Key Vault in the same ARM Group:

New-AzureRmResourceGroup –Name 'KeyVaultResourceSampleCode' –Location 'Central US' New-AzureRmKeyVault -VaultName 'TheKeyVaultCodeSample' -ResourceGroupName 'KeyVaultResourceSampleCode' -Location 'Central US'

Creating A Self-Signed Certificate For Key Vault Access

Now that your new Key Vault is ready, you need to create a self-signed certificate. Note that you can use the Key Vault connection information instead, but I thought it might be more beneficial to show how this can be done more securely using a certificate. You will use this certificate to register the sample code application and authenticate with Azure using that certificate, then Azure will provide you with a token that you can then use to authenticate with Key Vault and retrieve your secrets.
So at first, I thought I would use PowerShell 5 to generate my self-signed certificate and use it to access Key Vault, unfortunately I ran into a number of issues with this and the provided sample code. One of the main issues I ran into was with the .NET code accessing the certificate in the code sample. Even though the certificate I generated using PowerShell contained the private key in the certificate store, at runtime the code was simply not able to find the private key for the self-signed certificate and things simply would not work correctly. I believe the issue might be related to the problem stated in this article: https://blogs.msdn.microsoft.com/alejacma/2009/12/22/invalid-provider-type-specified-error-when-accessing-x509certificate2-privatekey-on-cng-certificates/ and also in this article: https://blogs.msdn.microsoft.com/winsdk/2014/11/18/accessing-a-cng-private-key-from-an-x509certificate2-class/ What is more, I have not confirmed this yet, but it seems that the certificates issued by PowerShell may be using the CNG Key Storage Provider, for which the .NET framework support may not be fully baked in the version of the .NET framework that the code sample uses (4.5). Furthermore, if you take a look at some of the extension methods documentation that are targeting the next generation CNG Provider, you will noticed that it specifically states that it "is preliminary and is subject to change in the next release of the .NET Framework 4.6." as in the case of X509CertificateExtensions.HasCngKey Method However, I do not have any solid evidence for this, so take my inference with a grain of salt. In any case, in order to continue moving forward I decided to use the legacy "makecert.exe" for now, and when I find the formula for successfully using the PowerShell self-signed certificates then I will write about it then. There probably is a switch in PS to force it to generate a 'legacy' type of certificate, but I am not aware of it, if that is indeed the case. Nevertheless, if you would like to use the PowerShell version and test it out on your own, you can do so by using a command similar to this:

New-SelfSignedCertificateEx -Subject "CN=testcert.cloudapp.net" -StoreLocation "LocalMachine" -StoreName "My" -ProviderName "Microsoft Strong Cryptographic Provider" -Exportable

And for the current solution using the legacy makecert.exe you can use this command from a Developer Console:

makecert -r -pe -n "CN=samplekeyvault.oncloudapp.net" -ss My -len 2048 myKeyVaultCertificate.cer -sv myKeyVaultCertificatePrivateKey.pvk

and then use this command for creating the PFX file:

pvk2pfx.exe -pvk myKeyVaultCertificatePrivateKey.pvk -spc myKeyVaultCertificate.cer -pfx myPfxKeyVaultCertificate.pfx

After you have generated the PFX file, proceed to import it into the Personal certificate store in the Local Machine. The sample code will access the machine certificate store at runtime in order to use the self-signed certificate to connect to the Key Vault.

Now that you have a freshly minted self-signed certificate ready, you can go back to your PowerShell session and access the certificate from the PFX file you created earlier. You will then register a new Azure AD application and associate it with this certificate contained in the PFX file. Here is the PS command to access the PFX certificate file (replace any specific file paths with your own):

$mySelfSignedCertificate = Get-PfxCertificate -FilePath "C:\temp\MySuperPFXAuthCertificate.pfx" $certificateBase64Value = [System.Convert]::ToBase64String($mySelfSignedCertificate.GetRawCertData())

The previous snippet will access the PFX file and retrieve the certificate raw data as a base64 encoded string in order to use it for the application registration. Now, create a new application registration:

$adapp = New-AzureRmADApplication -DisplayName "SampleKeyVault" -HomePage "http://localhost:55547/" -IdentifierUris "https://{YourSubDomain}.onmicrosoft.com/SampleKeyVault" -CertValue $certificateBase64Value -StartDate $mySelfSignedCertificate.NotBefore -EndDate $mySelfSignedCertificate.NotAfter

Next, create a new Service Principal utilizing the Application Id from the previous snippet:

$sp = New-AzureRmADServicePrincipal -ApplicationId $adapp.ApplicationId

Ultimately, give your sample application registration its respective permissions to your Key Vault:

Set-AzureRmKeyVaultAccessPolicy -VaultName 'TheKeyVaultCodeSample' -ServicePrincipalName $sp.ApplicationId -PermissionsToSecrets all -PermissionsToKeys all -ResourceGroupName 'KeyVaultResourceSampleCode'

Configuring The Sample Code

Once the Key Vault is created and the certificate generation, application registration and association with the Key Vault is complete, open up the solution for the Microsoft Azure Key Vault sample and locate the 'HelloKeyVault' C# console project. This is the simplest project to setup in the sample and it will also give you a good idea of the various capabilities of Key Vault.
So once the project is open, find the app.config file inside of the 'HelloKeyVault' project, and locate these settings:

<appSettings> <!-- Update these settings for your test environment --> <add key="VaultUrl" value="URL to your Vault" /> <add key="AuthClientId" value="Client Id of your Service Principal" /> <add key="AuthCertThumbprint" value="Thumbprint of the certificate used for authentication" /> <add key="TracingEnabled" value="false" /> </appSettings>

Then proceed to replace the previous settings as follows:

  1. The Key Vault URL is usually the name of the Key Vault you created, appended to '.vault.azure.net'. For instance, in my sample case this would be: https://thekeyvaultcodesample.vault.azure.net/
    You then would update your configuration setting like this:
    <add key="VaultUrl" value="https://thekeyvaultcodesample.vault.azure.net/" />

  2. The next setting is the client id of your application service principal. You can access the Application Id from within your active PowerShell session by running this command: $sp.ApplicationId. Then update the following setting with the value for the output of the ApplicationId property: <add key="AuthClientId" value="0e2c1c14-4581-4f25-b54d-ed2e4e61290b" />

  3. Lastly, the value of the self-signed certificate thumbprint can also be obtained from within your PowerShell session with this command: $mySelfSignedCertificate.Thumbprint. And you would place the output for the value of the certificate thumbprint in this setting: <add key="AuthCertThumbprint" value="5330226CBB4519835DA820D1DA628C44F6B1D9FE" />

So that all your application settings should look similar to this:

<appSettings> <!-- Update these settings for your test environment --> <add key="VaultUrl" value="https://thekeyvaultcodesample.vault.azure.net" /> <add key="AuthClientId" value="0e2c1c14-4581-4f25-b54d-ed2e4e61290b" /> <add key="AuthCertThumbprint" value="5330226CBB4519835DA820D1DA628C44F6B1D9FE" /> <add key="TracingEnabled" value="false" /> </appSettings>

Running The Sample Application

Now that everything is setup, you can select the HelloKeyVault console project in the Microsoft.Azure.KeyVault.Samples solution and run it in Debug mode. If everything is setup correctly, you should see a console window start up with a sequence of outputs similar to this:

Key Vault Sample Code Console Output

Final Thoughts

Azure Key Vault is a good option for keeping your secrets safe in the cloud. You can control who can access and view or update your application secrets, and you can audit who or what accessed those secrets or certificates. This will help you and your organization for the next time your auditors ask you: "Do you know where all your secrets are?"

Until next time, keep your secrets safe and stay secure.