Partilhar via


Configurar o 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 de configuração do MicroProfile 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 seus benefícios de assinante do MSDN ou se inscrever para uma conta gratuita.
  • CLI do Azure para ambientes Unix-like. Este 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 no código.
      az login
      
    • Este artigo requer pelo menos a versão 2.61.0 da CLI do Azure. Se você estiver usando o Azure Cloud Shell, a versão mais recente já está instalada.
  • O Azure Cloud Shell tem todos esses pré-requisitos pré-instalados. Para saber mais, consulte Guia de 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 uma máquina local com o sistema operacional Unix-like instalado (por exemplo, Ubuntu, macOS ou Windows Subsystem for Linux).
    • Instale uma implementação 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 a configuração do MicroProfile 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 Cofre da Chave do Azure e o defaultValue é usado se o segredo não for descoberto. O valor secreto armazenado no Cofre de Chaves do Azure, ou o valor padrão se esse segredo não existir, é injetado automaticamente no campo em tempo de execução. Injetar valores de propriedade desta forma proporciona inúmeros 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 prod.

@Inject
@ConfigProperty(name = "key-name", defaultValue = "Unknown")
String keyValue;

Também é possível acessar a configuração do MicroProfile imperativamente, como 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 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 contentorizar e executar o aplicativo no Azure.

Este exemplo usa a extensão do Azure de baixo atrito para a biblioteca MicroProfile Key Vault Custom ConfigSource. Para obter mais informações sobre esta biblioteca, consulte o Leiame da biblioteca.

Estes são os passos necessários para executar este código no seu computador local, a começar pela criação de um recurso do Azure Key Vault.

Criar um recurso do Azure Key Vault

Use a CLI do Azure para criar o recurso Azure Key Vault e preenchê-lo com dois segredos.

Primeiro, entre no Azure e defina uma assinatura como sendo 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 Cofre da Chave do Azure com um nome exclusivo (por exemplo, kvejb010424), adicione dois segredos e exporte o uri do Cofre da Chave 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.

Está feito! Agora você tem o Cofre da Chave 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.

Comece a trabalhar localmente

Este exemplo é baseado em um aplicativo de exemplo disponível no GitHub. Mude para o terminal que 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 vir uma mensagem sobre You are in 'detached HEAD' stateo , é seguro ignorá-la.

Nota

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 Cofre da Chave do Azure.

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 o exemplo:

# 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 as saídas esperadas descritas nos comentários. Volte para o terminal onde o aplicativo está sendo executado. Pressione Ctrl + C para parar 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 da 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 Cofre da Chave do Azure 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 ler a partir 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 vincular 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 config, como azure.keyvault.url, é descoberto em 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.

Principais classes no aplicativo de exemplo

Vamos examinar o recurso REST que os comandos cURL anteriores chamaram. Este recurso REST é definido na classe ConfigResource.java no 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 procurar um valor das fontes de configuração do aplicativo. Qualquer pesquisa de valor na Config implementação é encontrada através 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 Cofre da Chave do Azure e implanta o aplicativo em contêineres nos Aplicativos de Contêiner do Azure.

Volte para o terminal onde 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 deste comando antes de continuar.

Contentorizar a aplicação

Em seguida, coloque o aplicativo em contêiner e envie a imagem do aplicativo 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 compilação que termina com uma mensagem semelhante a Run ID: ca1 was successful after 1m28s. Se não vir uma mensagem semelhante, 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 quando você implantar o aplicativo nos Aplicativos de Contêiner do Azure mais tarde.

export ACR_LOGIN_SERVER=$(az acr show \
    --name $ACR_NAME \
    --query 'loginServer' \
    --output tsv)

Configurar uma identidade gerenciada atribuída pelo usuário

Como dito anteriormente, a biblioteca usa a credencial padrão do Azure para autenticar no Azure. Ao implantar o aplicativo em 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 Cofre de Chaves do Azure e é atribuída aos Aplicativos de Contêiner do Azure posteriormente.

Primeiro, use os seguintes comandos para criar uma identidade gerenciada atribuída pelo usuário com um nome exclusivo, por exemplo, uamiejb010424. Para obter mais informações, consulte 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 Cofre da Chave do Azure. 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 seus Aplicativos de Contêiner do Azure mais tarde para acessar o Cofre da Chave do Azure:

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 em Aplicativos de Contêiner do Azure

Você colocou o aplicativo em contêiner e configurou uma identidade gerenciada atribuída pelo usuário para acessar o Cofre da Chave do Azure. Agora você pode implantar o aplicativo em contêiner 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 limite seguro em torno de 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 espaço de trabalho 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 Container Apps 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'

Nota

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 de Aplicativos de Contêiner pode acessar o Cofre de Chaves do Azure 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, 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)

Finalmente, execute os seguintes comandos novamente para testar o exemplo em execução na instância Container Apps:

# 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 as saídas esperadas descritas nos comentários. Se você não vê-los, o aplicativo ainda pode estar iniciando. Aguarde algum tempo e tente novamente.

Clean up resources (Limpar recursos)

Para evitar cobranças do Azure, você deve limpar recursos desnecessários. Quando os recursos não forem mais necessários, execute os seguintes comandos 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óximos passos

Você pode aprender mais com as seguintes referências: