5

Summary: Can I use KeyVault to supply Function the Connection string to a Blob storage binding?

I recently moved all my connect strings and secrets out of the Azure Function app settings and into KeyVault. This included the connection strings to the various storage accounts I reference. I now am working on a Azure Blob storage binding but it seems (per the docs) that all the ways there are to reference a connection string resolves to an app level setting.

I'd love to not have to have this one secret in two separate places. Is there a way to specify the storage account connection string ala KeyVault?

ThatCreole
  • 495
  • 1
  • 7
  • 17
  • see this answer, it could be useful in your case: https://stackoverflow.com/a/50061836/4167200 – Thomas Apr 29 '18 at 20:58

3 Answers3

2

I may be on a different tangent but I believe that I agree with @ThatCreole with this being a pain. Centralized configuration and removing secrets from deployed code is not just about where you replace it in your CI/CD pipeline. Should the file system be compromised, accessing the configuration files allows for further compromise of your infrastructure. With Azure we have the ability to use Managed Service Identity which creates a trust on the underlying hardware with the system running and azure active directory. This removes the need for any secrets to be stored in the configurations at any one point, including the ones to access Key Vault. Azure functions can leverage this but this only helps at startup/runtime of the application. The trigger is still relied upon for the function to fire up and even get to that point, which causes a small bit of exposure surface.

The only bit I have been able to do is create an RBAC for the trigger that is extremely limited in its permission set. Add that as the trigger in the function and then have the function load up the extended permission RBAC through key vault on startup. Its an unfortunate workaround but I cannot see another way to do it while maintaining security of our systems.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
CoreyZ
  • 189
  • 2
  • 3
  • 11
1

If you're asking whether you can do the following:

[FunctionName("ResizeImage")]
public static void Run(
   [BlobTrigger("sample-images/{name}", Connection = "StorageConnectionAppSetting")] Stream image, 
   [Blob("sample-images-md/{name}", FileAccess.Write)] Stream imageSmall)
{
   ....
}

And then storing StorageConnectionAppSetting so it points to the KeyVault instance(and not easily accessible connection string), then I'm afraid it's not currently possible.

Of course it'd possible to obtain your connection string manually like this:

var azureServiceTokenProvider = new AzureServiceTokenProvider();
var kvClient = new KeyVaultClient(new  KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback), client);                
string blobConectionString = (await 
kvClient.GetSecretAsync("some"secret")).Value;

And then connecting to Blob "manually"(so binding would not be used), but I guess it could be a no-go for you.

Other question is - what is the reason to store connection string in KV? Is that because you're afraid that somebody will look at it when stored in App Settings of a Function App? Or is it because you you don't want to store it in your CI/CD pipeline?

kamil-mrzyglod
  • 4,948
  • 1
  • 20
  • 29
  • Thanks. My reasoning is the latter. The way I'm using KeyVault now is as a single abstracted place where all settings that give access to resources are held. This keeps those things totally out of the CI/CD pipeline and is one less thing to worry about. Secrets are cached so the overall load we put on KeyVault is low. – ThatCreole May 04 '18 at 16:27
  • If you're using VSTS it's also possible to secure variables, so noone is able to restore them once saved - that way there's no need to use KV. – kamil-mrzyglod May 04 '18 at 17:18
1

I have created a nuget package that integrates Azure KeyVault into Azure Functions with support for connection strings and so on. This is actually now possible with Azure Function v2, since it uses Microsoft.Extensions.Configuration internaly. We can make use of that and extend the configuration with Azure Key Vault. Therefor you need to create a WebJobsStartup class, get the IConfiguration from the WebjobsBuuilder Service Provider and recreate it with Azure KeyVault in addition.

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;
}

You can finde source for this at https://github.com/BorisWilhelms/azure-function-keyvault.

Boris Wilhelms
  • 621
  • 6
  • 9
  • It looks like as of .net core 3.1 (and possible .net core 3.0) this will no longer work because the `descriptor?.ImplementationInstance` will be null. Issue opened in dotnet/extensions [link](https://github.com/dotnet/extensions/issues/2837) – Dmitri M Jan 08 '20 at 20:54