Esercizio - Accedere ai segreti archiviati in Azure Key Vault

Completato

Si sa come abilitare le identità gestite per le risorse di Azure crea un'identità da usare per l'autenticazione dell'app. Creare ora un'app che usa tale identità per accedere ai segreti nell'insieme di credenziali.

Leggere i segreti in un'app ASP.NET Core

L'API Azure Key Vault è un'API REST che gestisce tutte le attività di gestione e utilizzo delle chiavi e degli insiemi di credenziali. Ogni segreto in un insieme di credenziali ha un URL univoco. I valori dei segreti vengono recuperati con le richieste HTTP GET.

Il client ufficiale di Key Vault per .NET Core è la SecretClient classe nel Azure.Security.KeyVault.Secrets pacchetto NuGet. Tuttavia, non è necessario usarlo direttamente. Con il metodo AddAzureKeyVault di ASP.NET Core è possibile caricare tutti i segreti all'avvio da un insieme di credenziali nell'API di configurazione. Questa tecnica consente di accedere a tutti i segreti con il nome, usando la stessa interfaccia IConfiguration usata per il resto della configurazione. Le app che usano AddAzureKeyVault richiedono autorizzazioni e GetList per l'insieme di credenziali.

Suggerimento

Indipendentemente dal framework o dal linguaggio usato per compilare l'app, progettarla in modo da memorizzare i valori segreti nella cache locale o caricarli in memoria all'avvio, a meno che non si abbia un motivo valido per non farlo. Leggere i segreti direttamente dall'insieme di credenziali ogni volta che sono necessari è un'attività lenta e costosa.

AddAzureKeyVault richiede solo il nome dell'insieme di credenziali come input, ottenuto dalla configurazione dell'app locale. Gestisce automaticamente anche l'autenticazione dell'identità gestita. Quando viene usata in un'app distribuita in app Azure Servizio con identità gestite per le risorse di Azure abilitate, rileva il servizio token delle identità gestite e lo usa per l'autenticazione. È ideale per la maggior parte degli scenari e implementa tutte le procedure consigliate. Verrà usato nell'esercizio di questa unità.

Leggere i segreti in un'app Node.js

L'API Azure Key Vault è un'API REST che gestisce tutte le attività di gestione e utilizzo delle chiavi e degli insiemi di credenziali. Ogni segreto in un insieme di credenziali ha un URL univoco. I valori dei segreti vengono recuperati con le richieste HTTP GET.

Il client Key Vault ufficiale per le app Node.js è la classe SecretClient nel pacchetto npm @azure/keyvault-secrets. Le app che includono nomi segreti nella configurazione o nel codice usano in genere il getSecret relativo metodo, che carica un valore segreto in base al nome. getSecret richiede che l'identità dell'app disponga dell'autorizzazione Get per l'insieme di credenziali. Le app progettate per caricare tutti i segreti da un insieme di credenziali usano anche il listPropertiesOfSecrets metodo , che carica un elenco di segreti e richiede l'autorizzazione List .

Prima di poter creare un'istanza di SecretClient, l'app deve ottenere un oggetto Credenzial per l'autenticazione dell'insieme di credenziali. Per eseguire l'autenticazione, usare la classe DefaultAzureCredential fornita dal pacchetto npm @azure/identity. è DefaultAzureCredential appropriato per la maggior parte degli scenari in cui l'applicazione deve essere eseguita in definitiva nel cloud di Azure perché DefaultAzureCredential combina le credenziali comunemente usate per l'autenticazione quando viene distribuita, con le credenziali usate per l'autenticazione in un ambiente di sviluppo. Il DefaultAzureCredential tentativo di autenticazione viene eseguito usando i meccanismi seguenti in ordine:

  • Ambiente. Legge DefaultAzureCredential le informazioni sull'account specificate usando le variabili di ambiente e usarle per l'autenticazione.
  • Identità gestita. Se l'applicazione viene distribuita in un host di Azure con identità gestita abilitata, esegue l'autenticazione DefaultAzureCredential con tale account.
  • Visual Studio Code. Se lo sviluppatore ha eseguito l'autenticazione usando il plug-in dell'account Azure di Visual Studio Code, esegue l'autenticazione DefaultAzureCredential con tale account.
  • Interfaccia della riga di comando di Azure. Se lo sviluppatore ha autenticato un account usando il comando dell'interfaccia della riga di comando di Azure az login , esegue l'autenticazione DefaultAzureCredential con tale account.

Per altre informazioni, vedere la documentazione.

Suggerimento

Indipendentemente dal framework o dal linguaggio usato per compilare l'app, progettarla in modo da memorizzare i valori segreti nella cache locale o caricarli in memoria all'avvio, a meno che non si abbia un motivo valido per non farlo. Leggere i segreti direttamente dall'insieme di credenziali ogni volta che sono necessari è un'attività lenta e costosa.

Gestione di segreti in un'app

