带有 C# 和 ASP.NET Core 接口的动态键值对存储类

问题描述 投票:0回答:1

假设我想要一个接口和类来存储来自外部提供商(例如 Azure KeyVault)的键值对。

我有这个界面:

namespace SampleNamespace.Interfaces 
{
    public interface IKeyVault 
    {
        string string1 { get; }
        string string2 { get; }
        string string3 { get; }
        //... more member variables
        string stringN { get; }

        //initialize the class with the values from the keyvault
        public Task<bool> Initialize();
    }
}

然后我就有了这个接口的实现:

namespace SampleNamespace.Classes 
{
    public class AzureKeyVault : IKeyVault 
    {
        string string1 { get; private set; }
        string string2 { get; private set; }
        string string3 { get; private set; }
        ...
        string stringN { get; private set; }

        public async Task<bool> Initialize() 
        {
            if (AzureKeyVaultProvider.InitializeClient("somekey")) 
            {
                string1 = await AzureKeyVaultProvider.GetSecret("string1");
                //...more fetches
                stringN = await AzureKeyVaultProvider.GetSecret("stringN");

                return true;
            }

            return false;
        }
    }
}

您可以想象这些获取需要一些时间(对于 6 个值,大约需要 4 秒)。并非每个使用和初始化该类的服务都需要每个值。此外,将来可能会添加一些其他值到远程保管库(无论是什么,因此是接口)。如何使变量动态化,并使类的每个初始化器仅获取和初始化它需要的变量?

我尝试根据调用服务制作许多初始化程序,但这使得接口的使用违反直觉。另外,我不想实现异步获取每个值的 getter 函数。我想在我的代码中的一处初始化所需的。

c# asp.net-core interface azure-keyvault
1个回答
0
投票

也许这更多的是评论而不是答案,但作为 Key Vault SDK for .NET 的当前所有者,我可以告诉您,根据设计,您无法在一次调用中获取多个秘密值。列出和获取秘密是不同的操作,需要单独的权限,即

secret/list
secret/get

如果您知道在某些时候您将需要多个值,我们实际上建议您以这种方式存储它们。这实际上很常见。您可以将类序列化为 JSON,并将其作为 JSON blob 存储和检索,例如:

SecretClient client = new SecretClient(vaultUri, credential);
KeyVaultSecret secret = await client.GetSecretAsync(secretName);

Secrets secrets = JsonSerializer.Deserialize(secret.Value, SecretsGenerationContext.Default.Secrets)
    ?? throw new Exception("Corrupted secret");
Console.WriteLine($"Secret1: {secrets.Secret1}");
Console.WriteLine($"Secret2: {secrets.Secret2}");

class Secrets
{
    public string? Secret1 { get; set; }
    public string? Secret2 { get; set; }
}

[JsonSerializable(typeof(Secrets))]
[JsonSourceGenerationOptions(PropertyNameCaseInsensitive = true, WriteIndented = true)]
partial class SecretsGenerationContext : JsonSerializerContext {};

与单独检索每个相比,这种方式会快得多。如果您使用的是旧版访问策略,则无论如何都无法对单个机密设置权限。尽管这应该可以通过 RBAC 实现,但您可能会发现使用单独的 Key Vault 管理单独的应用程序更容易,这也可能有助于降低成本,即使 Key Vault 已经相当便宜。

© www.soinside.com 2019 - 2024. All rights reserved.