Reputation: 31
We are using Azure Functions, which require access to at least 1 Azure Storage location. The Azure Storage Location must support tables, So Azure AD Auth is out. The Connection String for the Storage account, with credential information, must be available to the Function on the environment. Good security practices dictate that we rotate the key with some frequency. We are currently storing keys in Key Vault, and want to continue doing so, rather than storing keys in the Azure Portal.
Are we correct that Azure AD authentication is not valid here since the tokens it produces are not able to be used with tables, which Functions requires?
It would seem that the ideal approach would be to add a new setting in Microsoft.Azure.Storage.CloudStorageAccount
,
internal const string AccountKeyVaultLocationSettingString = "AccountKeyVaultLocation";
And then add logic to ParseImpl so that a KeyVault URL representing the secret could be passed into this method, and it would query the key from there.
Another option would be to over-ride Microsoft.Azure.WebJobs.Script.Scaling.StorageConnectionString
(and similar connection string settings) so that it will query KeyVault.
Could this be added to the Storage Library? What would be an ETA? Would you welcome contribution on this?
Upvotes: 0
Views: 519
Reputation: 12153
In fact , using this way, you can get your Connection String successfully without version numbers . However, as you said, webapp will load appsettings once and it will not be updated even though your Connection String rotated in Key Vault: We should restart webapp to load latest Connection String version from KV .
You can use Azure app configuration which is a centralized configuration service and you can read latest Connection String from KV easily without restarting your webapp. However, you should care about the security of Azure app configuration connection string ,if you need to rotate it frequently , we goes back.
Maybe using Azure function MSI to get connection string from KV is the best way I know here, try the code below :
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault.Models;
namespace FunctionWithAppConfig
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://vault.azure.net");
KeyVaultClient kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
SecretBundle sec = await kv.GetSecretAsync("<your key vault url without version >");
var StorageConn = sec.Value;
// connect to your storage ...
return new OkObjectResult(StorageConn);
}
}
}
Upvotes: 0