webentwicklung-frage-antwort-db.com.de

Wie kann ich die Verbindungszeichenfolge aus Azure KeyVault entfernen?

Eine hypothetische Website verbindet sich derzeit mit:

public SqlConnection CreateConnection()
{
   DbConnection connection = new SqlConnection();
   connection.ConnectionString = GetConnectionString();
   connection.Open();

   return connection;
}

Wo die magische Verbindungszeichenfolge in web.config Gespeichert ist:

String GetConnectionString()
{
   //Get the connection string info from web.config
   ConnectionStringSettings cs = ConfigurationManager.ConnectionStrings["db"];

   if (cs == null)
      throw new Exception("Could not locate DB connection string");

   return cs.ConnectionString;
}

Jetzt möchte ich die Verbindungszeichenfolge aus der Datei web.config in Azure KeyVault verschieben. Wie ruft man etwas aus dem Azure-Schlüsseldepot ab?

String GetConnectionString()
{
   //Get the connection string info from Azure KeyVault
   String connectionString = GetAzureSecret("dbConnectionString");

   if (String.IsNullOrWhitespace(connectionString)
      throw new Exception.Create("Could not connection string of Azure Key Vault");

   return connectionString;
}

Abgesehen davon, dass ich gerade die benutzerfreundliche Azure-API erfunden habe. Was ist die tatsächliche API?

Ungetesteter Versuch

string GetAzureSecret(string key)
{
    KeyVaultClient vault = new KeyVaultClient();
    vault.OnAuthenticate += VaultClientAuthenticate;

    var sec = await vault.GetSecretAsync(Key);
    return sec.Value;
}

public static async Task<string> VaultClientAuthenticate(string authority, string resource, string scope)
{
   String clientID = "8675209";
   String clientSecret = "correct battery horse pencil";

   var authContext = new AuthenticationContext(authority);
   ClientCredential clientCred = new ClientCredential(clientID, clientSecret);
   AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);

   if (result == null)
      throw new Exception("Could not acquire token");

   return result.AccessToken;
}

Bonus Lesung

20
Ian Boyd

Was ist die tatsächliche API?

Wir könnten die GetSecret API verwenden, um einen Wert zu erhalten.

Vorbereitung:

Registry Azure Active Directory-Anwendung und Rolle zuweisen

Schritte:

1.Erstellen Sie KeyVault und fügen Sie ein Geheimnis aus dem Azure-Portal hinzu

enter image description here

2.Zugriffsrichtlinie konfigurieren

enter image description here

3.Holen Sie sich das Zugriffstoken

 var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
            ClientCredential clientCredential = new ClientCredential(appId, secretKey);
            var tokenResponse =await context.AcquireTokenAsync("https://vault.Azure.net", clientCredential);
            var accessToken = tokenResponse.AccessToken;
            return accessToken;

Hinweis : Die Ressource für Keyvault ist https://vault.Azure.net

4. Test mit Fiddler

enter image description here

Das können wir auch mit SDK ganz einfach machen:

1.Erstellen Sie ein Konsolenprojekt und eine Utils.cs-Datei

public static string EncryptSecret { get; set; }
        static string appId = "Application ID";
        static string secretKey = "Secert key";
        static string tenantId = "TenantId";

        public static async Task<string> GetAccessToken(string azureTenantId,string azureAppId,string azureSecretKey)
        {

            var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
            ClientCredential clientCredential = new ClientCredential(appId, secretKey);
            var tokenResponse =await context.AcquireTokenAsync("https://vault.Azure.net", clientCredential);
            var accessToken = tokenResponse.AccessToken;
            return accessToken;
        }

2.Fügen Sie den folgenden Code in die Hauptfunktion ein und testen Sie ihn.

enter image description here

datei packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Hyak.Common" version="1.0.2" targetFramework="net452" />
  <package id="Microsoft.Azure.Common" version="2.0.4" targetFramework="net452" />
  <package id="Microsoft.Azure.Common.Dependencies" version="1.0.0" targetFramework="net452" />
  <package id="Microsoft.Azure.KeyVault" version="1.0.0" targetFramework="net452" />
  <package id="Microsoft.Bcl" version="1.1.9" targetFramework="net452" />
  <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net452" />
  <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net452" />
  <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.13.9" targetFramework="net452" />
  <package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
</packages>

Wir können auch mehr Informationen von CtrlDot erhalten document .

24
Tom Sun

Ich habe nichts gegen Key Vault (ich denke, es ist ein großartiges Produkt!), Aber ich kann nicht anders, als zu glauben, dass Sie dies überarbeiten.

Ich würde einfach die integrierte Funktion Anwendungseinstellungen im Azure App Service verwenden :

Verbindungszeichenfolgen

Bei .NET-Apps werden diese Verbindungszeichenfolgen zur Laufzeit in die Einstellungen der .NET-Konfiguration connectionStrings eingefügt. Überschreiben vorhandener Einträge, bei denen der Schlüssel dem Namen der verknüpften Datenbank entspricht.

Web App → Anwendungseinstellungen → Verbindungszeichenfolgen → Fügen Sie eine Verbindungszeichenfolge hinzu und nennen Sie sie db.

String GetConnectionString()
{
   // Get the Connection String from Application Settings (App Service) 
   // with graceful fallback to web.config
   string cs = WebConfigurationManager.ConnectionStrings["db"].ConnectionString;

   if (cs == null)
      throw new Exception("Could not locate DB connection string");

   return cs;
}

Was ist der Unterschied zwischen dem WebConfigurationManager und dem ConfigurationManager?

Update Mai 2018:

Seit Managed Service Identity eine Sache geworden ist, erfordert der Erwerb eines Zugriffstokens nicht mehr, dass Geheimnisse (Dienstprinzipalanmeldeinformationen) in Ihrem Dienst gespeichert werden, um auf Key Vault zuzugreifen, was ein viel besseres Angebot ist. Hier ist ein Node.js-Beispiel, um diese Antwort ein wenig aufzupeppen:

// Get an access token from Managed Service Identity
// on an Azure IaaS VM
async function getAccessTokenWithMSI() {
  let msi = await axios.get('http://169.254.169.254/metadata/identity/oauth2/token',
    {
      params: {
        'api-version': '2018-02-01',
        'resource': 'https://vault.Azure.net'
      },
      headers: {
        'Metadata': 'true'
      },
      timeout: 2000
    });

  return msi.data.access_token;
}

und dann:

// Get a secret from Key Vault
async function getSecret(accessToken, secretUrl) {
  let response;
  try {
    response = await axios.get(secretUrl,
      {
         params: { 'api-version': '2016-10-01' },
         headers: { 'Authorization': `Bearer ${accessToken}` },
         timeout: 3000
      });
  }
  catch (e) {
    console.log('\nError calling Key Vault:,
        e.response.status, e.response.statusText, e.response.data);
  }
  console.log('\nGet Secret response from Key Vault: ',
      JSON.stringify(response.data, null, 4));

  return response.data;
}
16
evilSnobu