Ejercicio: Programación de una aplicación de Java que usa secretos

Completado

Va a programar una aplicación web de Java, mediante Spring Boot, que se conecta a una base de datos.

Por motivos de seguridad, tendrá que proteger el acceso a la base de datos en el futuro. Pero primero se creará la infraestructura de la aplicación y, después, se configurará la aplicación de Java que se va a usar.

Creación de la infraestructura de la aplicación

En este ejercicio, usará la CLI de Azure para crear los siguientes recursos:

  • Un grupo de recursos de Azure, que contendrá todos los recursos de la aplicación.
  • Un servidor de bases de datos de PostgreSQL.
  • Un clúster de Azure Spring Apps y una aplicación de Spring Boot que se ejecuta dentro de este clúster.

Tendrá que proporcionar algunas variables de entorno al principio del script que deben ser únicas en Azure.

También debe proporcionar la dirección IP local para acceder a la base de datos desde el equipo local. Esta dirección IP debe ser una dirección IPv4. Si no conoce la dirección IP local, puede ir al siguiente sitio web: https://www.whatismyip.com/.

Establezca estas variables de entorno:

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>

Una vez que establezca esas variables de entorno, puede ejecutar el comando siguiente para crear los recursos:

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

Este comando puede tardar varios minutos en completarse.

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

Este comando puede tardar varios minutos en completarse.

az extension add --name spring

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

Este comando puede tardar varios minutos en completarse.

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

Estos scripts tardan algún tiempo en ejecutarse, por lo que puede permitirles ejecutarse en segundo plano y empezar a codificar la aplicación mientras tanto.

Configuración de la aplicación de Java

Obtenga el esqueleto de la aplicación del repositorio de GitHub https://github.com/Azure-Samples/manage-secrets-in-java-applications mediante el comando git clone:

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

Esta aplicación usa Spring Data JPA para acceder a la base de datos. Puede ver la interfaz del repositorio CRUD:

package com.example.demo;

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

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

Los datos que se almacenan en la base de datos se exponen a la web mediante un controlador REST MVC de Spring:

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

Estos datos se insertan en la base de datos durante el inicio, mediante el archivo src/main/resources/data.sql:

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

Puede agregar más líneas a este archivo si quiere más datos o si quiere personalizarlo.

Para acceder a la base de datos, tiene que configurar el archivo src/main/resources/application.properties:

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

Este archivo de configuración tiene tres variables que se deben configurar:

  • ${azureDatabaseName} es el nombre de la base de datos PostgreSQL que se ha configurado antes en la variable de entorno AZ_DATABASE_NAME. Escriba echo $AZ_DATABASE_NAME para verla.
  • ${azureDatabaseUsername} es el nombre del usuario de base de datos que se ha configurado antes en la variable de entorno AZ_DATABASE_USERNAME. Escriba echo $AZ_DATABASE_USERNAME para verlo.
  • ${azureDatabasePassword} es el nombre de la contraseña de base de datos que se ha configurado antes en la variable de entorno AZ_DATABASE_PASSWORD. Escriba echo $AZ_DATABASE_PASSWORD para verla.

Como vimos en la unidad anterior, no se recomienda codificar de forma rígida esos valores en el código fuente de la aplicación. Pero para probar la aplicación, puede escribirlos temporalmente y ejecutarla:

./mvnw spring-boot:run

Puede leer el contenido de la base de datos si accede al controlador MVC de Spring mediante el siguiente comando o con un explorador web:

curl http://localhost:8080

Implementación de la aplicación Java en Azure

Para implementar la aplicación, primero tiene que empaquetarla como un archivo Jar:

./mvnw clean package

Este comando genera un archivo Jar ejecutable en el directorio target, que se implementa mediante la CLI de Azure:

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

Si se producen errores, puede ver los registros de la aplicación si escribe el comando siguiente:

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

Después, la aplicación estará disponible en la nube y puede acceder a sus datos mediante 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'}]
#

Felicidades. Ha creado correctamente una aplicación de Java que se conecta a una base de datos. Ahora tiene que proteger las credenciales de la base de datos en las unidades siguientes.