Configurer MicroProfile avec Azure Key Vault

Ce tutoriel montre comment configurer une application MicroProfile pour récupérer des secrets à partir d’Azure Key Vault à l’aide des API MicroProfile Config. Les développeurs bénéficient de l’API de configuration MicroProfile standard ouverte pour récupérer et injecter des données de configuration dans leurs microservices.

Prérequis

  • Un abonnement Azure. Si vous n’avez pas déjà un abonnement Azure, vous pouvez activer vos avantages d’abonné MSDN ou vous inscrire pour obtenir un compte gratuit.
  • Interface de ligne de commande Azure (Azure CLI) pour les environnements de type Unix. Cet article requiert uniquement la variante Bash d’Azure CLI.
    • Installez Azure CLI et connectez-vous de manière interactive avec la commande az login pour vous connecter à Azure avant d’utiliser DefaultAzureCredential du code.
      az login
      
    • Cet article nécessite au moins la version 2.55.0 d’Azure CLI. Si vous utilisez Azure Cloud Shell, sachez que la version la plus récente est déjà installée.
  • Tous ces prérequis sont déjà installés sur Azure Cloud Shell. Pour en savoir plus, consultez Démarrage rapide pour Azure Cloud Shell.
  • Si vous exécutez les commandes de ce guide localement (au lieu d’utiliser Azure Cloud Shell), procédez comme suit :
    • Préparez un ordinateur local avec un système d’exploitation de type UNIX installé (par exemple, Ubuntu, macOS, ou Sous-système Windows pour Linux).
    • Installez une implémentation Java SE version 17 ou ultérieure (par exemple, build Microsoft d’OpenJDK).
    • Installez Maven 3.5.0 ou une version ultérieure.
    • Installez cURL.

Connecter ing MicroProfile Config avec Azure Key Vault

Examinons rapidement la puissance de la combinaison d’Azure Key Vault et de l’API MicroProfile Config. Voici un extrait de code d’un champ d’une classe annotée avec @Inject et @ConfigProperty. L’annotation name spécifiée est le nom du secret à rechercher dans Azure Key Vault, et il defaultValue est utilisé si le secret n’est pas découvert. La valeur secrète stockée dans Azure Key Vault ou la valeur par défaut si aucun tel secret n’existe, est injectée automatiquement dans le champ au moment de l’exécution. L’injection de valeurs de propriété de cette façon offre de nombreux avantages. Par exemple, vous n’avez plus besoin de passer des valeurs autour des constructeurs et des méthodes setter, et la configuration est externalisée à partir du code. L’un des avantages les plus puissants est d’avoir des ensembles de valeurs distincts pour les environnements dev, test et prod.

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

Il est également possible d’accéder à la configuration MicroProfile de manière impérative, comme illustré dans l’exemple suivant :

public class DemoClass {
    @Inject
    Config config;

    public void method() {
        System.out.println("Hello: " + config.getValue("key-name", String.class));
    }
}

Cet exemple utilise l’implémentation Open Liberty de MicroProfile. Pour obtenir la liste complète des implémentations compatibles, consultez Implémentations compatibles microProfile. L’exemple montre également comment conteneuriser et exécuter l’application sur Azure.

Cet exemple utilise l’extension Azure à faible friction pour la bibliothèque Custom ConfigSource microProfile Key Vault. Pour plus d’informations sur cette bibliothèque, consultez la bibliothèque README.

Voici les étapes nécessaires à l’exécution de ce code sur votre ordinateur local, la première consistant à créer une ressource pour Azure Key Vault.

Créer une ressource Azure Key Vault

Vous utilisez Azure CLI pour créer la ressource Azure Key Vault et la remplir avec deux secrets.

Tout d’abord, connectez-vous à Azure et définissez un abonnement comme abonnement actif actuel.

az login
az account set --subscription <subscription-id>

Ensuite, créez un groupe de ressources avec un nom unique, par exemple mp-kv-rg-ejb010424.

export RESOURCE_GROUP_NAME=mp-kv-rg-ejb010424
az group create \
    --name ${RESOURCE_GROUP_NAME} \
    --location eastus

Créez maintenant une ressource Azure Key Vault avec un nom unique (par exemple, kvejb010424), ajoutez deux secrets et exportez l’URI Key Vault en tant que variable d’environnement.

export KEY_VAULT_NAME=kv-ejb010424
az keyvault create \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --name "${KEY_VAULT_NAME}" \
    --location eastus

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

La variable AZURE_KEYVAULT_URL d’environnement est requise pour configurer la bibliothèque pour qu’elle fonctionne avec l’exemple ultérieurement. Laissez le terminal ouvert et utilisez-le pour exécuter l’application localement.

Et voilà ! Vous disposez maintenant de Key Vault en cours d’exécution dans Azure avec deux secrets. Vous pouvez maintenant cloner l’exemple de dépôt et le configurer pour utiliser cette ressource dans votre application.

