Carga de un secreto desde Azure Key Vault en una aplicación de Spring Boot

En este tutorial se muestra cómo usar Key Vault en aplicaciones de Spring Boot para proteger los datos de configuración confidenciales y recuperar las propiedades de configuración de Key Vault. Key Vault proporciona un almacenamiento seguro de secretos genéricos, como contraseñas y cadenas de conexión de base de datos.

Requisitos previos

Importante

Se necesita Spring Boot versión 2.5 o superior para completar los pasos descritos en este artículo.

Establecimiento de un secreto en Azure Key Vault

En este tutorial se describe cómo leer las credenciales de base de datos de Key Vault en una aplicación de Spring Boot. Para leer las credenciales de Key Vault, primero debe almacenar las credenciales de base de datos en Key Vault.

Para almacenar la dirección URL de una base de datos H2 como un nuevo secreto en Key Vault, consulte Inicio rápido: Establecimiento y recuperación de un secreto de Azure Key Vault mediante Azure Portal. En este tutorial, establecerá un secreto con el nombre h2url y el valor jdbc:h2:~/testdb;user=sa;password=password.

Nota:

Después de establecer el secreto, conceda a la aplicación acceso a Key Vault siguiendo las instrucciones de Asignación de una directiva de acceso de Key Vault.

Lectura de un secreto desde Azure Key Vault

Ahora que las credenciales de base de datos se han almacenado en Key Vault, puede recuperarlas con Spring Cloud Azure.

Para instalar el módulo Spring Cloud Azure Key Vault Starter, agregue las siguientes dependencias al archivo pom.xml :

  • La lista de materiales (BOM) de Azure de Spring Cloud:

    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>com.azure.spring</groupId>
          <artifactId>spring-cloud-azure-dependencies</artifactId>
          <version>5.18.0</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>
    

    Nota:

    Si usa Spring Boot 2.x, asegúrese de establecer la versión de spring-cloud-azure-dependencies en 4.19.0. Esta lista de materiales (BOM) debe configurarse en la sección <dependencyManagement> del archivo pom.xml. Esto garantiza que todas las dependencias de Spring Cloud Azure usen la misma versión. Para obtener más información sobre la versión que se usa para esta lista de materiales, consulte Qué versión de Spring Cloud Azure debo usar.

  • El artefacto de Spring Cloud Azure Key Vault Starter:

    <dependency>
      <groupId>com.azure.spring</groupId>
      <artifactId>spring-cloud-azure-starter-keyvault</artifactId>
    </dependency>
    

Spring Cloud Azure tiene varios métodos para leer secretos de Key Vault. Puede usar los siguientes métodos de forma independiente o combinarlos para distintos casos de uso:

  • Usar el SDK de Azure para Key Vault.
  • Usar Spring KeyVault PropertySource.

Usar el SDK de Azure para Key Vault

El SDK de Azure para Key Vault proporciona SecretClient para administrar secretos en Key Vault.

En el ejemplo de código siguiente se muestra cómo usar SecretClient para recuperar credenciales de base de datos H2 de Azure Key Vault.

Para leer un secreto mediante el SDK de Azure desde Key Vault, configure la aplicación siguiendo estos pasos:

  1. Configure un punto de conexión de Key Vault en el archivo de configuración application.properties.

    spring.cloud.azure.keyvault.secret.endpoint=https://<your-keyvault-name>.vault.azure.net/
    
  2. Inyecte el bean SecretClient en la aplicación Spring y use el método getSecret para recuperar un secreto, como se muestra en el ejemplo siguiente:

    import com.azure.security.keyvault.secrets.SecretClient;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SecretClientApplication implements CommandLineRunner {
    
        // Spring Cloud Azure will automatically inject SecretClient in your ApplicationContext.
        private final SecretClient secretClient;
    
        public SecretClientApplication(SecretClient secretClient) {
            this.secretClient = secretClient;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(SecretClientApplication.class, args);
        }
    
        @Override
        public void run(String... args) {
            System.out.println("h2url: " + secretClient.getSecret("h2url").getValue());
        }
    }
    

    Sugerencia

    En este tutorial, no hay ninguna operación de autenticación en las configuraciones ni en el código. Sin embargo, la conexión a los servicios de Azure requiere autenticación. Para completar la autenticación, debe usar Azure Identity. Spring Cloud Azure usa DefaultAzureCredential, que la biblioteca de Azure Identity proporciona para ayudarle a obtener credenciales sin cambios en el código.

    DefaultAzureCredential admite varios métodos de autenticación y determina qué método se usa en tiempo de ejecución. Este enfoque permite que la aplicación use diferentes métodos de autenticación en distintos entornos, como entornos locales o de producción, sin implementar código específico del entorno. Para obtener más información, vea DefaultAzureCredential.

    Para completar la autenticación en entornos de desarrollo local, puede usar la CLI de Azure, Visual Studio Code, PowerShell u otros métodos. Para obtener más información, consulte Autenticación de Azure en entornos de desarrollo de Java. Para completar la autenticación en entornos de hospedaje de Azure, se recomienda usar la identidad administrada asignada por el usuario. Para obtener más información, consulta ¿Qué son las identidades administradas para recursos de Azure?

  3. Inicie la aplicación. Verá registros similares a los del siguiente ejemplo:

    h2url: jdbc:h2:~/testdb;user=sa;password=password
    

Puede crear el bean SecretClient por su cuenta, pero el proceso es complicado. En las aplicaciones de Spring Boot, tiene que administrar propiedades, aprender el patrón de generador y registrar el cliente en el contexto de la aplicación Spring. En el ejemplo de código siguiente se muestra cómo se compila un bean SecretClient:

import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SecretClientConfiguration {

    @Bean
    public SecretClient createSecretClient() {
        return new SecretClientBuilder()
            .vaultUrl("https://<your-key-vault-url>.vault.azure.net/")
            .credential(new DefaultAzureCredentialBuilder().build())
            .buildClient();
    }

}

En la lista siguiente se muestran algunos motivos por los que este código no es flexible o correcto:

  • El punto de conexión de Key Vault está codificado de forma fija.
  • Si usa @Value para obtener configuraciones del entorno de Spring, no puede tener sugerencias IDE en el archivo application.properties.
  • Si tiene un escenario de microservicio, debe duplicar el código de cada proyecto y es fácil cometer errores y es difícil ser coherente.

Afortunadamente, la creación del bean SecretClient por su cuenta no es necesaria con Spring Cloud Azure. En su lugar, puede inyectar SecretClient y usar directamente las propiedades de configuración con las que ya está familiarizado para configurar Key Vault. Para obtener más información, consulte Ejemplos de configuración.

Spring Cloud Azure también proporciona las siguientes configuraciones globales para diferentes escenarios. Para obtener más información, consulte la sección Configuración global de los SDK de Azure Service de Guía para desarrolladores de Spring Cloud Azure.

  • Opciones de proxy
  • Opciones de reintento.
  • Opciones de cliente de transporte de HTTP.

También puede conectarse a diferentes nubes de Azure. Para obtener más información, consulte Conexión a diferentes nubes de Azure.

Uso de PropertySource de Spring Key Vault

En las secciones anteriores se muestra cómo usar SecretClient en CommandLineRunner para leer el secreto una vez iniciada la aplicación. Sin embargo, en las aplicaciones de Spring Boot se requiere la lectura de secretos antes de que se inicie la aplicación. Por ejemplo, la propiedad de contraseña del origen de datos es necesaria antes de que se inicie la aplicación. El escenario anterior no funcionará si desea almacenar la contraseña del origen de datos en Key Vault y seguir usando la configuración automática de Spring para obtener un origen de datos.

En este caso, Spring Cloud Azure proporciona integración del entorno de Spring para cargar secretos desde Key Vault antes de compilar el contexto de la aplicación. Puede usar el secreto para construir y configurar el bean durante la inicialización del contexto de aplicación de Spring. Este enfoque es una manera transparente de acceder a secretos desde Key Vault y no se requieren cambios en el código.

En el ejemplo de código siguiente se muestra cómo usar PropertySource para recuperar credenciales de base de datos H2 para compilar el origen de datos desde Azure Key Vault.

Para recuperar la dirección URL de una base de datos H2 desde Key Vault y almacenar datos de la base de datos H2 mediante Spring Data JPA, configure la aplicación siguiendo estos pasos:

  1. Agregue las siguientes propiedades de origen de datos y punto de conexión de Key Vault al archivo de configuración application.properties.

    logging.level.org.hibernate.SQL=DEBUG
    
    spring.cloud.azure.keyvault.secret.property-sources[0].endpoint=https://<your-keyvault-name>.vault.azure.net/
    spring.datasource.url=${h2url}
    
    spring.jpa.hibernate.ddl-auto=create-drop
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    

    Sugerencia

    Para obtener ejemplos de configuración de propiedades de Azure de Spring Cloud, consulte la sección Ejemplos de configuración de la Guía para desarrolladores de Azure de Spring Cloud.

    Sugerencia

    Este ejemplo es un escenario de base de datos simple mediante una base de datos H2. Se recomienda usar Azure Database for MySQL o Azure Database for PostgreSQL en un entorno de producción y almacenar la dirección URL de la base de datos, el nombre de usuario y la contraseña en Azure Key Vault. Si desea evitar la contraseña, las conexiones sin contraseña son una buena opción. Para más información, consulte Conexiones sin contraseña para los servicios de Azure.

  2. Cree una clase nueva de Java Todo. Esta clase es un modelo de dominio asignado en la tabla todo, que se creará automáticamente mediante JPA. El siguiente código ignora los métodos getters y setters.

    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    @Entity
    public class Todo {
    
        public Todo() {
        }
    
        public Todo(String description, String details, boolean done) {
            this.description = description;
            this.details = details;
            this.done = done;
        }
    
        @Id
        @GeneratedValue
        private Long id;
    
        private String description;
    
        private String details;
    
        private boolean done;
    
    }
    
  3. Edite el archivo de clase de inicio para mostrar el siguiente contenido.

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.event.ApplicationReadyEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.annotation.Bean;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    import java.util.stream.Stream;
    
    @SpringBootApplication
    public class KeyvaultApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(KeyvaultApplication.class, args);
        }
    
        @Bean
        ApplicationListener<ApplicationReadyEvent> basicsApplicationListener(TodoRepository repository) {
            return event->repository
                .saveAll(Stream.of("A", "B", "C").map(name->new Todo("configuration", "congratulations, you have set up "
                    + "correctly!", true)).toList())
                .forEach(System.out::println);
        }
    
    }
    
    interface TodoRepository extends JpaRepository<Todo, Long> {
    
    }
    
  4. Inicie la aplicación. La aplicación recuperará la dirección URL de la base de datos H2 de Key Vault, se conectará a la base de datos H2 y almacenará los datos en la base de datos. Verá registros similares a los del siguiente ejemplo:

    2023-01-13 15:51:35.498 DEBUG 5616 --- [main] org.hibernate.SQL: insert into todo (description, details, done, id) values (?, ?, ?, ?)
    com.contoso.keyvault.Todo@1f
    

Implementación en Azure Spring Apps

Ahora que tiene la aplicación Spring Boot que se ejecuta localmente, es el momento de moverla a producción. Azure Spring Apps facilita la implementación de aplicaciones de Spring Boot en Azure sin necesidad de realizar cambios en el código. El servicio administra la infraestructura de las aplicaciones de Spring, con el fin de que los desarrolladores puedan centrarse en el código. Azure Spring Apps proporciona administración del ciclo de vida mediante el uso de una supervisión y un diagnóstico completos, administración de la configuración, detección de servicios, integración de CI/CD e implementaciones azul-verde, entre otros. Para implementar la aplicación en Azure Spring Apps, consulte Implementación de la primera aplicación en Azure Spring Apps.

Pasos siguientes