Accessing Azure Key Vault Value From Console App Without Deploying To Azure Platform
What Is Azure Key Vault
Azure Key Vault, Safeguard cryptographic keys and other secrets used by cloud apps and services.
Microsoft Azure Key Vault is a cloud-hosted management service that allows users to encrypt keys and small secrets by using keys that are protected by hardware security modules (HSMs). Small secrets are data less than 10 KB like passwords and .PFX files. An HSM is a secure, tamper-resistant piece of hardware that stores cryptographic keys. Keys can also be imported or generated in HSMs that have been certified to FIPS 140-2 level 2 standards.
What I'm saying is, Azure Key Vault can help us to store sensitive data (maybe an API key or else), and keep them safe.
Step By Step
Let's do it. Follow the steps, to grab some important information.
Register App On Azure AD
In order to access Key Vault REST api successfully, we need to register an app on Azure AD first. Please follow these steps.
Azure AD
App registration
New registration
Register an application
Certificates & secrets
Client secrets: write down the secret. A secret string that the application uses to prove its identity when requesting a token. Also can be referred to as application password.
PS: You have ONLY one shot to write the secret down, after it generated. If missed, you must create a new one.
Key Vault Overview: remember that DNS Name, and directory id.
App registrations: please write down the directory id, and client id, we will need them.
Secret Identifier
Get Vault Value by Using SDK
An easier way to get vault value, by using SDK.
NuGet packages
Azure Key Vault ref packages
As we choose a quick way to get vault value by using SDK, and we will need to Install these packages from NuGet.
Azure.Security.KeyVault.Secrets
Microsoft.IdentityModel.Clients.ActiveDirectory
They will be great help.
Code sample
private static string GetVaultValue()
{
var client = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(AccessToken));
const string vaultBaseUrl = "https://<your-key-vault-name>.vault.azure.net"; // aka DNS name from overview
const string secretName = "<your-secret-name>";
var secret = client.GetSecretAsync(vaultBaseUrl, secretName).GetAwaiter().GetResult();
return secret.Value;
}
private static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
// AAD: App Registration client id
const string clientId = "<your-client-id>";
// AAD: App Registration client secret
const string clientSecret = "<your-client-secret>";
var credential = new ClientCredential(clientId, clientSecret);
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
var result = await context.AcquireTokenAsync(resource, credential).ConfigureAwait(false);
return result.AccessToken;
}
Get Vault Value by Calling REST APIs
Define models
Before we continue programming, we should generate few models for json parsing.
public class KeyVaultResult
{
[JsonPropertyName("value")]
public string Value { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("attributes")]
public Attributes Attributes { get; set; }
}
public class Attributes
{
[JsonPropertyName("enabled")]
public bool Enabled { get; set; }
[JsonPropertyName("created")]
public int Created { get; set; }
[JsonPropertyName("updated")]
public int Updated { get; set; }
[JsonPropertyName("recoveryLevel")]
public string RecoveryLevel { get; set; }
}
public class AccessCredential
{
[JsonPropertyName("token_type")]
public string TokenType { get; set; }
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }
[JsonPropertyName("ext_expires_in")]
public int ExtExpiresIn { get; set; }
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
}
Here's a tip: Edit > Paste Special > Paste JSON As Classess. It provide us a quick way to generate models in a short time.
Paste JSON As Classess
Handmade by calling Api
Basically, these handmade methods are original calling by SDK usage, and encapsulate to an easier way to people to use it.
private static string GetAccessTokenHandMade(HttpClient httpClient)
{
const string azureADDirectoryID = "<your-directory-id>";
var reqUrl = $"https://login.microsoftonline.com/{azureADDirectoryID}/oauth2/v2.0/token";
var req = new HttpRequestMessage(HttpMethod.Post, reqUrl)
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>()
{
{ "grant_type", "client_credentials" },
{ "client_id", "<your-client-id>" },
{ "client_secret", "<your-client-secret>" },
{ "scope", "https://vault.azure.net/.default" }
})
};
var response = httpClient.SendAsync(req).GetAwaiter().GetResult();
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var ret = response.Content.ReadFromJsonAsync<AccessCredential>().GetAwaiter().GetResult();
return ret?.AccessToken;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
Yes, of course. we still could do it by using Postman.
get access token
private static string GetVaultHandMade(HttpClient httpClient, string token)
{
// ref: https://docs.microsoft.com/en-us/rest/api/keyvault/getsecret/getsecret
// Key-Vault Secret Identifier with api-version
const string reqUrl = "https://<your-key-vault-name>.vault.azure.net/secrets/<your-secret-name>/<secret-version>?api-version=7.0";
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
try
{
var resp = httpClient.GetFromJsonAsync<KeyVaultResult>(reqUrl).GetAwaiter().GetResult();
return resp?.Value;
}
catch (Exception ex)
{
return $"{ex.Message}\n{ex.InnerException?.Message}";
}
}
get secret value
And now, we can get the secret value from Console Application.
Here is an online reference code demo on fiddle. When you open it, you will get some errors. There's nothing to worry about, please change some keys: Directory Id, Client id, Client secret, DNS Name, Secret Identifier, to your own ones. Once you changed them, re-run the program, and you will get vault value on the platform.
Enjoy it.
References:
Azure Key Vault basic concepts
Quickstart: Register an application with the Microsoft identity platform
Using Azure Key Vault references with Azure Functions or App Service
Using Managed Service Identity with Key Vault from a .NET Azure Function