Exercício – Acessar os segredos armazenados no Azure Key Vault
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 em um aplicativo ASP.NET Core
A API do Azure Key Vault é uma API REST que lida com todo o gerenciamento e o uso de chaves e cofres. Cada segredo em um cofre tem uma URL exclusiva. Os valores de segredo são recuperados com solicitações HTTP GET.
O cliente oficial do Key Vault para .NET Core é a classe SecretClient
no pacote NuGet Azure.Security.KeyVault.Secrets
. No entanto, você não precisa usá-lo diretamente. Com o método AddAzureKeyVault
do ASP.NET Core, você pode carregar todos os segredos de um cofre na API de Configuração durante a inicialização. Essa técnica permite acessar todos os segredos pelo nome usando a mesma interface IConfiguration
que você usa para o restante da configuração. Os aplicativos que usam AddAzureKeyVault
exigem permissões Get
e List
para o cofre.
Dica
Independentemente da estrutura ou da linguagem usada para a criação do aplicativo, você deve projetá-lo para armazenar em cache os valores secretos localmente ou carregá-los na memória na inicialização, a menos que você tenha um motivo específico para não fazer isso. É desnecessariamente lento e caro lê-los diretamente do cofre sempre que você precisa deles.
AddAzureKeyVault
requer apenas o nome do cofre como uma entrada, que você obtém da configuração do aplicativo local. Ele também cuida automaticamente da 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 habilitados, ele detecta 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. Você o usa no exercício desta unidade.
Ler segredos em um aplicativo Node.js
A API do Azure Key Vault é uma API REST que lida com todo o gerenciamento e o uso de chaves e cofres. Cada segredo em um cofre tem uma URL exclusiva. Os valores de segredo são recuperados com solicitações HTTP GET.
O cliente oficial do Key Vault para aplicativos Node.js é a classe SecretClient
no pacote npm @azure/keyvault-secrets
. Aplicativos que incluem nomes de segredo em sua configuração ou código geralmente usam seu método getSecret
, que carrega um valor de segredo dado o seu nome. getSecret
exige que a identidade do aplicativo tenha a permissão Get
no cofre. Os aplicativos projetados para carregar todos os segredos de um cofre também usam o método listPropertiesOfSecrets
, que carrega uma lista de segredos e requer a permissão List
.
Antes que o aplicativo possa criar uma instância SecretClient
, ele precisará obter um objeto de credencial para autenticação no cofre. Para se autenticar, use a DefaultAzureCredential
fornecida pelo pacote npm @azure/identity
. O DefaultAzureCredential
é apropriado para a maioria dos cenários em que o aplicativo se destina a ser executado no Azure Cloud porque o DefaultAzureCredential
combina credenciais normalmente usadas para autenticação durante a implantação, com credenciais usadas para autenticação em um ambiente de desenvolvimento. DefaultAzureCredential
tenta autenticar usando os seguintes mecanismos, nesta ordem:
- Ambiente. O
DefaultAzureCredential
lê informações da conta especificadas usando variáveis de ambiente e as usa para autenticar. - Identidade gerenciada. Se o aplicativo for implantado em um host do Azure com a Identidade Gerenciada habilitada, o
DefaultAzureCredential
será autenticado com essa conta. - Visual Studio Code. Se o desenvolvedor for autenticado usando o plug-in da Conta do Azure do Visual Studio Code, o
DefaultAzureCredential
será autenticado com essa conta. - CLI do Azure. Se o desenvolvedor autenticar uma conta usando o comando da CLI do Azure
az login
, oDefaultAzureCredential
será autenticado com essa conta.
Para obter mais informações, confira a documentação.
Dica
Independentemente da estrutura ou da linguagem usada para a criação do aplicativo, você deve projetá-lo para armazenar em cache os valores secretos localmente ou carregá-los na memória na inicialização, a menos que você tenha um motivo específico para não fazer isso. É desnecessariamente lento e caro lê-los diretamente do cofre sempre que você precisa deles.
Manipular segredos em um aplicativo
Cabe ao aplicativo tratar o segredo com segurança após ele ser carregado em seu aplicativo. No aplicativo criado neste módulo, você grava seu valor de segredo na resposta do cliente e, para demonstrar que ele foi carregado com êxito, você o exibe em um navegador da Web. O retorno de um valor secreto para o cliente não é algo que você normalmente faria! Normalmente, você usa segredos para fazer coisas como inicializar bibliotecas de clientes para bancos de dados ou APIs remotas.
Importante
Examine sempre o código cuidadosamente para garantir que seu aplicativo nunca grave segredos em nenhum tipo de saída, incluindo logs, armazenamento e respostas.
Exercício
Para carregar o segredo de nosso cofre, crie uma nova API Web do ASP.NET Core e use AddAzureKeyVault
.
Criar o aplicativo
Para criar um novo aplicativo de API Web do ASP.NET Core e abri-lo no editor, execute os comandos a seguir no Azure Cloud Shell.
dotnet new webapi -o KeyVaultDemoApp cd KeyVaultDemoApp code .
Depois que o editor for carregado, adicione o pacote NuGet que contém
AddAzureKeyVault
e restaure todas as dependências do aplicativo. No Azure Cloud Shell, execute os comandos a seguir.dotnet add package Azure.Identity dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets dotnet restore
Adicionar um código para carregar e usar segredos
Para demonstrar um bom uso do Key Vault, modificaremos nosso aplicativo para carregar os segredos do cofre na inicialização. Você também adiciona um novo controlador com um ponto de extremidade que obtém seu segredo SecretPassword
do cofre.
Para a inicialização do aplicativo, insira o comando a seguir para iniciar o editor.
code .
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
Salve os arquivos quando terminar de editá-los. Você pode salvar arquivos por meio do menu "..." ou a tecla aceleradora (Ctrl+S no Windows e Linux, Cmd+S no macOS).
A única alteração no código inicial é a adição de
ConfigureAppConfiguration
. Esse elemento é onde carregamos o nome do cofre da configuração e chamamosAddAzureKeyVault
com ele.Para o controlador, crie um arquivo na pasta
Controllers
chamadoSecretTestController.cs
e cole o código a seguir nele.Dica
Para criar um arquivo, use o comando
touch
no Cloud Shell. Nesse caso, execute o comandotouch Controllers/SecretTestController.cs
. Para vê-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!"); } } } }
Execute o comando
dotnet build
no Azure Cloud Shell para garantir que tudo seja compilado. O aplicativo está pronto para ser executado. Agora é hora de entrar no Azure!
Crie uma nova API Web com o Express.js e use o e os pacotes @azure/keyvault-secrets
e @azure/identity
para carregar o segredo de nosso cofre.
Crie o aplicativo
Execute o código a seguir no Azure Cloud Shell para inicializar um novo aplicativo do Node.js, instale os pacotes necessários, e abra 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 um código para carregar e usar segredos
Para demonstrar o bom uso do Key Vault, seu aplicativo carrega segredos do cofre na inicialização. Para demonstrar que seus segredos foram carregados, crie um ponto de extremidade que exiba o valor do segredo SecretPassword
.
Cole o código a seguir no editor para configurar o aplicativo. Esse código importa os pacotes necessários, configura a configuração de URI da porta e do cofre e cria um novo objeto para armazenar os nomes e valores de segredo.
// 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
Certifique-se de salvar os arquivos enquanto você trabalha neles, especialmente quando tiver terminado. Você pode salvar arquivos por meio do menu "..." ou a tecla aceleradora (Ctrl+S no Windows e Linux, Cmd+S no macOS).
Em seguida, adicione o código para autenticar no cofre e carregar os segredos. Você adiciona esse código como duas funções separadas. Insira algumas linhas em branco após o código adicionado anteriormente e cole o código a seguir.
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) } }
Crie o ponto de extremidade da opção Expresso para testar se o segredo foi carregado. Cole neste 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); });
Chame suas funções para carregar os segredos do cofre e inicie o aplicativo. Cole este último snippet para concluir o aplicativo.
(async () => { await getKeyVaultSecrets(); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); }); })().catch(err => console.log(err));
Você terminou de escrever o código, portanto, verifique se salvou o arquivo.
O aplicativo está pronto para ser executado. Agora é hora de entrar no Azure!