Securing the private key utilized by an Azure Function

Viewed 1321

I have an Azure Function that is copying files from a SFTP location to an Azure Blob. The Private Key / SSH Key needed to establish connection to SFTP is now part of app settings json - as the solution is still constrained to PoC/Development phase.

Before I line this up for Production I have to secure the aforementioned private key.

Is Azure Key Vault an optimal candidate where I can store the private key. And provision the Azure Function dynamic access to this key via AD ?

Or is there an alternative approach from an Azure PaaS perspective?

1 Answers

I personally have not accessed secrets from the Azure Key Vault from an Azure Function. I find that storing the secrets/keys in the Function App's application settings have suited me just fine thus far.

However, you may find this useful: Retrieve Azure Key Vault Secrets using Azure Functions and Managed Service Identity After following the steps described at that page to properly set up the vault, you would access from the Function like so:

using System.Net;
using System.Configuration;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.KeyVault.Models;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;
using System.Text;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    SecretRequest secretRequest = await req.Content.ReadAsAsync<SecretRequest>();

    if(string.IsNullOrEmpty(secretRequest.Secret))
        return req.CreateResponse(HttpStatusCode.BadRequest, "Request does not contain a valid Secret."); 

    log.Info($"GetKeyVaultSecret request received for secret {secretRequest.Secret}");        

    var serviceTokenProvider = new AzureServiceTokenProvider();

    var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(serviceTokenProvider.KeyVaultTokenCallback));            

    var secretUri = SecretUri(secretRequest.Secret);
    log.Info($"Key Vault URI {secretUri} generated");
    SecretBundle secretValue; 
    try
    {
      secretValue = await keyVaultClient.GetSecretAsync(secretUri);
    }
    catch(KeyVaultErrorException kex)
    {
        return req.CreateResponse(HttpStatusCode.NotFound, $"{kex.Message}");
    }
    log.Info("Secret Value retrieved from KeyVault.");

    var secretResponse = new SecretResponse {Secret = secretRequest.Secret, Value = secretValue.Value};

    return new HttpResponseMessage(HttpStatusCode.OK) {
        Content = new StringContent(JsonConvert.SerializeObject(secretResponse), Encoding.UTF8, "application/json")};


}

public class SecretRequest
{
    public string Secret {get;set;}
}

public class SecretResponse
{
    public string Secret {get; set;}
    public string Value {get; set;}
}

public static string SecretUri(string secret)
{
   return $"{ConfigurationManager.AppSettings["KeyVaultUri"]}/Secrets/{secret}";
}
Related