Configurare MicroProfile con Azure Key Vault

Questa esercitazione illustra come configurare un'applicazione MicroProfile per recuperare i segreti da Azure Key Vault usando le API di configurazione microProfile. Gli sviluppatori traggono vantaggio dall'API Di configurazione MicroProfile standard aperta per il recupero e l'inserimento dei dati di configurazione nei microservizi.

Prerequisiti

  • Sottoscrizione di Azure. Se non si ha una sottoscrizione di Azure, è possibile attivare i vantaggi per i sottoscrittori di MSDN oppure iscriversi per ottenere un account gratuito.
  • Interfaccia della riga di comando di Azure per ambienti simili a Unix. Questo articolo richiede solo la variante Bash dell'interfaccia della riga di comando di Azure.
    • Installare l'interfaccia della riga di comando di Azure e accedere in modo interattivo con il comando az login per accedere ad Azure prima di usare DefaultAzureCredential nel codice.
      az login
      
    • Questo articolo richiede almeno la versione 2.61.0 dell'interfaccia della riga di comando di Azure. Se si sta usando Azure Cloud Shell, la versione più recente è già installata.
  • Tutti questi prerequisiti sono preinstallati in Azure Cloud Shell. Per saperne di più, vedi Avvio rapido per Azure Cloud Shell.
  • Se stai eseguendo i comandi in questa guida in locale (anziché usare Azure Cloud Shell), completa i passaggi seguenti:
    • Prepara un computer locale con un sistema operativo simile a Unix installato (ad esempio Ubuntu, Azure Linux, macOS, Sottosistema Windows per Linux).
    • Installare un'implementazione java SE 17 o successiva (ad esempio, microsoft build di OpenJDK).
    • Installare Maven 3.9.8 o versione successiva.
    • Installa cURL.

Connessione di MicroProfile Config con Azure Key Vault

Verrà ora esaminata rapidamente la combinazione di Azure Key Vault e dell'API Di configurazione MicroProfile. Ecco un frammento di codice di un campo in una classe annotata con @Inject e @ConfigProperty. L'oggetto name specificato nell'annotazione è il nome del segreto da cercare in Azure Key Vault e defaultValue viene usato se il segreto non viene individuato. Il valore del segreto archiviato in Azure Key Vault o il valore predefinito, se tale segreto non esiste, viene inserito automaticamente nel campo in fase di esecuzione. L'inserimento di valori di proprietà in questo modo offre numerosi vantaggi. Ad esempio, non è più necessario passare valori nei costruttori e nei metodi setter e la configurazione viene esternata dal codice. Uno dei vantaggi più potenti è la presenza di set di valori separati per ambienti di sviluppo, test e produzione.

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

È anche possibile accedere in modo imperativo alla configurazione di MicroProfile, come illustrato nell'esempio seguente:

public class DemoClass {
    @Inject
    Config config;

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

Questo esempio usa l'implementazione Open Liberty di MicroProfile. Per un elenco completo delle implementazioni compatibili, vedere Implementazioni compatibili con MicroProfile. L'esempio illustra anche come inserire ed eseguire l'applicazione in Azure.

Questo esempio usa l'estensione Azure a basso attrito per la libreria ConfigSource personalizzata microProfile Key Vault. Per altre informazioni su questa libreria, vedere readME della libreria.

Di seguito sono indicati i passaggi necessari per eseguire questo codice nel computer locale, iniziando con la creazione di una risorsa di Azure Key Vault.

Creare una risorsa di Azure Key Vault

Usare l'interfaccia della riga di comando di Azure per creare la risorsa di Azure Key Vault e popolarla con due segreti.

Per prima cosa, accedere ad Azure e impostare una sottoscrizione come sottoscrizione attiva corrente.

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

Creare quindi un gruppo di risorse con un nome univoco, ad esempio mp-kv-rg-ejb010424.

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

A questo punto creare una risorsa di Azure Key Vault con un nome univoco ( ad esempio, kdeviceb010424), aggiungere due segreti ed esportare l'URI di Key Vault come variabile di 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

La variabile AZURE_KEYVAULT_URL di ambiente è necessaria per configurare la libreria in modo che funzioni con l'esempio in un secondo momento. Mantenere aperto il terminale e usarlo per l'esecuzione dell'app in locale in un secondo momento.

Ecco fatto! L'insieme di credenziali delle chiavi è ora in esecuzione in Azure con due segreti. È ora possibile clonare il repository di esempio e configurarlo per usare questa risorsa nell'app.

Esecuzione in locale

Questo esempio si basa su un'applicazione di esempio disponibile in GitHub. Passare al terminale aperto prima ed eseguire i comandi seguenti per clonare il repository ed eseguire l'app in locale:

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 viene visualizzato un messaggio su You are in 'detached HEAD' state, questo messaggio è sicuro da ignorare.

Nota

La libreria usa le credenziali di Azure predefinite per l'autenticazione in Azure.

Poiché è stato autenticato un account tramite il comando dell'interfaccia della riga di comando di Azure az login in locale, DefaultAzureCredential esegue l'autenticazione con tale account per accedere ad Azure Key Vault.

Attendere fino a quando non viene visualizzato un output simile a The defaultServer server is ready to run a smarter planet. Aprire un nuovo terminale ed eseguire i comandi seguenti per testare l'esempio:

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

Verranno visualizzati gli output previsti descritti nei commenti. Tornare al terminale in cui è in esecuzione l'app. Premi Ctrl + C per arrestare l'app.

Esaminare l'app di esempio

Si apprenderà in modo più approfondito il funzionamento di MicroProfile Config in generale e la libreria ConfigSource personalizzata di MicroProfile Key Vault funziona in particolare.

Dipendenza della libreria

Includere MicroProfile Key Vault Custom ConfigSource nell'app con la dipendenza Maven seguente:

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

Connessione ad Azure Key Vault

La azure-microprofile-config-keyvault libreria connette l'app ad Azure Key Vault senza introdurre dipendenze dirette dalle API di Azure. La libreria fornisce un'implementazione dell'interfaccia Config specification Di MicroProfile ConfigSource che sa come leggere da Azure Key Vault. Il resto dell'implementazione di MicroProfile Config viene fornito dal runtime Open Liberty. Per un collegamento alla specifica, vedere Passaggi successivi.

La libreria definisce la proprietà di configurazione per associare l'app azure.keyvault.url a un insieme di credenziali delle chiavi specifico. La specifica MicroProfile Config definisce le "Regole di mapping delle variabili di ambiente" per il modo in cui il valore di una proprietà config, ad esempio azure.keyvault.url, viene individuato in fase di esecuzione. Una di queste regole indica che le proprietà vengono convertite in variabili di ambiente. La proprietà azure.keyvault.url fa in modo che la variabile AZURE_KEYVAULT_URL di ambiente venga consultata.

Classi chiave nell'app di esempio

Si esaminerà ora la risorsa REST che hanno chiamato i comandi cURL precedenti. Questa risorsa REST viene definita nella classe ConfigResource.java nel integration-tests/open-liberty-sample progetto.

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

Il getConfigValue() metodo usa l'implementazione inserita Config per cercare un valore dalle origini di configurazione dell'applicazione. Le ricerche di valori nell'implementazione Config vengono trovate tramite l'algoritmo di ricerca definito dalla specifica MicroProfile Config. La azure-microprofile-config-keyvault libreria aggiunge Azure Key Vault come origine di configurazione.

Il getConfigSource() metodo evita l'algoritmo di ricerca e passa direttamente a AzureKeyVaultConfigSource per risolvere le proprietà. Questo metodo viene utilizzato dai getConfigPropertyNames() metodi e getConfigProperties() .

Eseguire nelle app di Azure Container

In questa sezione si in contenitori l'app, si configura un'identità gestita assegnata dall'utente per accedere ad Azure Key Vault e si distribuisce l'app in contenitori in App Azure Container.

Tornare al terminale in cui è stata eseguita l'app in locale e usarla in questa sezione.

Configurare un Registro Azure Container

Si usa il Registro Azure Container per inserire in contenitori l'app e archiviare l'immagine dell'app.

Creare prima di tutto un Registro Azure Container con un nome univoco, ad esempio acrejb010424.

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

Attendere alcuni minuti dopo che questo comando viene restituito prima di continuare.

Containerizzare l'app

Successivamente, inserire l'app in un contenitore ed eseguire il push dell'immagine dell'app nell'Registro Azure Container. Assicurarsi di essere nel percorso dell'app di esempio, ad esempio azure-microprofile/integration-tests/open-liberty-sample.

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

Verrà visualizzato l'output di compilazione che termina con un messaggio simile a Run ID: ca1 was successful after 1m28s. Se non viene visualizzato un messaggio simile, risolvere e risolvere il problema prima di continuare.

Usare i comandi seguenti per recuperare le informazioni di connessione necessarie per accedere all'immagine quando si distribuisce l'app in App Contenitore di Azure in un secondo momento.

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)

