Azure KeyVault integration for Azure Function v2

Currently the most asked feature on UserVoice for Azure Function is integration of Azure KeyVault. Unfortunately this is not yet available out of the box. In addition the solutions that are suggested are not very integrative as they do not support AutoResolve properties or can not be used for connection strings on trigger or bindings.

Welcome Willezone.Azure.WebJobs.Extensions.AzureKeyVault!

Since the configuration in Azure Function v2 relies on the Microsoft.Extensions.Configuration package we are able to actually extend this to also support Azure KeyVault. In order to integrate the Azure KeyVault configuration provider we need to use the existing IConfiguration and extend it with provider. After that the configuration instance must be replaced in the Service Provider.

static IWebJobsBuilder AddAzureKeyVault(this IWebJobsBuilder builder, 
    Func<ConfigurationBuilder, IKeyVaultClient> configure)
{
    var configurationBuilder = new ConfigurationBuilder();
    var descriptor = builder.Services.FirstOrDefault(d => d.ServiceType == typeof(IConfiguration));
    if (descriptor?.ImplementationInstance is IConfigurationRoot configuration)
    {
        configurationBuilder.AddConfiguration(configuration);
    }

    configurationBuilder.AddAzureKeyVault(....);

    var config = configurationBuilder.Build();
    builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), config));
    return builder;
}

How to configure

Once the package is added to the function project, a WebJobsStartup class is needed to register and configure the extension.

This is an example WebJobsStartup class

using ExampleFunction;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Willezone.Azure.WebJobs.Extensions.AzureKeyVault;

[assembly: WebJobsStartup(typeof(Startup))]
namespace ExampleFunction
{
    public class Startup : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {
            // Create temporary service provider to access configuration.
            var tempProvider = builder.Services.BuildServiceProvider();
            var config = tempProvider.GetRequiredService<IConfiguration>();
            builder.AddAzureKeyVault(config["AzureKeyVault_Uri"]);
        }
    }
}

Access to Azure KeyVault is possible either via client id & secret or using Managed Service Identity!

Using the extension

Once the extension is registered and configured Azure KeyVault will also be used to get values for AutoResolve or AppSettings properties. In addition we can use the AzureKeyVaultClient binding to get the KeyVaultClient for advanced usage.

Example

[FunctionName("Function1")]
public static void Run(
    [BlobTrigger("%blobpath%", Connection = "storageconnection")]Stream myBlob,
    string name,
    ILogger log,
    [AzureKeyVaultClient]IKeyVaultClient client)
{
    log.LogInformation($"API Version: {client.ApiVersion}");
    log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name}");
}

In this example the values for blobpath and storageconnection are now also pulled from Azure KeyVault, if there are no values present in the normal config. The AzureKeyVaultClient Attributes binds an instance of an IKeyVaultClient into the function for advanced usage.

Package & Source

The package is available on Nuget and the source for this can be found on Github. Feel free to fork it or open issues!