2017-09-20 4 views
1

Ich versuche, Azure Key Vault zum Speichern meiner Web-API-Verbindungszeichenfolgen für Entity Framework zu verwenden. Im Idealfall möchte ich vermeiden, die Key-Vault-Nuget-Pakete mit meinem Datenzugriffscode zu koppeln. Meine DbContext Klasse hat zwei Konstruktoren:Azure Key Vault mit Entity Framework App-Einstellung "DefaultConnection"

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

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

Mein Code Verwendung des parameterlosen Konstruktor macht, die die Verbindungszeichenfolge aus dem Web-Config wird. Es gibt einige Stellen, wo ich ein neues MyDbContext-Objekt instanziiere, das eine Lösung verhindert, die Injektion verwendet.

Die Route, die ich nahm, ist eine statische Eigenschaft auf meinem DbContext mit einem Verbindungszeichenfolge-Locator einzustellen:

public interface IConnectionStringLocator 
{ string Get(); } 

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

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

Mein Web api Projekt hat die nuget Pakete für die wichtigsten Gewölbe Geheimnisse abruft. Also in meinem Global.asax-Datei habe ich dies:

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

ich diese veröffentlicht und es funktioniert, aber es funktioniert nicht „fühlen“ rechts.

Eine andere Möglichkeit wäre, diesem Artikel https://blog.falafel.com/keeping-secrets-with-azure-key-vault/ zu folgen, aber ich würde die KeyVault-API-Pakete mit meinem Datenzugriff verbinden müssen.

Ich bin auf der Suche nach Feedback und Richtung. Ich sollte hinzufügen, dass der Grund, warum ich den Schlüsseltresor verwenden möchte, darin besteht, dass ich Azure-Administratoren haben kann, die die Anwendungseinstellungen online sehen können, ohne über die Verbindungszeichenfolge Zugriff auf die SQL-Datenbank zu haben.

KeyVault Ressource mit der neuen MSI Implementierung: https://github.com/Azure-Samples/app-service-msi-keyvault-dotnet/

Antwort

0

Hier ist, wie ich dieses Problem gelöst, falls jemand stolpert auf sich.

Es wurde eine ConfigurationManager-Klasse erstellt, die zuerst versucht, den Wert aus dem Schlüsseltresor abzurufen. Bei einem Fehler wird jedoch der WebConfigurationManager zum Lesen der App-Einstellungen verwendet.

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

Da ist in meinem DbContext Klasse Ich rufe Configurationmanager.GetConnectionStringValue ("DefaultConnection").

Verwandte Themen