Configurar MicroProfile com o Azure Key Vault
Este tutorial demonstra como configurar um aplicativo MicroProfile para recuperar segredos do Azure Key Vault usando as APIs de configuração do MicroProfile. Os desenvolvedores se beneficiam da API MicroProfile Config de padrão aberto para recuperar e injetar dados de configuração em seus microsserviços.
Pré-requisitos
- Uma assinatura do Azure: se você ainda não tiver uma assinatura do Azure, poderá ativar o benefício de assinante do MSDN ou se inscrever para uma conta gratuita.
- CLI do Azure para ambientes do tipo Unix. Esse artigo requer apenas a variante Bash da CLI do Azure.
Instale a CLI do Azure e entre interativamente com o comando az login para fazer logon no Azure antes de usar DefaultAzureCredential
o código.az login
- Este artigo requer pelo menos a versão 2.61.0 da CLI do Azure. Se você está usando o Azure Cloud Shell, a última versão já está instalada.
- O Azure Cloud Shell tem todos esses pré-requisitos pré-instalados. Para saber mais, confira Início Rápido para o Azure Cloud Shell.
- Se você estiver executando os comandos neste guia localmente (em vez de usar o Azure Cloud Shell), conclua as seguintes etapas:
- Prepare um computador local com sistema operacional semelhante ao Unix instalado (por exemplo, Ubuntu, macOS ou do Subsistema do Windows para Linux).
- Instale uma implementação do Java SE versão 17 ou posterior (por exemplo, compilação Microsoft do OpenJDK).
- Instale o Maven 3.9.8 ou superior.
- Instale o cURL.
Conectando o MicroProfile Config com o Azure Key Vault
Vamos dar uma olhada rápida no poder de combinar o Azure Key Vault e a API de configuração do MicroProfile. Aqui está um trecho de código de um campo em uma classe que é anotado com @Inject
e @ConfigProperty
. O name
especificado na anotação é o nome do segredo a ser pesquisado no Azure Key Vault e o defaultValue
será usado se o segredo não for descoberto. O valor secreto armazenado no Azure Key Vault ou o valor padrão, se esse segredo não existir, é injetado automaticamente no campo em runtime. Injetar valores de propriedade dessa maneira oferece vários benefícios. Por exemplo, você não precisa mais passar valores em construtores e métodos setter, e a configuração é externalizada do código. Um dos benefícios mais poderosos é ter conjuntos separados de valores para ambientes de desenvolvimento, teste e produção.
@Inject
@ConfigProperty(name = "key-name", defaultValue = "Unknown")
String keyValue;
Também é possível acessar a configuração do MicroProfile imperativamente, conforme mostrado no exemplo a seguir:
public class DemoClass {
@Inject
Config config;
public void method() {
System.out.println("Hello: " + config.getValue("key-name", String.class));
}
}
Este exemplo usa a implementação do Open Liberty do MicroProfile. Para obter uma lista completa de implementações compatíveis, consulte Implementações compatíveis com MicroProfile. O exemplo também demonstra como conteinerizar e executar o aplicativo no Azure.
Este exemplo usa a extensão do Azure de baixo atrito para a biblioteca ConfigSource personalizada do MicroProfile Key Vault. Para obter mais informações sobre essa biblioteca, consulte o README da biblioteca.
Aqui estão as etapas necessárias para executar esse código em seu computador local, começando com a criação de um recurso do Azure Key Vault.
Criamos um recurso do Azure Key Vault
Use a CLI do Azure para criar o recurso do Azure Key Vault e preenchê-lo com dois segredos.
Primeiro, entre no Azure e defina uma assinatura como a assinatura ativa atual.
az login
az account set --subscription <subscription-id>
Em seguida, crie um grupo de recursos com um nome exclusivo, por exemplo, mp-kv-rg-ejb010424.
export RESOURCE_GROUP_NAME=mp-kv-rg-ejb010424
az group create \
--name ${RESOURCE_GROUP_NAME} \
--location eastus
Agora, crie um recurso do Azure Key Vault com um nome exclusivo (por exemplo, kvejb010424), adicione dois segredos e exporte o URI do Key Vault como uma variável de ambiente.
export KEY_VAULT_NAME=kv-ejb010424
az keyvault create \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEY_VAULT_NAME}" \
--location eastus \
--enable-rbac-authorization false
az keyvault secret set \
--vault-name "${KEY_VAULT_NAME}" \
--name secret \
--value 1234
az keyvault secret set \
--vault-name "${KEY_VAULT_NAME}" \
--name anotherSecret \
--value 5678
export AZURE_KEYVAULT_URL=$(az keyvault show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEY_VAULT_NAME}" \
--query properties.vaultUri \
--output tsv)
echo $AZURE_KEYVAULT_URL
A variável AZURE_KEYVAULT_URL
de ambiente é necessária para configurar a biblioteca para trabalhar com o exemplo posteriormente. Mantenha o terminal aberto e use-o para executar o aplicativo localmente mais tarde.
É isso! Agora você tem o Key Vault em execução no Azure com dois segredos. Agora você pode clonar o repositório de exemplo e configurá-lo para usar esse recurso em seu aplicativo.
Colocá-lo em funcionamento localmente
Este exemplo é baseado em um aplicativo de exemplo disponível no GitHub. Alterne para o terminal que você abriu antes e execute os seguintes comandos para clonar o repositório e executar o aplicativo localmente:
git clone https://github.com/Azure/azure-microprofile.git
cd azure-microprofile
git checkout 1.0.0-beta.3
cd integration-tests/open-liberty-sample
mvn clean package liberty:run
Se você vir uma mensagem sobre You are in 'detached HEAD' state
, é seguro ignorá-la.
Observação
A biblioteca usa a credencial padrão do Azure para autenticar no Azure.
Como você autenticou uma conta por meio do comando da CLI az login
do Azure localmente, DefaultAzureCredential
autentica com essa conta para acessar o Azure Key Vault.
Aguarde até ver uma saída semelhante a The defaultServer server is ready to run a smarter planet
. Abra um novo terminal e execute os seguintes comandos para testar a amostra:
# Get the value of secret "secret" stored in the Azure key vault. You should see 1234 in the response.
echo $(curl -s http://localhost:9080/config/value/secret -X GET)
# Get the value of secret "anotherSecret" stored in the Azure key vault. You should see 5678 in the response.
echo $(curl -s http://localhost:9080/config/value/anotherSecret -X GET)
# Get the names of secrets stored in the Azure key vault. You should see ["anotherSecret","secret"] in the response.
echo $(curl -s http://localhost:9080/config/propertyNames -X GET)
# Get the name-value paris of secrets stored in the Azure key vault. You should see {"anotherSecret":"5678","secret":"1234"} in the response.
echo $(curl -s http://localhost:9080/config/properties -X GET)
Você deve ver os resultados esperados descritos nos comentários. Volte para o terminal em que o aplicativo está sendo executado. Pressione Ctrl + C para interromper o aplicativo.
Examinar o aplicativo de exemplo
Vamos obter uma compreensão mais profunda de como o MicroProfile Config funciona em geral e a biblioteca MicroProfile Key Vault Custom ConfigSource funciona em particular.
Dependência de biblioteca
Inclua o MicroProfile Key Vault Custom ConfigSource em seu aplicativo com a seguinte dependência do Maven:
<dependency>
<groupId>com.azure.microprofile</groupId>
<artifactId>azure-microprofile-config-keyvault</artifactId>
</dependency>
Conectando-se ao Azure Key Vault
A azure-microprofile-config-keyvault
biblioteca conecta seu aplicativo ao Azure Key Vault sem introduzir dependências diretas nas APIs do Azure. A biblioteca fornece uma implementação da interface ConfigSource da especificação MicroProfile Config que sabe como ler do Azure Key Vault. O restante da implementação do MicroProfile Config é fornecido pelo tempo de execução do Open Liberty. Para obter um link para a especificação, consulte Próximas etapas.
A biblioteca define a azure.keyvault.url
propriedade de configuração para associar seu aplicativo a um cofre de chaves específico. A especificação MicroProfile Config define as "Regras de mapeamento de variáveis de ambiente" para saber como o valor de uma propriedade de configuração, como azure.keyvault.url
, é descoberto no tempo de execução. Uma dessas regras afirma que as propriedades são convertidas em variáveis de ambiente. A propriedade azure.keyvault.url
faz com que a variável AZURE_KEYVAULT_URL
de ambiente seja consultada.
Classes de chave no aplicativo de exemplo
Vamos examinar o recurso REST que os comandos cURL anteriores estão chamando. Esse recurso REST é definido na classe ConfigResource.java
do integration-tests/open-liberty-sample
projeto.
@Path("/config")
public class ConfigResource {
@Inject
private Config config;
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/value/{name}")
public String getConfigValue(@PathParam("name") String name) {
return config.getConfigValue(name).getValue();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/propertyNames")
public Set<String> getConfigPropertyNames() {
ConfigSource configSource = getConfigSource(AzureKeyVaultConfigSource.class.getSimpleName());
return configSource.getPropertyNames();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/properties")
public Map<String, String> getConfigProperties() {
ConfigSource configSource = getConfigSource(AzureKeyVaultConfigSource.class.getSimpleName());
return configSource.getProperties();
}
private ConfigSource getConfigSource(String name) {
return StreamSupport.stream(config.getConfigSources().spliterator(), false)
.filter(source -> source.getName().equals(name))
.findFirst()
.orElseThrow(() -> new RuntimeException("ConfigSource not found: " + name));
}
}
O getConfigValue()
método usa a implementação injetada Config
para pesquisar um valor das fontes de configuração do aplicativo. Todas as pesquisas de valor na Config
implementação são encontradas por meio do algoritmo de pesquisa definido pela especificação MicroProfile Config. A azure-microprofile-config-keyvault
biblioteca adiciona o Azure Key Vault como uma fonte de configuração.
O getConfigSource()
método evita o algoritmo de pesquisa e vai direto para o AzureKeyVaultConfigSource
para resolver propriedades. Este método é usado pelos getConfigPropertyNames()
métodos e getConfigProperties()
.
Executar em Aplicativos de Contêiner do Azure
Nesta seção, você coloca o aplicativo em contêineres, configura uma identidade gerenciada atribuída pelo usuário para acessar o Azure Key Vault e implanta o aplicativo em contêineres nos Aplicativos de Contêiner do Azure.
Volte para o terminal em que você executou o aplicativo localmente e use-o ao longo desta seção.
Configurar um Registro de Contêiner do Azure
Você usa o Registro de Contêiner do Azure para conteinerizar o aplicativo e armazenar a imagem do aplicativo.
Primeiro, crie um Registro de Contêiner do Azure com um nome exclusivo, por exemplo, acrejb010424.
export ACR_NAME=acrejb010424
az acr create \
--resource-group $RESOURCE_GROUP_NAME \
--name $ACR_NAME \
--sku Basic
Aguarde alguns minutos após o retorno desse comando antes de continuar.
Conteinerizar o aplicativo
Em seguida, conteinerize o aplicativo e envie a imagem do aplicativo por push para o Registro de Contêiner do Azure. Verifique se você está no caminho do aplicativo de exemplo, por exemplo, azure-microprofile/integration-tests/open-liberty-sample.
az acr build \
--registry ${ACR_NAME} \
--image open-liberty-mp-azure-keyvault:latest \
.
Você deve ver a saída de build que termina com uma mensagem semelhante a Run ID: ca1 was successful after 1m28s
. Se você não vir uma mensagem semelhante, solucione o problema e resolva o problema antes de continuar.
Use os comandos a seguir para recuperar as informações de conexão necessárias para acessar a imagem ao implantar o aplicativo nos Aplicativos de Contêiner do Azure posteriormente.
export ACR_LOGIN_SERVER=$(az acr show \
--name $ACR_NAME \
--query 'loginServer' \
--output tsv)
Configurar uma identidade gerenciada atribuída ao usuário
Conforme mencionado anteriormente, a biblioteca usa a credencial padrão do Azure para autenticar no Azure. Ao implantar o aplicativo nos Aplicativos de Contêiner do Azure, você define a variável AZURE_CLIENT_ID
de ambiente para configurar DefaultAzureCredential para autenticar como uma identidade gerenciada definida pelo usuário, que tem permissões para acessar o Azure Key Vault e é atribuída aos Aplicativos de Contêiner do Azure posteriormente.
Primeiro, use os comandos a seguir para criar uma identidade gerenciada atribuída pelo usuário com um nome exclusivo, por exemplo, uamiejb010424. Para obter mais informações, acesse Criar uma identidade gerenciada atribuída pelo usuário.
export USER_ASSIGNED_IDENTITY_NAME=uamiejb010424
az identity create \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${USER_ASSIGNED_IDENTITY_NAME}
Em seguida, use os comandos a seguir para conceder permissões para obter e listar segredos do Azure Key Vault. Para obter mais informações, consulte Atribuir a política de acesso.
export USER_ASSIGNED_IDENTITY_OBJECT_ID="$(az identity show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--query 'principalId' \
--output tsv)"
az keyvault set-policy --name "${KEY_VAULT_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--secret-permissions get list \
--object-id "${USER_ASSIGNED_IDENTITY_OBJECT_ID}"
A saída deve conter o seguinte JSON para ser considerada bem-sucedida:
"permissions": {
"certificates": null,
"keys": null,
"secrets": [
"list",
"get"
],
"storage": null
}
Se a saída não contiver esse JSON, solucione e resolva o problema antes de continuar.
Em seguida, use os seguintes comandos para recuperar a ID e a ID do cliente da identidade gerenciada atribuída pelo usuário para que você possa atribuí-la aos Aplicativos de Contêiner do Azure posteriormente para acessar o Azure Key Vault:
export USER_ASSIGNED_IDENTITY_ID="$(az identity show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--query 'id' \
--output tsv)"
export USER_ASSIGNED_IDENTITY_CLIENT_ID="$(az identity show \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--query 'clientId' \
--output tsv)"
echo $USER_ASSIGNED_IDENTITY_ID
echo $USER_ASSIGNED_IDENTITY_CLIENT_ID
Implantar o aplicativo nos Aplicativos de Contêiner do Azure
Você conteinerizou o aplicativo e configurou uma identidade gerenciada atribuída pelo usuário para acessar o Azure Key Vault. Agora você pode implantar o aplicativo em contêineres nos Aplicativos de Contêiner do Azure.
Primeiro, crie um ambiente para os Aplicativos de Contêiner do Azure. Um ambiente em aplicativos de contêiner do Azure cria um marco de delimitação seguro em um grupo de aplicativos de contêiner. Os Aplicativos de Contêiner implantados no mesmo ambiente são implantados na mesma rede virtual e gravam logs no mesmo workspace do Log Analytics. Use o comando az containerapp env create para criar um ambiente com um nome exclusivo (por exemplo, acaenvejb010424), conforme mostrado no exemplo a seguir:
export ACA_ENV=acaenvejb010424
az containerapp env create \
--resource-group $RESOURCE_GROUP_NAME \
--location eastus \
--name $ACA_ENV
Em seguida, use o comando az containerapp create para criar uma instância de Aplicativos de Contêiner com um nome exclusivo (por exemplo, acaappejb010424) para executar o aplicativo depois de extrair a imagem do Registro de Contêiner, conforme mostrado no exemplo a seguir:
export ACA_NAME=acaappejb010424
az containerapp create \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${ACA_NAME} \
--environment ${ACA_ENV} \
--image ${ACR_LOGIN_SERVER}/open-liberty-mp-azure-keyvault:latest \
--registry-server $ACR_LOGIN_SERVER \
--registry-identity system \
--user-assigned ${USER_ASSIGNED_IDENTITY_ID} \
--env-vars \
AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} \
AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL} \
--target-port 9080 \
--ingress 'external'
Observação
Você atribui a identidade gerenciada atribuída pelo usuário à instância de Aplicativos de Contêiner com o parâmetro --user-assigned ${USER_ASSIGNED_IDENTITY_ID}
.
A instância dos Aplicativos de Contêiner pode acessar o Azure Key Vault com duas variáveis de ambiente fornecidas nos parâmetros --env-vars AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL}
. Lembre-se de que a variável de ambiente é consultada AZURE_KEYVAULT_URL
devido às Regras de Mapeamento de Variáveis de Ambiente definidas pela especificação MicroProfile Config.
Em seguida, recupere uma url totalmente qualificada para acessar o aplicativo usando o seguinte comando:
export APP_URL=https://$(az containerapp show \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${ACA_NAME} \
--query properties.configuration.ingress.fqdn \
--output tsv)
Por fim, execute os seguintes comandos novamente para testar o exemplo em execução na instância de Aplicativos de Contêiner:
# Get the value of secret "secret" stored in the Azure key vault. You should see 1234 in the response.
echo $(curl -s ${APP_URL}/config/value/secret -X GET)
# Get the value of secret "anotherSecret" stored in the Azure key vault. You should see 5678 in the response.
echo $(curl -s ${APP_URL}/config/value/anotherSecret -X GET)
# Get the names of secrets stored in the Azure key vault. You should see ["anotherSecret","secret"] in the response.
echo $(curl -s ${APP_URL}/config/propertyNames -X GET)
# Get the name-value paris of secrets stored in the Azure key vault. You should see {"anotherSecret":"5678","secret":"1234"} in the response.
echo $(curl -s ${APP_URL}/config/properties -X GET)
Você deve ver os resultados esperados descritos nos comentários. Se você não os vir, o aplicativo ainda pode estar inicializando. Aguarde um pouco e tente novamente.
Limpar os recursos
Para evitar cobranças do Azure, limpe recursos desnecessários. Quando os recursos não forem mais necessários, execute os comandos a seguir para limpar os recursos.
az keyvault delete \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEY_VAULT_NAME}"
az keyvault purge \
--name "${KEY_VAULT_NAME}" \
--no-wait
az group delete \
--name ${RESOURCE_GROUP_NAME} \
--yes \
--no-wait
Próximas etapas
Você pode saber mais nas referências a seguir: