Compartir a través de


Habilitación de HTTPS en Spring Boot con certificados de Azure Key Vault

En este tutorial se muestra cómo proteger las aplicaciones de Spring Boot (incluidas Azure Spring Apps) con certificados TLS/SSL mediante Azure Key Vault e identidades administradas para recursos de Azure.

Las aplicaciones de Spring Boot de nivel de producción, ya sea en la nube o en el entorno local, requieren cifrado de un extremo a otro para el tráfico de red mediante protocolos TLS estándar. La mayoría de los certificados TLS/SSL que puedes encontrar son accesibles a través de una autoridad de certificación raíz pública. A veces, sin embargo, esta detección no es posible. Cuando los certificados no se pueden detectar, la aplicación debe tener alguna manera de cargar dichos certificados, presentarlos a las conexiones de red entrantes y aceptarlos de las conexiones de red salientes.

Las aplicaciones de Spring Boot suelen habilitar TLS mediante la instalación de los certificados. Los certificados se instalan en el almacén de claves local de la JVM que ejecuta la aplicación Spring Boot. Con Spring en Azure, los certificados no se instalan localmente. En su lugar, la integración de Spring para Microsoft Azure proporciona una manera segura y sin fricción de habilitar TLS con ayuda de Azure Key Vault e identidad administrada para los recursos de Azure.

Diagrama que muestra la interacción de los elementos en este tutorial.

Importante

Actualmente, Spring Cloud Azure Certificate Starter versión 4.x o posterior no admite TLS/mTLS, solo configuran automáticamente el cliente de certificados de Key Vault. Por lo tanto, si desea usar TLS/mTLS, no puede migrar a la versión 4.x.

Prerrequisitos

  • Una suscripción a Azure: cree una cuenta gratuita.

  • Un kit de desarrollo de Java (JDK) admitido, versión 11.

  • Apache Maven versión 3.0 o posterior.

  • CLI de Azure

  • cURL o una utilidad HTTP similar para probar la funcionalidad.

  • Una instancia de máquina virtual (VM) de Azure. Si no tiene una, use el comando az vm create y la imagen de Ubuntu proporcionada por UbuntuServer para crear una instancia de máquina virtual con una identidad administrada asignada por el sistema habilitada. Conceda el rol Contributor a la identidad administrada asignada por el sistema y luego configure el acceso scope en su suscripción.

  • Una instancia de Azure Key Vault. Si no la tiene, consulte Inicio rápido: Creación de una instancia de Key Vault mediante Azure Portal.

  • Una aplicación de Spring Boot. Si no tiene uno, cree un proyecto Maven con Spring Initializr. Asegúrese de seleccionar del proyecto de Maven y, en Dependencias, agregue la dependencia Spring Web y, después, seleccione Versión de Java 8 o posterior.

Importante

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

Establecimiento de un certificado TLS/SSL autofirmado

Los pasos de este tutorial se aplican a cualquier certificado TLS/SSL (incluido el autofirmado) almacenado directamente en Azure Key Vault. Los certificados autofirmados no son adecuados para su uso en producción, pero son útiles para aplicaciones de desarrollo y pruebas.

En este tutorial se usa un certificado autofirmado. Para establecer el certificado, consulte Inicio rápido: Establecimiento y recuperación de un certificado de Azure Key Vault mediante Azure Portal.

Nota

Después de establecer el certificado, conceda a la máquina virtual acceso a Key Vault siguiendo las instrucciones de Asignación de una directiva de acceso de Key Vault.

Protección de la conexión a través del certificado TLS/SSL

Ahora tiene una máquina virtual y una instancia de Key Vault, y ha concedido acceso de la máquina virtual al Key Vault. En las secciones siguientes se muestra cómo conectarse de forma segura a través de certificados TLS/SSL desde Azure Key Vault en la aplicación Spring Boot. En este tutorial se muestran los dos escenarios siguientes:

  • Ejecución de una aplicación de Spring Boot con conexiones entrantes seguras
  • Ejecución de una aplicación de Spring Boot con conexiones salientes seguras

Sugerencia

En los pasos siguientes, el código se empaquetará en un archivo ejecutable y se cargará en la máquina virtual. No olvide instalar OpenJDK en la máquina virtual.

