2017-09-20 1 views
1

エンティティフレームワークのWeb API接続文字列を格納するためにAzure Key Vaultを使用しようとしています。理想的には、キーボルトのナゲットパッケージとデータアクセスコードの結合を避けたいと思います。エンティティフレームワーク「DefaultConnection」アプリケーション設定のAzureキーボルト

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

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

私のコードは、Web設定から接続文字列を取得し、パラメータなしのコンストラクタを使用しています:私dbContextクラスには2つのコンストラクタを持っています。私は新しいMyDbContextオブジェクトをインスタンス化するいくつかの場所があり、注入を使用して解決策を禁止しています。

私が取ったルートは、接続文字列ロケータと私のdbcontext上の静的プロパティを設定することです:

public interface IConnectionStringLocator 
{ string Get(); } 

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

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

マイウェブ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; 
     } 
    } 
} 

私はこれを公表し、それが動作しますが、それは右の「感触」はありません。

もう1つの選択肢は、この記事https://blog.falafel.com/keeping-secrets-with-azure-key-vault/に従うことですが、KeyVault APIパッケージとデータアクセスを結合する必要があります。

フィードバックと方向を探しています。私は、キーボルトを使用する理由は、接続文字列を介してSQLデータベースにアクセスすることなく、アプリケーションの設定をオンラインで見ることができる青信号の管理者がいるためです。新しいMSI実装と

KeyVaultリソースは:https://github.com/Azure-Samples/app-service-msi-keyvault-dotnet/

答えて

0

ここで私はその上にケースの誰つまずくで、これを解決する方法です。

最初にキーボルトから値を取得しようとする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")) 
    {...} 
関連する問題