Exercício – aceder a segredos armazenados no Azure Key Vault

Concluído

Você sabe como habilitar identidades gerenciadas para recursos do Azure cria uma identidade para seu aplicativo usar para autenticação. Agora, crie um aplicativo que use essa identidade para acessar segredos no cofre.

Ler segredos numa aplicação ASP.NET Core

A API do Azure Key Vault é uma API REST que lida com todo o gerenciamento e uso de chaves e cofres. Cada segredo em um cofre tem um URL exclusivo. Os valores secretos são recuperados com solicitações HTTP GET.

O cliente oficial do Key Vault para .NET Core é a SecretClientAzure.Security.KeyVault.Secrets classe no pacote NuGet. No entanto, você não precisa usá-lo diretamente. Com o método do AddAzureKeyVault de ASP.NET Core, pode carregar todos os segredos de um cofre para a API de Configuração durante o arranque. Essa técnica permite que você acesse todos os seus segredos pelo nome usando a mesma IConfiguration interface que você usa para o resto da sua configuração. Os aplicativos que usam AddAzureKeyVault exigem permissões Get e List para o cofre.

Gorjeta

Independentemente da estrutura ou linguagem usada para criar seu aplicativo, você deve projetá-lo para armazenar em cache valores secretos localmente ou carregá-los na memória na inicialização, a menos que tenha um motivo específico para não fazê-lo. Lê-los diretamente a partir do cofre, sempre que precisar deles, é um processo desnecessariamente lento e caro.

AddAzureKeyVault requer apenas o nome do cofre como entrada, que você obtém da configuração do aplicativo local. Ele também lida automaticamente com a autenticação de identidade gerenciada. Quando usado em um aplicativo implantado no Serviço de Aplicativo do Azure com identidades gerenciadas para recursos do Azure habilitadas, ele deteta o serviço de token de identidades gerenciadas e o usa para autenticar. É uma boa opção para a maioria dos cenários e implementa todas as práticas recomendadas. Utiliza-o no exercício desta unidade.

Ler segredos em um aplicativo .js nó

A API do Azure Key Vault é uma API REST que lida com todo o gerenciamento e uso de chaves e cofres. Cada segredo em um cofre tem um URL exclusivo. Os valores secretos são recuperados com solicitações HTTP GET.

O cliente do Key Vault oficial para aplicações Node.js é a classe SecretClient no pacote npm @azure/keyvault-secrets. Os aplicativos que incluem nomes secretos em sua configuração ou código geralmente usam seu método, que carrega um valor secreto dado seu getSecret nome. getSecret requer que a identidade do seu aplicativo tenha a Get permissão no cofre. Os aplicativos projetados para carregar todos os segredos de um cofre também usam o listPropertiesOfSecrets método, que carrega uma lista de segredos e requer a List permissão.

Para a aplicação poder criar uma instância do SecretClient, esta tem de obter um objeto de credencial através da autenticação no cofre. Para autenticar, utilize a DefaultAzureCredential disponibilizada pelo pacote npm @azure/identity. O DefaultAzureCredential é apropriado para a maioria dos cenários em que o aplicativo se destina a ser executado na Nuvem do Azure porque o DefaultAzureCredential combina credenciais comumente usadas para autenticar quando implantado, com credenciais usadas para autenticar em um ambiente de desenvolvimento. As DefaultAzureCredential tentativas de autenticação usando os seguintes mecanismos em ordem:

  • Ambiente. O DefaultAzureCredential lê as informações da conta especificadas usando variáveis de ambiente e usa-as para autenticar.
  • Identidade gerenciada. Se o aplicativo for implantado em um host do Azure com a Identidade Gerenciada habilitada, o DefaultAzureCredential autenticará com essa conta.
  • Visual Studio Code. Se o desenvolvedor autenticou usando o plug-in da Conta do Azure do Visual Studio Code, o DefaultAzureCredential autenticará com essa conta.
  • CLI do Azure. Se o desenvolvedor autenticou uma conta usando o comando da CLI az login do Azure, o DefaultAzureCredential autentica com essa conta.

Para obter mais informações, consulte a documentação.

Gorjeta

Independentemente da estrutura ou linguagem usada para criar seu aplicativo, você deve projetá-lo para armazenar em cache valores secretos localmente ou carregá-los na memória na inicialização, a menos que tenha um motivo específico para não fazê-lo. Lê-los diretamente a partir do cofre, sempre que precisar deles, é um processo desnecessariamente lento e caro.

Gerir segredos numa aplicação

