Condividi tramite


Esercitazione: Connettersi al database PostgreSQL da un'applicazione contenitore Java Quarkus senza segreti tramite un'identità gestita

App contenitore di Azure offre un'identità gestita per l'app, una soluzione chiavi in mano per proteggere l'accesso a Database di Azure per PostgreSQL e ad altri servizi di Azure. Le identità gestite nelle App contenitore rendono l'app più sicura eliminando i segreti dall'app, ad esempio le credenziali nelle variabili di ambiente.

Questa esercitazione illustra il processo di creazione, configurazione, distribuzione e ridimensionamento di app contenitore Java in Azure. Alla fine di questa esercitazione si avrà un'applicazione Quarkus che archivia i dati in un database PostgreSQL con un'identità gestita in esecuzione in App contenitore.

Contenuto dell'esercitazione:

  • Configurare un'app Quarkus per l'autenticazione usando Microsoft Entra ID con un database PostgreSQL.
  • Creare un registro Azure Container ed eseguire il push di un'immagine dell'app Java in esso.
  • Creare un'app contenitore in Azure.
  • Creare un database PostgreSQL in Azure.
  • Connettersi al database PostgreSQL con identità gestita tramite la funzionalità Connettore servizio.

Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.

1. Prerequisiti

2. Creare un registro contenitori

Creare un gruppo di risorse con il comando az group create. Un gruppo di risorse di Azure è un contenitore logico in cui le risorse di Azure vengono distribuite e gestite.

L'esempio seguente crea un gruppo di risorse nell'area di Azure denominata myResourceGroup nell'area di Azure Stati Uniti orientali.

az group create --name myResourceGroup --location eastus

Creare un'istanza del Registro Azure Container usando il comando az acr create. Il nome del registro deve essere univoco in Azure e contenere da 5 a 50 caratteri alfanumerici. Tutte le lettere devono essere specificate in minuscolo. Il seguente esempio usa mycontainerregistry007. Aggiornarlo a un valore univoco.

az acr create \
    --resource-group myResourceGroup \
    --name mycontainerregistry007 \
    --sku Basic

3. Clonare l'app di esempio e preparare l'immagine del contenitore

In questa esercitazione viene usata un'app elenco Frutta di esempio con un'interfaccia utente Web che chiama un'API REST Quarkus supportata da Database di Azure per PostgreSQL. Il codice per l'app è disponibile in GitHub. Per altre informazioni sulla scrittura di app Java con Quarkus e PostgreSQL, vedere la Guida a Quarkus Hibernate ORM con Panache e la Guida a Quarkus Datasource.

Eseguire i comandi seguenti nel terminale per clonare il repository di esempio e configurare l'ambiente dell'app di esempio.

git clone https://github.com/quarkusio/quarkus-quickstarts
cd quarkus-quickstarts/hibernate-orm-panache-quickstart