Dopo aver caricato un segreto nell'app, sarà l'app a gestirlo in modo sicuro. Nell'app compilata in questo modulo si scrive il valore del segreto nella risposta client e si dimostra che è stato caricato correttamente, viene visualizzato in un Web browser. La restituzione di un valore del segreto al client non è un'operazione usuale. In genere, si usano segreti per eseguire operazioni come l'inizializzazione delle librerie client per i database o le API remote.

Importante

Esaminare sempre con attenzione il codice per verificare che l'app non scriva i segreti in output di qualunque tipo, inclusi log, archiviazione e risposte.

Esercizio

Per caricare il segreto dall'insieme di credenziali, creare una nuova API Web di ASP.NET Core e usare AddAzureKeyVault.

Creare l'app

  1. Per creare una nuova app api Web di ASP.NET Core e aprirla nell'editor, eseguire i comandi seguenti in Azure Cloud Shell.

    dotnet new webapi -o KeyVaultDemoApp
    cd KeyVaultDemoApp
    code .
    
  2. Dopo il caricamento dell'editor, aggiungere il pacchetto NuGet contenente AddAzureKeyVault e ripristinare tutte le dipendenze dell'app. In Azure Cloud Shell eseguire i comandi riportati di seguito.

    dotnet add package Azure.Identity
    dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
    dotnet restore
    

Aggiungere il codice per caricare e usare i segreti

Per mostrare l'uso ottimale di Key Vault, modificare l'app in modo che carichi i segreti dall'insieme di credenziali all'avvio. È anche possibile aggiungere un nuovo controller con un endpoint che ottiene il SecretPassword segreto dall'insieme di credenziali.

  1. Per l'avvio dell'app, immettere il comando seguente per avviare l'editor.

    code .
    
  2. Aprire Program.cs, eliminare il contenuto e sostituirlo con il codice seguente.

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

    Importante

    Verificare di aver salvato i file dopo aver apportato le modifiche. È possibile salvare i file tramite "..." o il tasto di scelta rapida (CTRL+S in Windows e Linux, Cmd+S in macOS).

    L'unica modifica rispetto al codice di avvio è l'aggiunta di ConfigureAppConfiguration. Questo elemento consente di caricare il nome dell'insieme di credenziali dalla configurazione e chiamarlo AddAzureKeyVault con esso.

  3. Per il controller, creare un nuovo file nella cartella Controllers denominato SecretTestController.cs e incollare nel file il codice seguente.

    Suggerimento

    Per creare un nuovo file, usare il comando touch in Cloud Shell. In questo caso, eseguire il comando touch Controllers/SecretTestController.cs. Per trovarlo, nell'angolo in alto a destra del riquadro File dell'editor selezionare l'icona Aggiorna.

    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!");
                }
            }
        }
    }
    
  4. Eseguire il comando dotnet build in Azure Cloud Shell per assicurarsi che tutto venga compilato. L'app è pronta per l'esecuzione. Ora è il momento di inserirlo in Azure.

Creare una nuova API Web con Express.js e usare i @azure/keyvault-secrets pacchetti e @azure/identity per caricare il segreto dall'insieme di credenziali.

Creare l'app

Eseguire questo codice in Azure Cloud Shell per inizializzare una nuova app Node.js, installare i pacchetti necessari e aprire un nuovo file nell'editor.

mkdir KeyVaultDemoApp
cd KeyVaultDemoApp
npm init -y
npm install @azure/identity @azure/keyvault-secrets express
touch app.js
code app.js

Aggiungere il codice per caricare e usare i segreti

Per illustrare un buon uso di Key Vault, l'app carica i segreti dall'insieme di credenziali all'avvio. Per dimostrare che i segreti caricati, creare un endpoint che visualizzi il valore del SecretPassword segreto.

  1. Per configurare l'app, incollare il codice seguente nell'editor. Questo codice importa i pacchetti necessari, configura la configurazione della porta e dell'URI dell'insieme di credenziali e crea un nuovo oggetto per contenere i nomi e i valori dei segreti.

    // 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 = {};
    

    Importante

    Assicurarsi di salvare i file mentre si lavora su di essi, in particolare al termine. È possibile salvare i file tramite "..." o il tasto di scelta rapida (CTRL+S in Windows e Linux, Cmd+S in macOS).

  2. Aggiungere quindi il codice per eseguire l'autenticazione all'insieme di credenziali e caricare i segreti. Questo codice viene aggiunto come due funzioni separate. Inserire un paio di righe vuote dopo il codice aggiunto in precedenza e quindi incollarvi il codice seguente.

    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)
      }
    }
    
  3. Per testare il caricamento del segreto, creare l'endpoint di Express. Incollare questo codice.

    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);
    });
    
  4. Chiamare le funzioni per caricare i segreti dall'insieme di credenziali, quindi avviare l'app. Per completare l'app, incollare quest'ultimo frammento di codice.

    (async () =>  {
      await getKeyVaultSecrets();
      app.listen(port, () => {
        console.log(`Server running at http://localhost:${port}`);
      });
    })().catch(err => console.log(err));
    
  5. La scrittura del codice è stata completata, quindi assicurarsi di salvare il file.

L'app è pronta per l'esecuzione. Ora è il momento di inserirlo in Azure.