Depois de um segredo ser carregado na sua aplicação, esta é responsável por processá-lo de forma segura. No aplicativo que você cria neste módulo, você escreve seu valor secreto para a resposta do cliente e, para demonstrar que ele foi carregado com êxito, você o visualiza em um navegador da Web. Devolver o valor de um segredo ao cliente não é um procedimento recorrente! Normalmente, você usa segredos para fazer coisas como inicializar bibliotecas de cliente para bancos de dados ou APIs remotas.

Importante

Sempre revise cuidadosamente seu código para garantir que seu aplicativo nunca escreva segredos em qualquer tipo de saída, incluindo logs, armazenamento e respostas.

Exercício

Para carregar o segredo do nosso cofre, crie uma nova API Web ASP.NET Core e use AddAzureKeyVaulto .

Criar a aplicação

  1. Para criar um novo aplicativo de API Web ASP.NET Core e abri-lo no editor, execute os seguintes comandos no Azure Cloud Shell.

    dotnet new webapi -o KeyVaultDemoApp
    cd KeyVaultDemoApp
    code .
    
  2. Depois que o editor carregar, adicione o pacote NuGet que contém AddAzureKeyVault e restaure todas as dependências do aplicativo. No Azure Cloud Shell, execute os seguintes comandos.

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

Adicionar código para carregar e utilizar segredos

Para demonstrar o bom uso do Cofre da Chave, modifique seu aplicativo para carregar segredos do cofre na inicialização. Você também adiciona um novo controlador com um ponto de extremidade que obtém seu SecretPassword segredo do cofre.

  1. Para a inicialização do aplicativo, digite o seguinte comando para iniciar o editor.

    code .
    
  2. Abra Program.cs, exclua o conteúdo e substitua-o pelo código a seguir.

    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

    Certifique-se de que guarda os ficheiros quando terminar de os editar. Você pode salvar arquivos através do "..." ou a tecla aceleradora (Ctrl+S no Windows e Linux, Cmd+S no macOS).

    A única alteração ao código do dispositivo de arranque é a adição de ConfigureAppConfiguration. Este elemento é onde carregamos o nome do cofre da configuração e chamamos AddAzureKeyVault com ele.

  3. Para o controlador, crie um novo arquivo na Controllers pasta chamada SecretTestController.cs, e cole no código a seguir.

    Gorjeta

    Para criar um novo arquivo, use o touch comando no Cloud Shell. Nesse caso, execute o touch Controllers/SecretTestController.cs comando. Para encontrá-lo no canto superior direito do painel Arquivos do editor, selecione o ícone Atualizar.

    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. Execute o dotnet build comando no Azure Cloud Shell para garantir que tudo seja compilado. O aplicativo está pronto para ser executado. Agora é hora de colocá-lo no Azure!

Crie uma nova API da Web com o Express.js e use os pacotes e @azure/identity para carregar o @azure/keyvault-secrets segredo do nosso cofre.

Criar a aplicação

Execute o código a seguir no Azure Cloud Shell para inicializar um novo aplicativo Node.js, instalar os pacotes necessários e abrir um novo arquivo no editor.

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

Adicionar código para carregar e utilizar segredos

Para demonstrar o bom uso do Cofre da Chave, seu aplicativo carrega segredos do cofre na inicialização. Para demonstrar que seus segredos foram carregados, crie um ponto de extremidade que exiba o SecretPassword valor do segredo.

  1. Para configurar o aplicativo, cole o código a seguir no editor. Esse código importa os pacotes necessários, configura a configuração do URI da porta e do vault e cria um novo objeto para armazenar os nomes e valores secretos.

    // 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

    Confirme que guarda os ficheiros à medida que trabalha neles, especialmente quando tiver terminado. Você pode salvar arquivos através do "..." ou a tecla aceleradora (Ctrl+S no Windows e Linux, Cmd+S no macOS).

  2. Em seguida, adicione o código para autenticar no cofre e carregue os segredos. Você adiciona esse código como duas funções separadas. Insira algumas linhas em branco depois do código que adicionou anteriormente e, em seguida, cole o seguinte código.

    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. Crie o ponto final Expresso para testar se o nosso segredo foi carregado. Cole este código.

    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. Chame as suas funções para carregar os segredos do nosso cofre e, em seguida, inicie a aplicação. Cole este último fragmento de código para concluir a aplicação.

    (async () =>  {
      await getKeyVaultSecrets();
      app.listen(port, () => {
        console.log(`Server running at http://localhost:${port}`);
      });
    })().catch(err => console.log(err));
    
  5. Acabou de escrever o código, por isso, certifique-se de que guarda o ficheiro.

O aplicativo está pronto para ser executado. Agora é hora de colocá-lo no Azure!