Microsoft is investing tons of money into Azure, its cloud environment. That’s great, because it means that what you can do in apps is expanding dramatically.
But the documentation always seems to be one or two steps behind what’s running. Worse yet, when you search online for help and examples, quite frequently you end up dealing with APIs and screenshots that are different from the current day situation. So starting down the learning curve on anything Azure that’s new to you is far more painful than used to be the case when working in the Microsoft development environment.
Today’s case in point: key vaults. They look like a simple but elegant way to manage information you need to keep secret. By storing those secrets in the cloud, they’re accessible from anywhere.
Unfortunately, getting even a simple password retriever to work is an exercise in frustration, for all the reasons I mentioned above. I’m going to try to help you avoid that frustration, at least in part, by sharing what I learned.
There are several steps to setting up a key vault, not all of which, so far as I can tell, can be done through the Azure portal. You may be able to do all of it through Powershell…but I’m not a Powershell expert, so I’m not sure about that.
Here’s how I got my simple password retriever to work…
Step 1: Create a key vault
You can do this from within the Azure portal. I did it by going to All Resources, and, in the right-side tab, enter key vault in the search box. This brings up the screen for creating a key vault. Fill in a name for the vault, specify the subscription to use, and either specify the resource group where the vault should be domiciled, or create a new one to hold it. I think the name has to be unique within Azure (ever noticed why Azure names TendToBeUnbelievablyLong?).
Click Create. After the creation/deployment is finished, either click the link to go the resource, or go back to All Resources and click on the new vault (you may need to refresh All Resources to see it). In the Overview panel, copy the DNS Name value, and save it. This is what I refer to later as the “vault URL”.
Step 2: Add something to the vault
Go back to All Resources, and click on the vault you just created (you may need to refresh to see it). Click on Add to bring up the Create a Secret panel.
Secrets can be either simple text strings, or a certificate. I have no idea what the latter is or why you’d want one, so we’re going to ignore that choice. Select Manual under Upload Options (another thing I dislike about Azure’s documentation: why in the world is the text field labeled ‘upload’ instead of something like ‘Type of Secret’? And why is the choice of creating a simple text secret deemed to be ‘Manual’?).
Enter a name for the secret, and its initial value. You can play around with the other options, but I didn’t. Click Create. Note that I refer to the name you’ve assigned as the “vault key”.
This creates and stores the initial value of the secret. Secrets seems to behave like stack structures — you can keep changing the value, which replaces the active value, but all the earlier values are still available. If you retrieve a secret by its name, you get the latest value. If you retrieve it by it’s name, a slash, and it’s key, you get whatever value corresponds to that particular key.
You can see this after you click Create, and return to the Secrets page. Click refresh if necessary, and then click on the name of the secret you just created. Up pops another panel listing all the versions of the secret that Azure knows about, and their corresponding keys. If you click on a version, you’ll get a panel showing that particular version of the secret’s access URI.
Step 3: Register an App with Azure
While you can access a secret through the Azure portal, to do so programmatically you have to register an application with Azure…and then tell Azure that it’s okay for that registered app to access the key vault you just created.
To do the first step — register an app — click on Azure Active Directory in the left hand pane of the portal. Click App registrations, and then click the link New application registration at the top of the panel which opened. This brings up the Create app registration panel.
Give the application a name (I’m not sure how unique it has to be; I think it’s “local” to your Azure account). Now comes several very unobvious (to me, anyway) steps:
- Select Web app / API for Application type. If you’re writing a desktop console app, as I was, you might be tempted to select Native. Don’t do that! A desktop console app interacts just fine with Azure key vaults via the Web app / API choice…and it doesn’t seem to work, at all, with the Native choice.
- Enter a valid Sign-on URL, which you will then ignore forevermore when retrieving secrets. I just used http://localhost:8080.
- Save the application ID that gets generated when the app is registered by Azure. This is one of two critical pieces of information you’ll need to access the key vault from your code.
- Go back to the App registrations panel, and click on the app you just registered (you may need to refresh the panel to see it).
- In the Settings panel that appears, click on Keys
- In the Keys panel that appears, define a new key with a description and an expiration date. As you enter information, the Value column notifies you a key will be created and made visible when you click the Save link at the top of the panel. When you’re ready, click that Save link.
- When the panel refreshes, the key’s value appears. It is crucial that you save this key value someplace; once you leave the panel, you can never view it again…and it’s the other critical piece of information you’ll need to access the key vault from your code.
Step 4: Give Your App Access Rights to the Key Vault
Learning to do this was accompanied by much teeth-gnashing and hair-pulling. So far as I know, you can’t do it through the Azure portal; you have to do it through Powershell. Which means you have to have the Azure Powershell modules installed. Unfortunately for this tutorial, what I don’t know about Powershell would fill volumes. Hopefully you’ll be able to search online for instructions on installing the Powershell Azure modules. And it’ll have to be a very recent version of the Azure Powershell modules, as of when I’m writing this blog post…because there was a bug in the Powershell modules which didn’t get fixed until November, 2017.
Once you’ve done that, fire up a Powershell command window — I think it has to have admin rights — and run the following commands:
Login-AzureRmAccount Set-AzureRmKeyVaultAccessPolicy -VaultName '<insert vault name here>' -ServicePrincipalName <application id> -PermissionsToSecrets Get
The vault name is the name you gave your key vault when you created it in step 1. The application ID is the first of the two critical GUIDs that were generated in step 3. Note that the application ID is not wrapped in quotes.
There are a bunch of permissions that you can grant your app in relation to the secrets stored in the key vault. In my case, I just want to be able to retrieve/get them; I add or edit them through the Azure portal. See the documentation for details on the other permissions.
Step 5: Write Some Code
With all that out of the way, it’s time to write some code (C#, in my case). All the magic happens in a very few lines of code (the method names can be anything you like; and I’ve left out all the error checking stuff):
// required usings...
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net.Http;
using System.Threading.Tasks;
namespace YourNamespace
{
public class YourClass
{
public async Task<string> GetSecretAsync( string vaultUrl, string vaultKey )
{
var client = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback( GetAccessTokenAsync ), new HttpClient() );
var secret = await client.GetSecretAsync( vaultUrl, vaultKey );
return secret.Value;
}
private async Task<string> GetAccessTokenAsync( string authority, string resource, string scope )
{
var appCredentials = new ClientCredential( "<your app's Azure ID>", "<your app's hidden key>" );
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
var result =await context.AcquireTokenAsync( resource, appCredentials );
return result.AccessToken;
}
}
}
You’d use this via something like:
var yourClass = new YourClass();
string password = yourClass.GetSecretAsync("<your vault url>", "<your vault key");
The vault URL is DNS Name that Azure created when you created the key vault in step 1. The vault key is the name you assigned to the secret when you added it to the key vault in step 2.
A lot of work to store and retrieve secrets. But worth it, I think, for the security it provides. Speaking of which, most of the articles I read included a disclaimer to the effect that what I’ve outlined here isn’t really the ideal way to use key vaults. So don’t blame me if you get hacked or something :).
2 thoughts on “Azure Key Vaults”
Hi,
Your code got messed up by special characters, really hard to read.
Please fix!
Sorry about the delay in responding and fixing the problem, Alexander. It appears to be related to how the Enlighter plugin, which I use to display source code, interacts with the new WordPress Gutenberg editor. Hopefully it stays fixed this time!
– Mark