Esercizio - Scrivere il codice di un'applicazione Java che usa segreti

Completato

Si scriverà il codice di un'applicazione Web Java, usando Spring Boot, che si connette a un database.

Per motivi di sicurezza, sarà necessario proteggere l'accesso al database in futuro. Prima di tutto creeremo l'infrastruttura dell'applicazione e quindi configureremo l'applicazione Java da usare.

Creare l'infrastruttura dell'applicazione

In questo esercizio si usa l'interfaccia della riga di comando di Azure per creare le risorse seguenti:

  • Gruppo di risorse di Azure che contiene tutte le risorse per l'applicazione.
  • Un server di database PostgreSQL.
  • Un cluster di Azure Spring Apps e un'applicazione Spring Boot in esecuzione all'interno di questo cluster.

È necessario specificare alcune variabili di ambiente all'inizio dello script che devono essere univoche in Azure.

Sarà anche necessario specificare l'indirizzo IP locale per accedere al database dal computer locale. Questo indirizzo IP deve essere un indirizzo IPv4. Se non si conosce l'indirizzo IP locale, è possibile visitare il sito Web seguente: https://www.whatismyip.com/

Impostare le seguenti variabili di ambiente:

AZ_RESOURCE_GROUP=<YOUR_UNIQUE_RESOURCE_GROUP_NAME>
AZ_DATABASE_USERNAME=<YOUR_POSTGRESQL_USERNAME>
AZ_DATABASE_PASSWORD=<YOUR_POSTGRESQL_PASSWORD>
AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

Dopo averle impostate, è possibile eseguire il comando seguente per creare le risorse:

AZ_LOCATION=eastus
# Must be all lowercase
AZ_SPRING_CLOUD=spring-${AZ_RESOURCE_GROUP,,}

AZ_DATABASE_NAME=pgsql-${AZ_RESOURCE_GROUP}
AZ_DATABASE_USERNAME=${AZ_DATABASE_USERNAME}

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION

Il completamento di questo comando può richiedere alcuni minuti.

az postgres server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --sku-name B_Gen5_1 \
    --storage-size 5120 \
    --admin-user $AZ_DATABASE_USERNAME \
    --admin-password $AZ_DATABASE_PASSWORD
az postgres server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS

az postgres server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-azure-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address 0.0.0.0 \
    --end-ip-address 0.0.0.0
az postgres db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server-name $AZ_DATABASE_NAME

Il completamento di questo comando può richiedere alcuni minuti.

az extension add --name spring

az spring create \
   --name $AZ_SPRING_CLOUD \
   --resource-group $AZ_RESOURCE_GROUP \
   --location $AZ_LOCATION \
   --sku Basic

Il completamento di questo comando può richiedere alcuni minuti.

az spring app create \
   --resource-group $AZ_RESOURCE_GROUP \
   --service $AZ_SPRING_CLOUD \
   --name application \
   --runtime-version Java_11 \
   --assign-endpoint true

L'esecuzione di questi script richiede tempo, quindi è possibile consentire l'esecuzione in background e avviare la codifica dell'applicazione nel frattempo.

Configurare l'applicazione Java

Ottenere lo scheletro dell'applicazione dal repository GitHub https://github.com/Azure-Samples/manage-secrets-in-java-applications usando il comando git clone:

git clone https://github.com/Azure-Samples/manage-secrets-in-java-applications.git

Questa applicazione usa Spring Data JPA per accedere al database. È possibile esaminare l'interfaccia del repository CRUD:

package com.example.demo;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ItemRepository extends CrudRepository<Item, Integer> {
}

I dati archiviati nel database vengono quindi esposti al Web usando un controller REST Spring MVC:

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ItemController {

    private final ItemRepository itemRepository;

    public ItemController(ItemRepository itemRepository) {
        this.itemRepository = itemRepository;
    }

    @GetMapping("/")
    String welcome() {
        return "Here are all the database items: " + itemRepository.findAll();
    }
}

Questi dati vengono inseriti nel database al momento dell'avvio, tramite il file src/main/resources/data.sql:

insert into item (details) values ('This is a item from the database');

È possibile aggiungere altre righe a questo file se si desiderano più dati o se si desidera personalizzarlo.

Per accedere al database, è necessario configurare il src/main/resources/application.properties file:

logging.level.org.springframework.jdbc.core=DEBUG

spring.datasource.url=jdbc:postgresql://${azureDatabaseName}.postgres.database.azure.com:5432/demo
spring.datasource.username=${azureDatabaseUsername}@${azureDatabaseName}
spring.datasource.password=${azureDatabasePassword}

spring.sql.init.mode=always

Questo file di configurazione include tre variabili da configurare:

  • ${azureDatabaseName} è il nome del database PostgreSQL configurato in precedenza nella variabile di ambiente AZ_DATABASE_NAME. Digitare echo $AZ_DATABASE_NAME per visualizzarlo.
  • ${azureDatabaseUsername} è il nome del nome utente del database configurato in precedenza nella variabile di ambiente AZ_DATABASE_USERNAME. Digitare echo $AZ_DATABASE_USERNAME per visualizzarlo.
  • ${azureDatabasePassword} è il nome della password di database configurata in precedenza nella variabile di ambiente AZ_DATABASE_PASSWORD. Digitare echo $AZ_DATABASE_PASSWORD per visualizzarlo.

Come illustrato nell'unità precedente, è consigliabile impostare come hardcoded tali valori nel codice sorgente dell'applicazione. Tuttavia, per testare l'applicazione, è possibile scriverli temporaneamente ed eseguirla:

./mvnw spring-boot:run

È possibile leggere il contenuto del database accedendo al controller Spring MVC usando il comando seguente oppure usando un Web browser:

curl http://localhost:8080

Distribuire l'applicazione Java in Azure

Per distribuire l'applicazione, è prima necessario crearne il pacchetto come file JAR:

./mvnw clean package

Questo comando genera un file JAR eseguibile nella target directory, che viene distribuito usando l'interfaccia della riga di comando di Azure:

az spring app deploy \
   --resource-group $AZ_RESOURCE_GROUP \
   --service $AZ_SPRING_CLOUD \
   --name application \
   --artifact-path target/*.jar

Se si verificano errori, è possibile esaminare i log applicazioni digitando il comando seguente:

az spring app logs \
   --resource-group $AZ_RESOURCE_GROUP \
   --service $AZ_SPRING_CLOUD \
   --name application

L'applicazione sarà quindi disponibile nel cloud e sarà possibile accedere ai dati usando un comando cURL:

curl https://$AZ_SPRING_CLOUD-application.azuremicroservices.io

# Expected output:
#
# Here are all the database items: [Secret{Id=1, details='This is a item from the database'}]
#

Complimenti. È stata creata correttamente un'applicazione Java che si connette a un database. A questo punto è necessario proteggere le credenziali del database nelle unità successive.