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 requiere Spring Boot versión 2.5 o posterior 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 de 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.11.0</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>
    

    Nota:

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

  • El artefacto 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 métodos siguientes de forma independiente o combinarlos para distintos casos de uso:

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

Uso del 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. Inserte el bean en la SecretClient aplicación spring y use el getSecret método 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 identidades de Azure 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 a la aplicación usar diferentes métodos de autenticación en distintos entornos (como entornos locales y 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 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, consulte ¿Qué son las identidades administradas para recursos de Azure?

  3. Inicie la aplicación. Verá registros similares al ejemplo siguiente:

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

Puede crear el SecretClient bean 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 SecretClient bean:

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 de los motivos por los que este código no es flexible o correcto:

  • El punto de conexión de Key Vault está codificado de forma rígida.
  • 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, el código debe duplicarse en cada proyecto y es fácil cometer errores y es difícil ser coherente.

Afortunadamente, la creación del SecretClient bean por su cuenta no es necesaria con Spring Cloud Azure. En su lugar, puede insertar 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, vea Ejemplos de configuración.

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

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

También puede conectarse a diferentes nubes de Azure. Para más información, consulte Conectar 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 de 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 nueva Todo clase de Java. Esta clase es un modelo de dominio asignado a la todo tabla que JPA creará automáticamente. El código siguiente omite los getters métodos 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 al ejemplo siguiente:

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