Ejecución de una aplicación de Spring Boot con conexiones entrantes seguras

Cuando el certificado TLS/SSL para la conexión entrante procede de Azure Key Vault, configure la aplicación siguiendo estos pasos:

  1. Agregue las siguientes dependencias al archivo pom.xml:

    <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId>
       <version>3.14.0</version>
    </dependency>
    
  2. Configure las credenciales de Key Vault en el archivo de configuración application.properties.

    server.ssl.key-alias=<the name of the certificate in Azure Key Vault to use>
    server.ssl.key-store-type=AzureKeyVault
    server.ssl.trust-store-type=AzureKeyVault
    server.port=8443
    azure.keyvault.uri=<the URI of the Azure Key Vault to use>
    

    Estos valores permiten que la aplicación Spring Boot realice la carga acción para el certificado TLS/SSL, como se mencionó al principio del tutorial. En la tabla siguiente se describen los valores de propiedad.

    Propiedad Descripción
    server.ssl.key-alias El valor del argumento --name que pasó a az keyvault certificate create.
    server.ssl.key-store-type Debe ser AzureKeyVault.
    server.ssl.trust-store-type Debe ser AzureKeyVault.
    server.port Puerto TCP local en el que se van a escuchar las conexiones HTTPS.
    azure.keyvault.uri La propiedad vaultUri del JSON devuelto desde az keyvault create. Tú guardaste este valor en una variable de entorno.

    La única propiedad específica de Key Vault es azure.keyvault.uri. La aplicación se ejecuta en una máquina virtual cuya identidad administrada asignada por el sistema se ha concedido acceso a Key Vault. Por lo tanto, también se ha concedido acceso a la aplicación.

    Estos cambios permiten que la aplicación Spring Boot cargue el certificado TLS/SSL. En el paso siguiente, habilitará la aplicación para que realice la acción accept en el certificado TLS/SSL, como se indicó al principio del tutorial.

  3. Edite el archivo de clase de inicio para que tenga el siguiente contenido.

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    public class SsltestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SsltestApplication.class, args);
        }
    
        @GetMapping(value = "/ssl-test")
        public String inbound(){
            return "Inbound TLS is working!!";
        }
    
        @GetMapping(value = "/exit")
        public void exit() {
            System.exit(0);
        }
    
    }
    

    Llamar a System.exit(0) desde dentro de una llamada REST GET no autenticada solo es para fines de demostración. No use System.exit(0) en una aplicación real.

    Este código muestra la acción present mencionada al principio de este tutorial. En la lista siguiente se resaltan algunos detalles sobre este código:

    • Ahora hay una anotación @RestController en la clase SsltestApplication generada por Spring Initializr.
    • Hay un método anotado con @GetMapping, con un value para la llamada HTTP que realice.
    • El método inbound simplemente devuelve un saludo cuando un explorador realiza una solicitud HTTPS a la ruta de acceso /ssl-test. El método inbound muestra cómo el servidor presenta el certificado TLS/SSL al explorador.
    • El método exit hace que la JVM salga cuando se invoque. Este método es una comodidad para facilitar la ejecución del ejemplo en el contexto de este tutorial.
  4. Ejecute los siguientes comandos para compilar el código y empaquetarlo en un archivo JAR ejecutable.

    mvn clean package
    
  5. Compruebe que el grupo de seguridad de red creado en <your-resource-group-name> permite el tráfico entrante en los puertos 22 y 8443 desde su dirección IP. Para obtener información sobre cómo configurar reglas de grupo de seguridad de red para permitir el tráfico entrante, consulte la sección Trabajar con reglas de seguridad de Crear, cambiar o eliminar un grupo de seguridad de red.

  6. Coloque el archivo JAR ejecutable en la máquina virtual.

    cd target
    sftp azureuser@<your VM public IP address>
    put *.jar
    

    Ahora que ha compilado la aplicación Spring Boot y la ha cargado en la máquina virtual, siga estos pasos para ejecutarla en la máquina virtual y llamar al punto de conexión rest con curl.

  7. Use SSH para conectarse a la máquina virtual y, a continuación, ejecute el archivo JAR ejecutable.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  8. Abra un nuevo shell de Bash y ejecute el siguiente comando para comprobar que el servidor presenta el certificado TLS/SSL.

    curl --insecure https://<your VM public IP address>:8443/ssl-test
    
  9. Invoque la ruta de acceso exit para eliminar el servidor y cerrar los sockets de red.

    curl --insecure https://<your VM public IP address>:8443/exit
    

