In the old days, we used to access the Azure Key Vaults using the Vault URL and its Secret Key, we were placing this in the config file and going from there.
Placing sensitive information in the config file is a bad idea, it may cause a security breach and loss of data.
This article will explain how we can access the Azure Key Vault information using Self-signed certification, which involves the below steps.
- Create self-signed certificate
- Create a private key for the certificate
- Create Azure AD App
- Assign certificate to Azure AD APP
- Provide permission to Azure AD app in Key Vault
- Register/publish the certificate on a local machine (In the current scenario we are storing the certificate in a local machine, we can register the certificate in Azure app service also)
Coming to actual implementation.
Step 1. Creating Self-Signed certificate
Open Visual Studio command prompt as administrator.
Execute the below command to create the certificate. It will prompt for the private key password; provide the same password in all the places.
makecert -sv Mykey.pvk -n "cn=DEVCertificate" DEVCertificate.cer -b <<StartDate>> -e <<End Date>> -r
Step 2. Create a private key for the certificate
Use the below command to create a private certificate. Here, we need to pass the certificate name and desired pfx file name and private key.
pvk2pfx -pvk Mykey.pvk -spc DEVCertificate.cer -pfx DEVCertificate.pfx -po <<Password>>
It created both, public and private, certificates.
Step 3 & 4. Create an Azure AD App and Assign a certificate
The below PowerShell script will import the certificate, create an Azure AD App, and assign the certificate to that app.
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certificateFilePath = "C:\DEVCertificate.cer"
$certificate.Import($certificateFilePath)
$rawCertificateData = $certificate.GetRawCertData()
$credential = [System.Convert]::ToBase64String($rawCertificateData)
$adApplication = New-AzureRmADApplication -DisplayName "DevClientApp" -HomePage "http://www.DevClient.com" -IdentifierUris "http://www.DevClient.com" -CertValue $credential -StartDate $certificate.GetEffectiveDateString() -EndDate $certificate.GetExpirationDateString()
Step 4. Provide permission to the Azure AD app
The below script will give permission to the Azure AD App in Azure Key Vault.
$servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $adApplication.ApplicationId
Set-AzureRmKeyVaultAccessPolicy -VaultName 'RKDevKeyVault' -ServicePrincipalName $servicePrincipal.ServicePrincipalNames[0] -PermissionsToSecrets all -PermissionsToKeys all
You can get the thumbprint of the certificate by using the Certificate Thumbprint function.
$certificate.Thumbprint
Now, we have done all the necessary configuration for registering the certification with Azure, and created an application to access the key vaults.
Step 5. Register certificate in Local Machine
Open the private certification (.psk file) and follow the below steps to register the certificate on a local machine.
Select default options provide a private key and finish the wizard, this will register the certificate on a local machine. We can find the registered certificate in MMC (Microsoft Management Console).
Search for MMC and open.
Open the File menu and click on Add/Remove Snap-in. Select Computer Account and Local Computer to add the certificate section.
Open the Certificate folder. You can see all the registered certificates here.
Step 6. Creating an application to access the key vaults
Here, I am creating a simple Visual Studio console application for demo purposes.
Create a console application and add the below helper call to the project.
AzureKeyVaultCertificationHelper.cs
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace KeyVaultCertification
{
public class AzureKeyVaultCertificationHelper
{
public static X509Certificate2 FindCertificateByThumbprint(string thumbprint)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (col == null || col.Count == 0)
{
throw new Exception("ERROR: Certificate not found with thumbprint");
}
return col[0];
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return null;
}
finally
{
store.Close();
}
}
public static ClientAssertionCertificate AssertionCert { get; set; }
public static void GetCertification()
{
var clientAssertionCertPfx = FindCertificateByThumbprint(ConfigurationManager.AppSettings["ThumbPrint"]);
AssertionCert = new ClientAssertionCertificate(ConfigurationManager.AppSettings["ClientApplicationId"], clientAssertionCertPfx);
}
public static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
var result = await context.AcquireTokenAsync(resource, AssertionCert);
return result.AccessToken;
}
public static string GetKeyVaultSecret(string secretNode)
{
var secretUri = string.Format("{0}{1}", ConfigurationManager.AppSettings["VaultUrl"] + "/secrets/", secretNode);
GetCertification();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessToken));
return keyVaultClient.GetSecretAsync(secretUri).Result.Value;
}
}
}
Program. cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace KeyVaultCertification
{
public class Program
{
static void Main(string[] args)
{
string sourceUrl = AzureKeyVaultCertificationHelper.GetKeyVaultSecret("SourceUrl");
Console.WriteLine(sourceUrl);
}
}
}
Provide certificate Thumbprint, Azure AD App client ID, and Vault URL.
app. config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
<appSettings>
<add key="ThumbPrint" value="4444B4EDC4BFA4444444C44E4FF53B13B444C444"/>
<add key="ClientApplicationId" value="abcdef-ghij-413e-klmn-1922ff69xyz"/>
<add key="VaultUrl" value="https://RKkeyvault.azure.net"/>
</appSettings>
</configuration>
Output