In the previous post we saw how to connect to Azure Key Vault from Azure Functions. We used the Application Id and Secret to authenticate with the Azure AD Application. Since the general recommendation is to use certificate-based authentication, in this post, we will see how we can use certificates to authenticate from within an Azure Function.

First, we need to create an Azure AD application and set it up to use certificate-based authentication. Create a new service principal for the AD application and associate that with the Azure Key Vault. Authorize the AD application with the permissions required. In this case, I am providing all access to keys and secrets.

1
2
3
4
5
6
7
8
9
10
11
12
$certificateFilePath = "C:\certificates\ADTestVaultApplication.cer"
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certificate.Import($certificateFilePath)
$rawCertificateData = $certificate.GetRawCertData()
$credential = [System.Convert]::ToBase64String($rawCertificateData)
$startDate= [System.DateTime]::Now
$endDate = $startDate.AddYears(1)
$adApplication = New-AzureRmADApplication -DisplayName "CertAdApplication" -HomePage  "http://www.test.com" -IdentifierUris "http://www.test.com" -CertValue $credential  -StartDate $startDate -EndDate $endDate

$servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $adApplication.ApplicationId

Set-AzureRmKeyVaultAccessPolicy -VaultName 'RahulKeyVault' -ServicePrincipalName $servicePrincipal.ServicePrincipalNames[0] -PermissionsToSecrets all -PermissionToKeys all

Create an Azure Function App under your subscription as shown below. You can also use the same application created in the previous post (if you did create one).

Azure Function New App

In the Function Apps page, select the app just created. Add a new function like in the last post. Selecting the Function App shows the available set of actions. Under the Platform Features tab we can upload the SSL certificates first and then update the Application Certificates to make the certificate available for the function.

Azure Function Platform Features

Upload the certificate by selecting it from your folder system.

Azure Function Upload Certificate

For the certificate to be available for use in the Azure Functions an entry should be present in Application Settings. Under Application Settings in the Platform Features tab add App settings key and value - WEBSITE_LOAD_CERTIFICATES and the certificate thumbprint This makes the certificate available for consumption within the function. Multiple thumbprints can be specified comma separated if required.

Azure Function Certificates App Settings

Using a certificate to authenticate with the Key Vault is the same as we have seen before.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

private const string applicationId = "AD Application ID";
private const string certificateThumbprint = "Certificate Thumbprint";

public async static Task Run(TimerInfo myTimer, TraceWriter log)
{
    var keyClient = new KeyVaultClient(async (authority, resource, scope) =>
{
    var authenticationContext = new AuthenticationContext(authority, null);
    X509Certificate2 certificate;
    X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    try
    {
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection certificateCollection = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
        if (certificateCollection == null || certificateCollection.Count == 0)
        {
            throw new Exception("Certificate not installed in the store");
        }

        certificate = certificateCollection[0];
    }
    finally
    {
        store.Close();
    }

    var clientAssertionCertificate = new ClientAssertionCertificate(applicationId, certificate);
    var result = await authenticationContext.AcquireTokenAsync(resource, clientAssertionCertificate);
    return result.AccessToken;
});

    var secretIdentifier = "https://rahulkeyvault.vault.azure.net/secrets/mySecretName";
    var secret = await keyClient.GetSecretAsync(secretIdentifier);

    log.Info($"Secret Value: {secret}");
}

Make sure you add in the project.json as seen in the previous post to enable the required NuGet packages. The Azure function now uses the certificate to authenticate with Key Vault and retrieve the secret.

Hope this helps!

Comments