Ahora que ha visto las acciones load y present con un certificado TLS/SSL autofirmado, realizará algunos cambios triviales en la aplicación para ver también la acción accept.

Ejecución de una aplicación de Spring Boot con conexiones salientes seguras

En esta sección, modificará el código de la sección anterior para que el certificado TLS/SSL para las conexiones salientes provenga de Azure Key Vault. Por lo tanto, las acciones de load, present y accept se efectúan desde Azure Key Vault.

  1. Agregue la dependencia del cliente HTTP de Apache al archivo pom.xml:

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
       <version>4.5.13</version>
    </dependency>
    
  2. Incorporación de un nuevo punto de conexión de REST denominado ssl-test-outbound. Este punto de conexión abre un socket TLS a sí mismo y comprueba que la conexión TLS acepta el certificado TLS/SSL. Reemplace la parte anterior de la clase de inicio por el código siguiente.

    import java.security.KeyStore;
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import com.azure.security.keyvault.jca.KeyVaultLoadStoreParameter;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.ssl.SSLContexts;
    
    @SpringBootApplication
    @RestController
    public class SsltestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SsltestApplication.class, args);
        }
    
        @GetMapping(value = "/ssl-test")
        public String inbound(){
            return "Inbound TLS is working!!";
        }
    
        @GetMapping(value = "/ssl-test-outbound")
        public String outbound() throws Exception {
            KeyStore azureKeyVaultKeyStore = KeyStore.getInstance("AzureKeyVault");
            KeyVaultLoadStoreParameter parameter = new KeyVaultLoadStoreParameter(
                System.getProperty("azure.keyvault.uri"));
            azureKeyVaultKeyStore.load(parameter);
            SSLContext sslContext = SSLContexts.custom()
                                               .loadTrustMaterial(azureKeyVaultKeyStore, null)
                                               .build();
    
            HostnameVerifier allowAll = (String hostName, SSLSession session) -> true;
            SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, allowAll);
    
            CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(csf)
                .build();
    
            HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();
    
            requestFactory.setHttpClient(httpClient);
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            String sslTest = "https://localhost:8443/ssl-test";
    
            ResponseEntity<String> response
                = restTemplate.getForEntity(sslTest, String.class);
    
            return "Outbound TLS " +
                (response.getStatusCode() == HttpStatus.OK ? "is" : "is not")  + " Working!!";
        }
    
        @GetMapping(value = "/exit")
        public void exit() {
            System.exit(0);
        }
    
    }
    
  3. Ejecute los siguientes comandos para compilar el código y empaquetarlo en un archivo JAR ejecutable.

    mvn clean package
    
  4. Vuelva a cargar la aplicación utilizando de nuevo el mismo comando sftp mencionado anteriormente en este artículo.

    cd target
    sftp <your VM public IP address>
    put *.jar
    
  5. Ejecute la aplicación en la máquina virtual.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  6. Después de ejecutar el servidor, compruebe que el servidor acepta el certificado TLS/SSL. En el mismo shell de Bash donde emitió el comando curl anterior, ejecute el siguiente comando.

    curl --insecure https://<your VM public IP address>:8443/ssl-test-outbound
    

    Debería ver el mensaje Outbound TLS is working!!.

  7. Invoque la ruta de acceso exit para eliminar el servidor y cerrar los sockets de red.

    curl --insecure https://<your VM public IP address>:8443/exit
    

Ahora ha observado una ilustración sencilla de las acciones de load, present y accept con un certificado TLS/SSL autofirmado almacenado en Azure Key Vault.

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 para que los desarrolladores puedan centrarse en su código. Azure Spring Apps proporciona administración del ciclo de vida mediante supervisión y diagnósticos completos, administración de configuración, detección de servicios, integración de CI/CD, implementaciones azul-verde, etc. Para implementar la aplicación en Azure Spring Apps, consulte Implementación de la primera aplicación en Azure Spring Apps.

Pasos siguientes

Para más información sobre Spring y Azure, continúe con el Centro de documentación de Spring en Azure.