Modificare il progetto

  1. Aggiungere le dipendenze necessarie al file BOM del progetto.

    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-identity-providers-jdbc-postgresql</artifactId>
        <version>1.0.0-beta.1</version>
    </dependency>
    
  2. Configurare le proprietà dell'app Quarkus.

    La configurazione di Quarkus si trova nel file src/main/resources/application.properties. Aprire questo file nell'editor e osservare diverse proprietà predefinite. Le proprietà precedute da %prod vengono usate solo quando l'applicazione viene compilata e distribuita, ad esempio quando viene distribuita nel servizio app di Azure. Quando l'applicazione viene eseguita in locale, le proprietà %prod vengono ignorate. Analogamente, le proprietà %dev vengono usate nella modalità live coding/sviluppo di Quarkus e le proprietà %test vengono usate durante i test continui.

    Eliminare il contenuto esistente in application.properties e sostituire con quanto segue per configurare il database per le modalità di sviluppo, test e produzione:

    quarkus.package.type=uber-jar
    
    quarkus.hibernate-orm.database.generation=drop-and-create
    quarkus.datasource.db-kind=postgresql
    quarkus.datasource.jdbc.max-size=8
    quarkus.datasource.jdbc.min-size=2
    quarkus.hibernate-orm.log.sql=true
    quarkus.hibernate-orm.sql-load-script=import.sql
    quarkus.datasource.jdbc.acquisition-timeout = 10
    
    %dev.quarkus.datasource.username=${AZURE_CLIENT_NAME}
    %dev.quarkus.datasource.jdbc.url=jdbc:postgresql://${DBHOST}.postgres.database.azure.com:5432/${DBNAME}?\
    authenticationPluginClassName=com.azure.identity.providers.postgresql.AzureIdentityPostgresqlAuthenticationPlugin\
    &sslmode=require\
    &azure.clientId=${AZURE_CLIENT_ID}\
    &azure.clientSecret=${AZURE_CLIENT_SECRET}\
    &azure.tenantId=${AZURE_TENANT_ID}
    
    %prod.quarkus.datasource.username=${AZURE_MI_NAME}
    %prod.quarkus.datasource.jdbc.url=jdbc:postgresql://${DBHOST}.postgres.database.azure.com:5432/${DBNAME}?\
    authenticationPluginClassName=com.azure.identity.providers.postgresql.AzureIdentityPostgresqlAuthenticationPlugin\
    &sslmode=require
    
    %dev.quarkus.class-loading.parent-first-artifacts=com.azure:azure-core::jar,\
    com.azure:azure-core-http-netty::jar,\
    io.projectreactor.netty:reactor-netty-core::jar,\
    io.projectreactor.netty:reactor-netty-http::jar,\
    io.netty:netty-resolver-dns::jar,\
    io.netty:netty-codec::jar,\
    io.netty:netty-codec-http::jar,\
    io.netty:netty-codec-http2::jar,\
    io.netty:netty-handler::jar,\
    io.netty:netty-resolver::jar,\
    io.netty:netty-common::jar,\
    io.netty:netty-transport::jar,\
    io.netty:netty-buffer::jar,\
    com.azure:azure-identity::jar,\
    com.azure:azure-identity-providers-core::jar,\
    com.azure:azure-identity-providers-jdbc-postgresql::jar,\
    com.fasterxml.jackson.core:jackson-core::jar,\
    com.fasterxml.jackson.core:jackson-annotations::jar,\
    com.fasterxml.jackson.core:jackson-databind::jar,\
    com.fasterxml.jackson.dataformat:jackson-dataformat-xml::jar,\
    com.fasterxml.jackson.datatype:jackson-datatype-jsr310::jar,\
    org.reactivestreams:reactive-streams::jar,\
    io.projectreactor:reactor-core::jar,\
    com.microsoft.azure:msal4j::jar,\
    com.microsoft.azure:msal4j-persistence-extension::jar,\
    org.codehaus.woodstox:stax2-api::jar,\
    com.fasterxml.woodstox:woodstox-core::jar,\
    com.nimbusds:oauth2-oidc-sdk::jar,\
    com.nimbusds:content-type::jar,\
    com.nimbusds:nimbus-jose-jwt::jar,\
    net.minidev:json-smart::jar,\
    net.minidev:accessors-smart::jar,\
    io.netty:netty-transport-native-unix-common::jar
    

Compilare ed eseguire il push di un'immagine Docker nel registro contenitori

  1. Compilare l'immagine del contenitore.

    Eseguire il comando seguente per compilare l'immagine dell'app Quarkus. È necessario contrassegnarlo con il nome completo del server di accesso del Registro di sistema. Il nome del server di accesso è nel formato <registry-name>.azurecr.io (deve essere tutto in minuscolo), ad esempio mycontainerregistry007.azurecr.io. Sostituire il nome con il proprio nome del Registro di sistema.

    mvnw quarkus:add-extension -Dextensions="container-image-jib"
    mvnw clean package -Pnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true -Dquarkus.container-image.registry=mycontainerregistry007 -Dquarkus.container-image.name=quarkus-postgres-passwordless-app -Dquarkus.container-image.tag=v1
    
  2. Accedere al Registro di sistema.

    Prima di eseguire il push delle immagini del contenitore, è necessario accedere al registro. A tale scopo, usare il comando [az acr login][az-acr-login]. Specificare solo il nome della risorsa del Registro di sistema durante l'accesso con l'interfaccia della riga di comando di Azure. Non usare il nome completo del server di accesso.

    az acr login --name <registry-name>
    

    Il comando restituisce un messaggio Login Succeeded al termine dell'esecuzione.

  3. Eseguire il push dell'immagine nel registro.

    Usare [docker push][docker-push] per eseguire il push dell'immagine nell'istanza del Registro di sistema. Sostituire mycontainerregistry007 con il nome del server di accesso dell'istanza del registro. Questo esempio crea il repository quarkus-postgres-passwordless-app che contiene l'immagine quarkus-postgres-passwordless-app:v1.

    docker push mycontainerregistry007/quarkus-postgres-passwordless-app:v1
    

4. Creare un'app contenitore in Azure

  1. Creare un'istanza di App contenitore eseguendo il comando seguente. Assicurarsi di sostituire il valore delle variabili di ambiente con il nome e la posizione effettivi da usare.

    RESOURCE_GROUP="myResourceGroup"
    LOCATION="eastus"
    CONTAINERAPPS_ENVIRONMENT="my-environment"
    
    az containerapp env create \
        --resource-group $RESOURCE_GROUP \
        --name $CONTAINERAPPS_ENVIRONMENT \
        --location $LOCATION
    
  2. Creare un'app contenitore con l'immagine dell'app eseguendo il comando seguente. Sostituire i segnaposto con i valori. Per trovare i dettagli dell'account amministratore del registro contenitori, vedere Eseguire l'autenticazione con un registro Azure Container

    CONTAINER_IMAGE_NAME=quarkus-postgres-passwordless-app:v1
    REGISTRY_SERVER=mycontainerregistry007
    REGISTRY_USERNAME=<REGISTRY_USERNAME>
    REGISTRY_PASSWORD=<REGISTRY_PASSWORD>
    
    az containerapp create \
        --resource-group $RESOURCE_GROUP \
        --name my-container-app \
        --image $CONTAINER_IMAGE_NAME \
        --environment $CONTAINERAPPS_ENVIRONMENT \
        --registry-server $REGISTRY_SERVER \
        --registry-username $REGISTRY_USERNAME \
        --registry-password $REGISTRY_PASSWORD
    

