Übung: Zugreifen auf in Azure Key Vault gespeicherte Geheimnisse
Sie wissen, wie Sie durch die Aktivierung von verwalteten Identitäten für Azure-Ressourcen eine Identität für Ihre Anwendung erstellen, die Sie zur Authentifizierung verwenden können. Erstellen Sie nun eine Anwendung, die diese Identität verwendet, um auf Geheimnisse im Tresor zuzugreifen.
Lesen von Geheimnissen in einer ASP.NET Core-App
Die Azure Key Vault-API ist eine REST-API, die die gesamte Verwaltung und Nutzung von Schlüsseln und Tresoren verarbeitet. Jedes Geheimnis in einem Tresor hat eine eindeutige URL. Geheime Werte werden mit HTTP GET-Anforderungen abgerufen.
Der offizielle Key Vault-Client für .NET Core ist die Klasse SecretClient
im NuGet-Paket Azure.Security.KeyVault.Secrets
. Sie müssen sie jedoch nicht direkt verwenden. Mit der AddAzureKeyVault
-Methode von ASP.NET Core können Sie beim Start alle Geheimnisse in einem Tresor in die Konfigurations-API laden. So erhalten Sie Zugriff auf alle Ihre Geheimnisse anhand des Namens über dieselbe IConfiguration
-Schnittstelle, die Sie für den Rest Ihrer Konfiguration verwenden. Apps, die AddAzureKeyVault
verwenden, benötigen für den Tresor die die beiden Berechtigungen Get
und List
.
Tipp
Unabhängig davon, mit welchem Framework und welcher Sprache Sie Ihre App erstellen, sollten Sie sie dafür konzipieren, die Werte von Geheimnissen zu speichern oder diese beim App-Start in den Speicher zu laden, sofern kein spezifischer Grund dagegen spricht. Es ist unnötig langsam und teuer, Geheimnisse bei Bedarf direkt aus dem Tresor zu lesen.
AddAzureKeyVault
benötigt nur den Tresornamen als Eingabe, den Sie aus Ihrer lokalen App-Konfiguration abrufen können. Außerdem erfolgt die Verarbeitung der Authentifizierung verwalteter Identitäten automatisch. Beim Einsatz in einer App, die für Azure App Service mit aktivierten verwalteten Identitäten bereitgestellt ist, wird der Tokendienst für verwaltete Identitäten erkannt und zur Authentifizierung verwendet. Dieser Ablauf eignet sich für die meisten Szenarios und umfasst alle bewährten Methoden. Sie verwenden ihn in der Übung dieser Einheit.
Lesen von Geheimnissen in einer Node.js-App
Die Azure Key Vault-API ist eine REST-API, die die gesamte Verwaltung und Nutzung von Schlüsseln und Tresoren verarbeitet. Jedes Geheimnis in einem Tresor hat eine eindeutige URL. Geheime Werte werden mit HTTP GET-Anforderungen abgerufen.
Der offizielle Key Vault-Client für Node.js-Apps ist die SecretClient
-Klasse im npm-Paket @azure/keyvault-secrets
. Apps, die Geheimnisnamen in deren Konfiguration oder Code enthalten, verwenden in der Regel die getSecret
-Methode, die einen Geheimniswert anhand des Namens lädt. getSecret
erfordert, dass die Identität Ihrer App die Get
-Berechtigung für den Tresor hat. Apps, die darauf ausgelegt sind, alle Geheimnisse aus einem Tresor zu laden, verwenden ebenfalls die listPropertiesOfSecrets
-Methode, die eine Liste von Geheimnissen lädt und die List
-Berechtigung erfordert.
Bevor Ihre App eine SecretClient
-Instanz erstellen kann, muss sie für die Authentifizierung beim Tresor ein Objekt mit Anmeldeinformationen abrufen. Verwenden Sie zum Authentifizieren das vom npm-Paket @azure/identity
bereitgestellte Element DefaultAzureCredential
. DefaultAzureCredential
ist für die meisten Szenarien geeignet, in denen die Anwendung letztendlich in der Azure Cloud ausgeführt werden soll, da DefaultAzureCredential
die Anmeldedaten, die üblicherweise zur Authentifizierung bei der Bereitstellung verwendet werden, mit den Anmeldedaten kombiniert, die zur Authentifizierung in einer Entwicklungsumgebung verwendet werden. DefaultAzureCredential
versucht, sich in der angegebenen Reihenfolge über die folgenden Mechanismen zu authentifizieren:
- Umgebung
DefaultAzureCredential
liest Kontoinformationen, die mit Umgebungsvariablen angegeben werden, und nutzt diese zur Authentifizierung. - Verwaltete Identität Wenn die Anwendung auf einem Azure-Host bereitgestellt wird, während die Funktion „Verwaltete Identität“ aktiviert ist, authentifiziert sich
DefaultAzureCredential
mit diesem Konto. - Visual Studio Code. Wenn sich Entwickler*innen über das Visual Studio Code Plug-In „Azure Account“ authentifiziert haben, authentifiziert sich
DefaultAzureCredential
mit diesem Konto. - Azure-Befehlszeilenschnittstelle. Wenn Entwickler*innen ein Konto über den Befehl „Azure CLI
az login
“ authentifiziert haben, authentifiziert sichDefaultAzureCredential
mit diesem Konto.
Weitere Informationen finden Sie in der Dokumentation.
Tipp
Unabhängig davon, mit welchem Framework und welcher Sprache Sie Ihre App erstellen, sollten Sie sie dafür konzipieren, die Werte von Geheimnissen zu speichern oder diese beim App-Start in den Speicher zu laden, sofern kein spezifischer Grund dagegen spricht. Es ist unnötig langsam und teuer, Geheimnisse bei Bedarf direkt aus dem Tresor zu lesen.
Verarbeiten von Geheimnissen in einer App
Wenn ein Geheimnis in die App geladen wurde, muss diese es sicher verarbeiten. In der App, die Sie in diesem Modul erstellen, schreiben Sie Ihren geheimen Wert in die Client-Antwort und um zu zeigen, dass er erfolgreich geladen wurde, zeigen Sie ihn in einem Webbrowser an. Das Zurückgeben des Geheimniswerts an den Client ist nicht die übliche Vorgehensweise. In der Regel werden Geheimnisse beispielsweise zum Initialisieren von Clientbibliotheken für Datenbanken oder Remote-APIs verwendet.
Wichtig
Überprüfen Sie Ihren Code immer sorgfältig, um sicherzustellen, dass Ihre App nie Geheimnisse in Ausgaben (z. B. Protokolle, Speicherung und Antworten) schreibt.
Übung
Um das Geheimnis aus unserem Tresor zu laden, erstellen Sie eine neue ASP.NET Core Web API und verwenden AddAzureKeyVault
.
Erstellen der App
Führen Sie in Azure Cloud Shell die folgenden Befehle aus, um eine neue ASP.NET Core-Web-API-App zu erstellen und im Editor zu öffnen.
dotnet new webapi -o KeyVaultDemoApp cd KeyVaultDemoApp code .
Fügen Sie nach dem Laden des Editors das NuGet-Paket mit
AddAzureKeyVault
hinzu, und stellen Sie alle Abhängigkeiten der App wieder her. Führen Sie in Azure Cloud Shell die folgenden Befehle aus.dotnet add package Azure.Identity dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets dotnet restore
Hinzufügen von Code zum Laden und Verwenden von Geheimnissen
Zur Veranschaulichung der richtigen Verwendung von Key Vault modifizieren Sie Ihre App, sodass Geheimnisse beim Start aus dem Tresor geladen werden. Sie fügen außerdem einen neuen Controller mit einem Endpunkt hinzu, der das Geheimnis SecretPassword
aus dem Tresor abruft.
Geben Sie für den Start der App den folgenden Befehl ein, um den Editor zu starten.
code .
Öffnen Sie
Program.cs
, löschen Sie den Inhalt, und ersetzen Sie diesen durch den folgenden Code.using System; using Azure.Identity; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; namespace KeyVaultDemoApp { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .ConfigureAppConfiguration((context, config) => { // Build the current set of configuration to load values from // JSON files and environment variables, including VaultName. var builtConfig = config.Build(); // Use VaultName from the configuration to create the full vault URI. var vaultName = builtConfig["VaultName"]; Uri vaultUri = new Uri($"https://{vaultName}.vault.azure.net/"); // Load all secrets from the vault into configuration. This will automatically // authenticate to the vault using a managed identity. If a managed identity // is not available, it will check if Visual Studio and/or the Azure CLI are // installed locally and see if they are configured with credentials that can // access the vault. config.AddAzureKeyVault(vaultUri, new DefaultAzureCredential()); }); } }
Wichtig
Speichern Sie Dateien unbedingt, wenn Sie diese fertig bearbeitet haben. Sie können Dateien entweder über das Menü „…“ speichern oder mit der entsprechenden Tastenkombination (STRG+S unter Windows und Linux bzw. CMD+S unter macOS).
Die einzige Änderung gegenüber dem Startercode ist das Hinzufügen von
ConfigureAppConfiguration
. Hier laden Sie den Tresornamen aus der Konfiguration und rufen damitAddAzureKeyVault
auf.Erstellen Sie für den Controller im Ordner
Controllers
eine neue Datei namensSecretTestController.cs
, und fügen Sie den folgenden Code ein.Tipp
Verwenden Sie den Befehl
touch
in Cloud Shell, um eine neue Datei zu erstellen. Führen Sie in diesem Fall den Befehltouch Controllers/SecretTestController.cs
aus. Klicken Sie rechts oben im Bereich Dateien des Editors auf das Symbol „Aktualisieren“, damit es dort angezeigt wird.using System; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; namespace KeyVaultDemoApp.Controllers { [Route("api/[controller]")] public class SecretTestController : ControllerBase { private readonly IConfiguration _configuration; public SecretTestController(IConfiguration configuration) { _configuration = configuration; } [HttpGet] public IActionResult Get() { // Get the secret value from configuration. This can be done anywhere // we have access to IConfiguration. This does not call the Key Vault // API, because the secrets were loaded at startup. var secretName = "SecretPassword"; var secretValue = _configuration[secretName]; if (secretValue == null) { return StatusCode( StatusCodes.Status500InternalServerError, $"Error: No secret named {secretName} was found..."); } else { return Content($"Secret value: {secretValue}" + Environment.NewLine + Environment.NewLine + "This is for testing only! Never output a secret " + "to a response or anywhere else in a real app!"); } } } }
Führen Sie den
dotnet build
-Befehl in Azure Cloud Shell aus, um sicherzustellen, dass alles kompiliert wird. Die App ist für die Ausführung bereit. Jetzt ist es an der Zeit, sie in Azure zu integrieren!
Erstellen Sie eine neue Web-API mit Express.js, und verwenden Sie die Pakete @azure/keyvault-secrets
und @azure/identity
zum Laden des Geheimnisses aus dem Tresor.
Erstellen der App
Führen Sie in Azure Cloud Shell folgenden Code aus, um eine neue Node.js-App zu initialisieren, die benötigten Pakete zu installieren und eine neue Datei im Editor zu öffnen.
mkdir KeyVaultDemoApp
cd KeyVaultDemoApp
npm init -y
npm install @azure/identity @azure/keyvault-secrets express
touch app.js
code app.js
Hinzufügen von Code zum Laden und Verwenden von Geheimnissen
Zur Veranschaulichung der richtigen Verwendung von Key Vault lädt Ihre App beim Starten Geheimnisse aus dem Tresor. Erstellen Sie einen Endpunkt, der den Wert des Geheimnisses SecretPassword
anzeigt, um zu demonstrieren, dass die Geheimnisse geladen wurden.
Fügen Sie den folgenden Code in den Editor ein, um die App einzurichten. Dieser Code importiert die erforderlichen Pakete. Außerdem werden der Port und die URI-Konfiguration des Tresors eingerichtet, und ein neues Objekt für die Geheimnisnamen und -werte erstellt.
// Importing dependencies const { DefaultAzureCredential } = require("@azure/identity"); const { SecretClient } = require("@azure/keyvault-secrets"); const app = require('express')(); // Initialize port const port = process.env.PORT || 3000; // Create Vault URI from App Settings const vaultUri = `https://${process.env.VaultName}.vault.azure.net/`; // Map of key vault secret names to values let vaultSecretsMap = {};
Wichtig
Speichern Sie Dateien, während Sie an diesen arbeiten und insbesondere, wenn Sie fertig sind. Sie können Dateien entweder über das Menü „…“ speichern oder mit der entsprechenden Tastenkombination (STRG+S unter Windows und Linux bzw. CMD+S unter macOS).
Fügen Sie als Nächstes den Code hinzu, um sich beim Tresor zu authentifizieren und die Geheimnisse zu laden. Dieser Code wird in Form von zwei separaten Funktionen hinzugefügt. Fügen Sie ein paar leere Zeilen nach dem Code hinzu, den Sie zuvor hinzugefügt haben, und fügen Sie dann den folgenden Code ein:
const getKeyVaultSecrets = async () => { // Create a key vault secret client let secretClient = new SecretClient(vaultUri, new DefaultAzureCredential()); try { // Iterate through each secret in the vault listPropertiesOfSecrets = secretClient.listPropertiesOfSecrets(); while (true) { let { done, value } = await listPropertiesOfSecrets.next(); if (done) { break; } // Only load enabled secrets - getSecret will return an error for disabled secrets if (value.enabled) { const secret = await secretClient.getSecret(value.name); vaultSecretsMap[value.name] = secret.value; } } } catch(err) { console.log(err.message) } }
Erstellen Sie nun den Express-Endpunkt, um zu testen, ob das Geheimnis geladen wurde. Fügen Sie den folgenden Code ein:
app.get('/api/SecretTest', (req, res) => { let secretName = 'SecretPassword'; let response; if (secretName in vaultSecretsMap) { response = `Secret value: ${vaultSecretsMap[secretName]}\n\nThis is for testing only! Never output a secret to a response or anywhere else in a real app!`; } else { response = `Error: No secret named ${secretName} was found...` } res.type('text'); res.send(response); });
Rufen Sie Ihre Funktionen zum Laden der Geheimnisse aus dem Tresor auf, und starten Sie dann die App. Fügen Sie diesen letzten Codeausschnitt ein, um die App fertigzustellen:
(async () => { await getKeyVaultSecrets(); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); }); })().catch(err => console.log(err));
Sie sind jetzt mit dem Programmieren fertig, speichern Sie die Datei also unbedingt.
Die App ist für die Ausführung bereit. Jetzt ist es an der Zeit, sie in Azure zu integrieren!