In the old days, we used to access the Azure Key Vaults using 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 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 certificate in local machine (In current scenario we are storing certificate in local machine, we can register 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 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 Azure AD App and Assign certificate
The below PowerShell script will import the certificate, create 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 5 – 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 Certificate Thumbprint function.
$certificate.Thumbprint
Now, we have done all the necessary configuration for registering the certification with Azure, create an application to access the key vaults.
Step 6 – 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 and provide private key and finish the wizard, this will register certificate on a local machine. We can find register certificate in MMC (Microsoft Management Console).
Search for MMC and open,
Open 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 7 - Creating Application to access the key vaults
Here, I am creating a simple Visual Studio console application for demo purpose.
Create 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