5. Creare e connettere un database PostgreSQL con connettività di identità

Creare quindi un database PostgreSQL e configurare l'app contenitore per connettersi a un database PostgreSQL con un'identità gestita assegnata dal sistema. L'app Quarkus si connetterà a questo database e archivierà i propri dati durante l'esecuzione, rendendo persistente lo stato dell'applicazione indipendentemente dalla posizione in cui viene eseguita.

  1. Creare il servizio del database.

    DB_SERVER_NAME='msdocs-quarkus-postgres-webapp-db'
    ADMIN_USERNAME='demoadmin'
    ADMIN_PASSWORD='<admin-password>'
    
    az postgres flexible-server create \
        --resource-group $RESOURCE_GROUP \
        --name $DB_SERVER_NAME \
        --location $LOCATION \
        --admin-user $DB_USERNAME \
        --admin-password $DB_PASSWORD \
        --sku-name GP_Gen5_2
    

    I parametri seguenti vengono usati nel comando dell'interfaccia della riga di comando di Azure precedente:

    • resource-group → Usare lo stesso nome del gruppo di risorse in cui è stata creata l'app Web, ad esempio msdocs-quarkus-postgres-webapp-rg.

    • nome → il nome del server di database PostgreSQL. Questo nome deve essere univoco in tutti gli ambienti di Azure (l'endpoint server diventa https://<name>.postgres.database.azure.com). I caratteri consentiti sono A-Z, 0-9 e -. Un criterio valido consiste nell'usare una combinazione del nome della società e di un identificatore del server. (msdocs-quarkus-postgres-webapp-db)

    • posizione → Usare la stessa posizione usata per l'app Web.

    • Nome utente amministratore → nome utente per l'account amministratore. Non può essere azure_superuser, admin, administrator, root, guest o public. Ad esempio, demoadmin va bene.

    • Password amministratore → password dell'utente amministratore. Deve contenere da 8 a 128 caratteri di tre delle categorie seguenti: lettere maiuscole, lettere minuscole, numeri e caratteri non alfanumerici.

      Importante

      Quando si creano nomi utente o password non usare il carattere $. Successivamente nell'esercitazione, si creano variabili di ambiente con questi valori, in cui il carattere $ ha un significato speciale all'interno del contenitore Linux usato per eseguire le app Java.

    • public-accessNone che imposta il server in modalità di accesso pubblico senza regole del firewall. Le regole verranno create in un passaggio successivo.

    • sku-name → Il nome del piano tariffario e della configurazione di calcolo, ad esempio GP_Gen5_2. Per altre informazioni, vedere Piano tariffario di Database di Azure per PostgreSQL.

  2. Creare un database denominato fruits all'interno del servizio PostgreSQL con questo comando:

    az postgres flexible-server db create \
        --resource-group $RESOURCE_GROUP \
        --server-name $DB_SERVER_NAME \
        --database-name fruits
    
  3. Installare l'estensione senza password Connettore di servizi per l'interfaccia della riga di comando di Azure:

    az extension add --name serviceconnector-passwordless --upgrade
    
  4. Connettere il database all'app contenitore con un'identità gestita assegnata dal sistema usando il comando di connessione.

    az containerapp connection create postgres-flexible \
        --resource-group $RESOURCE_GROUP \
        --name my-container-app \
        --target-resource-group $RESOURCE_GROUP \
        --server $DB_SERVER_NAME \
        --database fruits \
        --managed-identity
    

6. Esaminare le modifiche

È possibile trovare l'URL dell'applicazione (FQDN) usando il comando seguente:

az containerapp list --resource-group $RESOURCE_GROUP

Quando nella nuova pagina Web viene visualizzato l'elenco di frutti, l'app si connette al database con l'identità gestita. Dovrebbe ora essere possibile modificare l'elenco di frutta come in precedenza.

Pulire le risorse

Nei passaggi precedenti sono state create risorse di Azure in un gruppo di risorse. Se si ritiene che queste risorse non saranno necessarie in futuro, eliminare il gruppo di risorse eseguendo questo comando in Cloud Shell:

az group delete --name myResourceGroup

L'esecuzione del comando può richiedere un minuto.

Passaggi successivi

Altre informazioni sull'esecuzione di app Java in Azure sono disponibili nella guida per sviluppatori.