Mise en route et exécution locales

Cet exemple est basé sur un exemple d’application disponible sur GitHub. Basculez vers le terminal que vous avez ouvert avant et exécutez les commandes suivantes pour cloner le référentiel et exécuter l’application localement :

git clone https://github.com/Azure/azure-microprofile.git
cd azure-microprofile
git checkout 20240116
cd integration-tests/open-liberty-sample
mvn package liberty:run

Si vous voyez un message sur You are in 'detached HEAD' state, ce message est sûr à ignorer.

Remarque

La bibliothèque utilise les informations d’identification Azure par défaut pour s’authentifier dans Azure.

Étant donné que vous avez authentifié un compte via la commande Azure CLI az login localement, DefaultAzureCredential s’authentifie auprès de ce compte pour accéder à Azure Key Vault.

Attendez que la sortie soit similaire à The defaultServer server is ready to run a smarter planet. Ouvrez un nouveau terminal et exécutez les commandes suivantes pour tester l’exemple :

# 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)

Vous devez voir les sorties attendues décrites dans les commentaires. Revenez au terminal où l’application est en cours d’exécution. Appuyez sur Ctrl + C pour arrêter l’application.

Examiner l’exemple d’application

Apprenons à mieux comprendre le fonctionnement de MicroProfile Config en général, et la bibliothèque MicroProfile Key Vault Custom ConfigSource fonctionne en particulier.

Dépendance de bibliothèque

Incluez MicroProfile Key Vault Custom ConfigSource dans votre application avec la dépendance Maven suivante :

<dependency>
  <groupId>com.azure.microprofile</groupId>
  <artifactId>azure-microprofile-config-keyvault</artifactId>
</dependency>

Connecter ing vers Azure Key Vault

La azure-microprofile-config-keyvault bibliothèque connecte votre application à Azure Key Vault sans introduire de dépendances directes sur les API Azure. La bibliothèque fournit une implémentation de l’interface Config config MicroProfile qui sait lire à partir d’Azure Key Vault. Le reste de l’implémentation de MicroProfile Config est fourni par le runtime Open Liberty. Pour obtenir un lien vers la spécification, consultez Étapes suivantes.

La bibliothèque définit la azure.keyvault.url propriété de configuration pour lier votre application à un coffre de clés spécifique. La spécification de configuration MicroProfile définit les « règles de mappage des variables d’environnement » pour déterminer comment la valeur d’une propriété de configuration, telle que azure.keyvault.url, est découverte au moment de l’exécution. L’une de ces règles indique que les propriétés sont converties en variables d’environnement. La propriété azure.keyvault.url entraîne la consultation de la variable AZURE_KEYVAULT_URL d’environnement.

Classes clés dans l’exemple d’application

Examinons la ressource REST que les commandes cURL précédentes ont appelé. Cette ressource REST est définie dans la classe ConfigResource.java du integration-tests/open-liberty-sample projet.

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

La getConfigValue() méthode utilise l’implémentation injectée Config pour rechercher une valeur à partir des sources de configuration de l’application. Toutes les recherches de valeurs sur l’implémentation Config sont trouvées via l’algorithme de recherche défini par la spécification de configuration MicroProfile. La azure-microprofile-config-keyvault bibliothèque ajoute Azure Key Vault en tant que source de configuration.

La getConfigSource() méthode évite l’algorithme de recherche et accède directement aux AzureKeyVaultConfigSource propriétés de résolution. Cette méthode est utilisée par les méthodes et getConfigProperties() les getConfigPropertyNames() méthodes.

Exécuter sur Azure Container Apps

Dans cette section, vous allez conteneuriser l’application, configurer une identité managée affectée par l’utilisateur pour accéder à Azure Key Vault et déployer l’application conteneurisée sur Azure Container Apps.

Revenez au terminal où vous avez exécuté l’application localement et utilisez-la dans cette section.

Configurer un registre de conteneurs Azure

Vous utilisez Azure Container Registry pour conteneuriser l’application et stocker l’image de l’application.

Tout d’abord, créez un Registre de conteneurs Azure avec un nom unique, par exemple acrejb010424.

export ACR_NAME=acrejb010424
az acr create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $ACR_NAME \
    --sku Basic \
    --admin-enabled

Patientez quelques minutes après la retour de cette commande avant de continuer.

Conteneuriser l’application

Ensuite, conteneurisez l’application et envoyez (push) l’image de l’application à votre instance Azure Container Registry. Vérifiez que vous êtes dans le chemin de l’exemple d’application, par exemple, azure-microprofile/integration-tests/open-liberty-sample.

az acr build \
    --registry ${ACR_NAME} \
    --image open-liberty-mp-azure-keyvault:latest \
    .

Vous devez voir la sortie de build qui se termine par un message similaire à Run ID: ca1 was successful after 1m28s. Si vous ne voyez pas de message similaire, résolvez et résolvez le problème avant de continuer.

