当前位置: 首页 > 知识库问答 >
问题:

带有实体框架“DefaultConnection”应用程序设置的Azure密钥存储库

王声
2023-03-14

我试图使用Azure Key Vault来存储实体框架的web api连接字符串。理想情况下,我希望避免将key vault nuget包与我的数据访问代码耦合。我的dbContext类有两个构造函数:

public MyDbContext() : base("DefaultConnection")
{ . . . }

public MyDbContext(string connectionString) : base(connectionString)
{ . . . }

我的代码使用了从web配置中获取连接字符串的无参数构造函数。我在某些地方实例化了一个新的MyDbContext对象,这禁止了使用注入的解决方案。

我采用的路线是在我的dbcontext上设置一个带有连接字符串定位器的静态属性:

public interface IConnectionStringLocator
{ string Get(); }

public class DefaultConnectionStringLocator : IConnectionStringLocator
{
    public string Get()
    {
        return "DefaultConnection";
    }
}

public static IConnectionStringLocator ConnectionStringLocator { get; set; } =
    new DefaultConnectionStringLocator();

我的web api项目有用于检索密钥库机密的nuget包。因此,在我的global.asax文件中,我有以下内容:

protected void Application_Start()
{
    MyDbContext.ConnectionStringLocator = new ConnectionStringLocator("DefaultConnection");
}

public class ConnectionStringLocator : IConnectionStringLocator
{
    private  readonly string _connectionStringName;

    public ConnectionStringLocator(string connectionStringName)
    {
        this._connectionStringName = connectionStringName;
    }
    public string Get()
    {
        var keyVaultName = WebConfigurationManager.AppSettings.Get("KeyVaultName");
        if (keyVaultName == "develop")
            return _connectionStringName;
        else
        {
            AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient =
                new KeyVaultClient(
                    new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
            var defaultConnectionSecret =
                keyVaultClient.GetSecretAsync($"https://{keyVaultName}.vault.azure.net/secrets/{this._connectionStringName}");

            return defaultConnectionSecret.Result.Value;
        }
    }
}

我发表了这篇文章,它很有效,但它“感觉”不对。

另一个选择是遵循本文https://blog.falafel.com/keeping-secrets-with-azure-key-vault/但这需要我将KeyVault API包与我的数据访问连接起来。

我在寻找反馈和方向。我应该补充的是,我想使用key vault的原因是,它允许我拥有azure管理员,他们可以在线查看应用程序设置,而无需通过连接字符串访问sql数据库。

具有新MSI实现的KeyVault资源:https://github.com/azure-samples/app-service-msi-keyvault-dotnet/

共有1个答案

萧胜
2023-03-14

以下是我如何解决这个问题的,以防其他人绊倒。

创建了一个ConfigurationManager类,该类首先尝试从密钥库中获取值,但失败后使用WebConfigurationManager读取应用程序设置。

    public static class ConfigurationManager
{
    public static string KeyVaultName => WebConfigurationManager.AppSettings.Get("KeyVaultName");
    private static readonly Dictionary<string, string> ConfigurationCache = new Dictionary<string, string>();
    private static SecretBundle GetSecret(string secretName, string vaultName = null)
    {
        AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
        var keyVaultClient =
            new KeyVaultClient(
                new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
        var secretUri = $"https://{vaultName ?? KeyVaultName}.vault.azure.net/secrets/{secretName}";
        var secret = keyVaultClient.GetSecretAsync(secretUri);
        return secret.Result;
    }

    public static string GetAppSettingValue(string secretName, string vaultName = null)
    {
        vaultName = vaultName ?? KeyVaultName;
        string key = $"{vaultName}:{secretName}";
        string value;

        if (ConfigurationCache.TryGetValue(key, out value))
            return value;

        if (string.IsNullOrEmpty(vaultName) || vaultName == "develop")
        {
            value = WebConfigurationManager.AppSettings.Get(secretName);
            ConfigurationCache.Add(key, value);
            return value;
        }

        var secret = GetSecret(secretName);
        value = secret.Value;
        ConfigurationCache.Add(key, value);
        return value;
    }

    public static void SetAppSettingValue(string secretName, string value, string vaultName = null)
    {
        vaultName = vaultName ?? KeyVaultName;
        string key = $"{vaultName}:{secretName}";

        if (ConfigurationCache.ContainsKey(key))
            ConfigurationCache[key] = value;
        else
        {
            WebConfigurationManager.AppSettings[key] = value;
            ConfigurationCache.Add(key, value);
        }


    }
    public static string GetConnectionStringValue(string secretName, string vaultName = null)
    {
        vaultName = vaultName ?? KeyVaultName;
        string key = $"{vaultName}:{secretName}";
        string value;

        if (ConfigurationCache.TryGetValue(key, out value))
            return value;

        if (string.IsNullOrEmpty(vaultName) || vaultName == "develop")
        {
            value = WebConfigurationManager.ConnectionStrings[secretName].ConnectionString;
            ConfigurationCache.Add(key, value);
            return value;
        }

        var secret = GetSecret(secretName);
        value = secret.Value;
        ConfigurationCache.Add(key, value);
        return value;
    }
}

然后,在我的dbcontext类中,我调用ConfigurationManager.GetConnectionStringValue(“DefaultConnection”)。

    public MyDbContext()
        : base(ConfigurationManager.GetConnectionStringValue("DefaultConnection"))
    {...}
 类似资料:
  • 我的web api项目有用于检索密钥库机密的nuget包。因此,在我的global.asax文件中,我有以下内容: 我发表了这篇文章,它起作用了,但它“感觉”不对。 另一个选择是遵循本文https://blog.falafel.com/keeping-secrets-with-azure-key-vault/的内容,但这需要我将KeyVault API包与数据访问耦合起来。

  • 我使用HTTPTrigger创建了一个简单的Azure函数,该函数通过Azure中的门户返回密钥集的秘密值。该值存储为 https://medium.com/statuscode/getting-key-vault-secrets-in-azure-functions-37620FD20A0B

  • 我做错了什么试图在我的功能v2应用程序设置以下设置。 在函数中读取这些内容,我得到的是完整字符串,而不是我所期望的密钥库中的连接字符串。 我需要多走几步吗?

  • 我在大多数文章中读到,需要在Azure中部署应用程序,这样应用程序才能以编程方式访问存储在Azure密钥库中的秘密。 有没有一种方法可以不在azure中部署应用程序,并且仍然能够通过使用客户端id和客户端机密或证书来访问azure密钥库以获取机密?

  • 问题内容: 我试图从存储过程中获取简单的输出 和我的MVC 但是当我编译时,在以下部分出现错误: 方法’sp_getrandomnumber’的重载没有接受1个参数 名称“ randoms”在当前上下文中不存在 提前非常感谢希什 问题答案: 您的问题是您的SPROC输出是一个int。 请参见Scott Gu的文章中的以下引用。 “ LINQ to SQL将SPROC中的“ out”参数映射为参考参