Access Azure KeyVault with Non-Azure Linux App

See how an on-prem .NET 5 application connects to and reads secrets in the Azure Key Vault.
I'll take a brief look at steps involved in connecting my .NET 5 app running in an on-prem Linux VM to Azure's Key Vault using client certificate authentication with a self-signed cert.
To Follow Along, You'll Need
- An Azure Subscription
- At least one Key Vault
- A computer running GNU/Linux
Overview
- Create a self-signed cert
- Convert the self-signed cert into a PFX file
- Register the App in the Azure Portal
- Associate the self-signed, public key cert with your App in the Azure Portal
- Create an Key Vault Access Policy which allows your App to read Key Vault Secrets
- In C#, leverage your client cert (PFX) to authenticate with Key Vault
- In C#, read Key Vault Secrets
Create the Cert and PFX
On the Linux machine where your app resides use the following commands to create a self-signed certificate using openssl. On Ubuntu install openssl
if necessary via
apt-get install openssl
In the following section, press Enter
when asked for a password.
$ openssl genrsa -aes256 -passout pass:gsahdg -out app.pass.key 4096
$ openssl rsa -passin pass:gsahdg -in app.pass.key -out app.key
$ rm app.pass.key
$ openssl req -new -key app.key -out app.csr
# Finally, generate the cert using the private key and client request
$ openssl x509 -req -sha256 -days 365 -in app.csr -signkey app.key -out app.crt
The commands above create
- A digital certificate with a public key only. This is the cert which gets uploaded to Azure later.
- The certificate is associated with the machine on which it was created. It can't be moved to another machine for consumption. Someone please correct me on this point if I'm mis-speaking. This was my experience, personally
The application code will need to consume a digital certificate with both the public and private key. This can either be a .pem or a .pfx file. The latter is created using the commands below.
Please note, the command below will prompt you for an export password which you will need to remember.
$ openssl pkcs12 -export -out app.pfx -inkey app.key -in app.crt
The app.pfx
file created above should be secured with file permissions. The user running your app will need read access to the cert.
In the Azure Portal
In the interest of time, I'll reference this blog post written by Shantanu Pandey over at C# Corner which does a nice job of showing how to register an application for Key Vault access. Again, the steps are
- Register the App in the Azure Portal
- Associate the self-signed, public key cert with your App in the Azure Portal
- Create a Key Vault Access Policy which allows your App to read Key Vault Secrets
The Application Code
Two NuGet packages are needed to connect to Azure and access a Key Vault.
Azure.Identity
Azure.Security.KeyVault.Secrets
The application will need these using
declarations.
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using System.Security.Cryptography.X509Certificates;
The following code in Program.cs could be used to authenticate with and create a client to Azure's Key Vault API.
public const string URL_KEY_VAULT = "https://{KeyVaultName}.vault.azure.net/";
public const string AZR_TENANT_ID = "The unique ID of the Azure Active Directory Tenant with which the app was registerd. This is a standard GUID.";
public const string AZR_CLIEN_ID = "The unique ID of the Service Pincipal associated with the app. This is also a standard GUID.";
public const string CERT_PATH = @"/super/secret/secured/path/to/app.pfx";
public const string CERT_EXPORT_PSWD = "{The password you entered when you created the PFX. Best not to store this directly in code.}"
static void Main(string[] args)
{
var keyVaultUri = new Uri(URL_KEY_VAULT);
X509Certificate2 cert = new X509Certificate2(CERT_PATH, CERT_EXPORT_PSWD);
var certificateCredential = new ClientCertificateCredential(AZR_TENANT_ID, AZR_CLIEN_ID, cert);
var client = new SecretClient(keyVaultUri, certificateCredential);
}
Upon successful authentication, the client
variable can be used to read KeyVault Secrets.
var secret = client.GetSecret("Foo").Value;
Console.WriteLine($"Foo's Secret Value: {secret.Value}");