Configurare un'identità gestita assegnata dall'utente

Come indicato in precedenza, la libreria usa le credenziali di Azure predefinite per l'autenticazione in Azure. Quando si distribuisce l'app in App Azure Container, si imposta la variabile di ambiente per configurare AZURE_CLIENT_ID DefaultAzureCredential per l'autenticazione come identità gestita definita dall'utente, che dispone delle autorizzazioni per accedere ad Azure Key Vault e viene assegnata in un secondo momento ad App Contenitore di Azure.

Usare prima di tutto i comandi seguenti per creare un'identità gestita assegnata dall'utente con un nome univoco, ad esempio uamiejb010424. Per altre informazioni, vedere Creare un'identità gestita assegnata dall'utente.

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

Usare quindi i comandi seguenti per concedere le autorizzazioni per ottenere ed elencare i segreti da Azure Key Vault. Per altre informazioni, vedere Assegnare i criteri di accesso.

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

L'output deve contenere il codice JSON seguente per essere considerato riuscito:

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

Se l'output non contiene questo codice JSON, risolvere e risolvere il problema prima di continuare.

Usare quindi i comandi seguenti per recuperare l'ID e l'ID client dell'identità gestita assegnata dall'utente in modo da poterlo assegnare alle app Azure Container in un secondo momento per accedere ad 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

Distribuire l'app in App Azure Container

L'app è stata in contenitori e è stata configurata un'identità gestita assegnata dall'utente per accedere ad Azure Key Vault. È ora possibile distribuire l'app in contenitori in App Azure Container.

Creare prima di tutto un ambiente per le app contenitore di Azure. Un ambiente di App contenitore di Azure crea un limite sicuro intorno a un gruppo di app contenitore. Le app contenitore nello stesso ambiente vengono distribuite nella stessa rete virtuale e scrivono log nella stessa area di lavoro Log Analytics. Usare il comando az containerapp env create per creare un ambiente con un nome univoco , ad esempio acaendeviceb010424, come illustrato nell'esempio seguente:

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

Usare quindi il comando az containerapp create per creare un'istanza di App contenitore con un nome univoco , ad esempio acaappejb010424, per eseguire l'app dopo aver eseguito il pull dell'immagine dal Registro Contenitori, come illustrato nell'esempio seguente:

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'

Nota

L'identità gestita assegnata dall'utente viene assegnata all'istanza di App contenitore con il parametro --user-assigned ${USER_ASSIGNED_IDENTITY_ID}.

L'istanza di App contenitore può accedere ad Azure Key Vault con due variabili di ambiente fornite nei parametri --env-vars AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL}. Tenere presente che la AZURE_KEYVAULT_URL variabile di ambiente viene consultata a causa delle regole di mapping delle variabili di ambiente definite dalla specifica MicroProfile Config.

Recuperare quindi un URL completo per accedere all'app usando il comando seguente:

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

Eseguire infine di nuovo i comandi seguenti per testare l'esempio in esecuzione nell'istanza di App contenitore:

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

Verranno visualizzati gli output previsti descritti nei commenti. Se non vengono visualizzate, l'app potrebbe comunque essere avviata. Attendere un po' e riprovare.

Pulire le risorse

Per evitare addebiti per Azure, è necessario eliminare le risorse non necessarie. Quando le risorse non sono più necessarie, eseguire i comandi seguenti per pulire le risorse.

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

Passaggi successivi

Per altre informazioni, vedere le risorse riportate di seguito: