来自 KeyVault 的 Azure Function BlobTrigger 连接

Azure Function BlobTrigger connection from KeyVault

总结:我可以使用 KeyVault 为 Blob 存储绑定提供连接字符串功能吗?

我最近将所有连接字符串和机密从 Azure Function 应用程序设置中移到了 KeyVault 中。这包括我引用的各种存储帐户的连接字符串。我现在正在处理 Azure Blob 存储绑定,但似乎 (per the docs) 引用连接字符串的所有方式都解析为应用程序级别设置。

我希望不必在两个不同的地方拥有这个秘密。有没有办法在 KeyVault 中指定存储帐户连接字符串?

如果您询问是否可以执行以下操作:

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

然后存储 StorageConnectionAppSetting 使其指向 KeyVault 实例(并且不容易访问连接字符串),那么目前恐怕不可能。

当然可以像这样手动获取连接字符串:

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

然后连接到 Blob "manually"(因此不会使用绑定),但我想这对你来说可能是不行的。

另一个问题是 - 将连接字符串存储在 KV 中的原因是什么?是怕存储在功能应用的应用设置里被人看到吗?还是因为您不想将其存储在 CI/CD 管道中?

我可能处于不同的切线,但我相信我同意@ThatCreole 的观点,这是一种痛苦。集中配置和从已部署代码中删除秘密不仅仅与您在 CI/CD 管道中替换它的位置有关。如果文件系统遭到破坏,访问配置文件会进一步破坏您的基础设施。借助 Azure,我们能够使用托管服务标识,它通过系统 运行 和 Azure 活动目录在底层硬件上建立信任。这消除了在任何时候将任何机密存储在配置中的需要,包括访问 Key Vault 的机密。 Azure 功能可以利用这一点,但这仅对应用程序的 startup/runtime 有帮助。触发器仍然依赖于功能启动甚至到达那个点,这会导致一点点暴露表面。

我唯一能做的就是为其权限集极其有限的触发器创建一个 RBAC。将其添加为函数中的触发器,然后让函数在启动时通过密钥库加载扩展权限 RBAC。这是一个不幸的解决方法,但我看不到另一种方法可以在维护我们系统安全的同时做到这一点。

我创建了一个 nuget 包,它将 Azure KeyVault 集成到 Azure Functions 中,支持连接字符串等。这实际上现在可以通过 Azure Function v2 实现,因为它在内部使用 Microsoft.Extensions.Configuration。我们可以利用它并使用 Azure Key Vault 扩展配置。因此,您需要创建一个 WebJobsStartup class,从 WebjobsBuuilder 服务提供商获取 IConfiguration 并另外使用 Azure KeyVault 重新创建它。

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

您可以在 https://github.com/BorisWilhelms/azure-function-keyvault 找到它的来源。