Utilisez les commandes suivantes pour récupérer les informations de connexion requises pour accéder à l’image lorsque vous déployez l’application sur Azure Container Apps ultérieurement.

export ACR_LOGIN_SERVER=$(az acr show \
    --name $ACR_NAME \
    --query 'loginServer' \
    --output tsv)
export ACR_USER_NAME=$(az acr credential show \
    --name $ACR_NAME \
    --query 'username' \
    --output tsv)
export ACR_PASSWORD=$(az acr credential show \
    --name $ACR_NAME \
    --query 'passwords[0].value' \
    --output tsv)

Configurer une identité managée affectée par l’utilisateur

Comme indiqué précédemment, la bibliothèque utilise les informations d’identification Azure par défaut pour s’authentifier dans Azure. Lorsque vous déployez l’application sur Azure Container Apps, vous définissez la variable AZURE_CLIENT_ID d’environnement pour configurer DefaultAzureCredential pour s’authentifier en tant qu’identité managée définie par l’utilisateur, qui dispose des autorisations nécessaires pour accéder à Azure Key Vault et est affectée ultérieurement à Azure Container Apps.

Tout d’abord, utilisez les commandes suivantes pour créer une identité managée affectée par l’utilisateur avec un nom unique, par exemple, uamiejb010424. Pour plus d’informations, consultez Créer une identité managée affectée par l’utilisateur.

export USER_ASSIGNED_IDENTITY_NAME=uamiejb010424
az identity create \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${USER_ASSIGNED_IDENTITY_NAME}

Ensuite, utilisez les commandes suivantes pour lui accorder des autorisations pour obtenir et répertorier les secrets à partir d’Azure Key Vault. Pour plus d’informations, consultez Affecter la stratégie d’accès.

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}"

La sortie doit contenir le code JSON suivant pour être considéré comme réussi :

"permissions": {
  "certificates": null,
  "keys": null,
  "secrets": [
    "list",
    "get"
  ],
  "storage": null
}

Si la sortie ne contient pas ce JSON, résolvez et résolvez le problème avant de continuer.

Ensuite, utilisez les commandes suivantes pour récupérer l’ID et l’ID client de l’identité managée affectée par l’utilisateur afin de pouvoir l’affecter ultérieurement à azure Container Apps pour accéder à 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

Déployer l’application sur Azure Container Apps

Vous avez conteneurisé l’application et configuré une identité managée affectée par l’utilisateur pour accéder à Azure Key Vault. Vous pouvez maintenant déployer l’application conteneurisée sur Azure Container Apps.

Tout d’abord, créez un environnement pour Azure Container Apps. Un environnement dans Azure Container Apps crée une limite sécurisée autour d’un groupe d’applications de conteneur. Les applications de conteneur déployées dans le même environnement sont déployées dans le même réseau virtuel et écrivent les journaux dans le même espace de travail Log Analytics. Utilisez la commande az containerapp env create pour créer un environnement avec un nom unique (par exemple, acaenvejb010424), comme illustré dans l’exemple suivant :

export ACA_ENV=acaenvejb010424
az containerapp env create \
    --resource-group $RESOURCE_GROUP_NAME \
    --location eastus \
    --name $ACA_ENV

Ensuite, utilisez la commande az containerapp create pour créer une instance Container Apps avec un nom unique (par exemple, acaappejb010424) pour exécuter l’application après avoir extrait l’image à partir du Registre de conteneurs, comme illustré dans l’exemple suivant :

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-username $ACR_USER_NAME \
    --registry-password $ACR_PASSWORD \
    --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'

Remarque

Vous affectez l’identité managée affectée par l’utilisateur à l’instance Container Apps avec le paramètre --user-assigned ${USER_ASSIGNED_IDENTITY_ID}.

L’instance Container Apps peut accéder à Azure Key Vault avec deux variables d’environnement fournies dans les paramètres --env-vars AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL}. N’oubliez pas que la AZURE_KEYVAULT_URL variable d’environnement est consultée en raison des règles de mappage des variables d’environnement définies par la spécification de configuration MicroProfile.

Ensuite, récupérez une URL complète pour accéder à l’application à l’aide de la commande suivante :

export APP_URL=https://$(az containerapp show \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${ACA_NAME} \
    --query properties.configuration.ingress.fqdn \
    --output tsv)

Enfin, réexécutez les commandes suivantes pour tester l’exemple en cours d’exécution sur l’instance 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)

Vous devez voir les sorties attendues décrites dans les commentaires. Si vous ne les voyez pas, l’application peut toujours démarrer. Attendez un certain temps et réessayez.

Nettoyer les ressources

Pour éviter des frais Azure, vous devez nettoyer les ressources inutiles. Lorsque les ressources ne sont plus nécessaires, exécutez les commandes suivantes pour propre les ressources.

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

Étapes suivantes

Pour plus d’informations, consultez les références suivantes :