Abilitare HTTPS in Spring Boot con i certificati di Azure Key Vault

Questa esercitazione illustra come proteggere le app Spring Boot (incluse le app Azure Spring Apps) con certificati TLS/SSL usando Azure Key Vault e le identità gestite per le risorse di Azure.

Le applicazioni Spring Boot di livello di produzione, sia nel cloud che in locale, richiedono la crittografia end-to-end per il traffico di rete usando protocolli TLS standard. La maggior parte dei certificati TLS/SSL individuati è individuabile da un'autorità di certificazione radice pubblica (CA). In alcuni casi, tuttavia, questa individuazione non è possibile. Quando i certificati non sono individuabili, l'app deve avere un modo per caricare tali certificati, presentarli alle connessioni di rete in ingresso e accettarli dalle connessioni di rete in uscita.

Le app Spring Boot in genere abilitano TLS installando i certificati. I certificati vengono installati nell'archivio chiavi locale della JVM che esegue l'app Spring Boot. Con Spring in Azure, i certificati non vengono installati in locale. L'integrazione spring per Microsoft Azure offre invece un modo sicuro e senza problemi per abilitare TLS con l'aiuto di Azure Key Vault e l'identità gestita per le risorse di Azure.

Diagram showing interaction of elements in this tutorial.

Importante

Attualmente, Spring Cloud Azure Certificate Starter versione 4.x o successiva non supporta TLS/mTLS, configurano automaticamente solo il client del certificato di Key Vault. Pertanto, se si vuole usare TLS/mTLS, non è possibile eseguire la migrazione alla versione 4.x.

Prerequisiti

Importante

Spring Boot versione 2.5 o successiva è necessario per completare i passaggi descritti in questo articolo.

Impostare un certificato TLS/SSL autofirmato

I passaggi descritti in questa esercitazione si applicano a qualsiasi certificato TLS/SSL (incluso quello autofirmato) archiviato direttamente in Azure Key Vault. I certificati autofirmati non sono adatti per l'uso nell'ambiente di produzione, ma sono utili per le applicazioni di sviluppo e test.

Questa esercitazione usa un certificato autofirmato. Per impostare il certificato, vedere Avvio rapido: Impostare e recuperare un certificato da Azure Key Vault usando il portale di Azure.

Nota

Dopo aver impostato il certificato, concedere all'insieme di credenziali delle macchine virtuali l'accesso a Key Vault seguendo le istruzioni riportate in Assegnare un criterio di accesso di Key Vault.

Connessione sicura tramite certificato TLS/SSL

Ora si dispone di una macchina virtuale e di un'istanza di Key Vault e si è concesso l'accesso alla macchina virtuale a Key Vault. Le sezioni seguenti illustrano come connettersi in modo sicuro tramite certificati TLS/SSL da Azure Key Vault nell'applicazione Spring Boot. Questa esercitazione illustra i due scenari seguenti:

  • Eseguire un'applicazione Spring Boot con connessioni in ingresso sicure
  • Eseguire un'applicazione Spring Boot con connessioni in uscita sicure

Suggerimento

Nei passaggi seguenti il codice verrà inserito in un file eseguibile e caricato nella macchina virtuale. Non dimenticare di installare OpenJDK nella macchina virtuale.

Eseguire un'applicazione Spring Boot con connessioni in ingresso sicure

Quando il certificato TLS/SSL per la connessione in ingresso proviene da Azure Key Vault, configurare l'applicazione seguendo questa procedura:

  1. Aggiungere le dipendenze seguenti al file pom.xml :

    <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId>
       <version>3.14.0</version>
    </dependency>
    
  2. Configurare le credenziali di Key Vault nel file di configurazione 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>
    

    Questi valori consentono all'app Spring Boot di eseguire l'azione di caricamento per il certificato TLS/SSL, come indicato all'inizio dell'esercitazione. Nella tabella seguente vengono descritti i valori delle proprietà.

    Proprietà Descrizione
    server.ssl.key-alias Valore dell'argomento --name passato a az keyvault certificate create.
    server.ssl.key-store-type Deve essere AzureKeyVault.
    server.ssl.trust-store-type Deve essere AzureKeyVault.
    server.port Porta TCP locale su cui restare in ascolto delle connessioni HTTPS.
    azure.keyvault.uri Proprietà vaultUri nel codice JSON restituito da az keyvault create. Questo valore è stato salvato in una variabile di ambiente.

    L'unica proprietà specifica di Key Vault è azure.keyvault.uri. L'app è in esecuzione in una macchina virtuale la cui identità gestita assegnata dal sistema ha concesso l'accesso all'insieme di credenziali delle chiavi. Pertanto, all'app è stato concesso anche l'accesso.

    Queste modifiche consentono all'app Spring Boot di caricare il certificato TLS/SSL. Nel passaggio successivo si abiliterà l'app a eseguire l'azione di accettazione per il certificato TLS/SSL, come indicato all'inizio dell'esercitazione.

  3. Modificare il file della classe di avvio in modo che contenga il contenuto seguente.

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

    La chiamata System.exit(0) da all'interno di una chiamata REST GET non autenticata è solo a scopo dimostrativo. Non usare System.exit(0) in un'applicazione reale.

    Questo codice illustra l'azione corrente indicata all'inizio di questa esercitazione. L'elenco seguente evidenzia alcuni dettagli su questo codice:

    • È ora disponibile un'annotazione @RestController sulla SsltestApplication classe generata da Spring Initializr.
    • Esiste un metodo annotato con @GetMapping, con per value la chiamata HTTP eseguita.
    • Il inbound metodo restituisce semplicemente un messaggio di saluto quando un browser effettua una richiesta HTTPS al /ssl-test percorso. Il inbound metodo illustra come il server presenta il certificato TLS/SSL al browser.
    • Il exit metodo fa uscire la JVM quando viene richiamata. Questo metodo è utile per semplificare l'esecuzione dell'esempio nel contesto di questa esercitazione.
  4. Eseguire i comandi seguenti per compilare il codice e crearne il pacchetto in un file JAR eseguibile.

    mvn clean package
    
  5. Verificare che il gruppo di sicurezza di rete creato in <your-resource-group-name> consenta il traffico in ingresso sulle porte 22 e 8443 dall'indirizzo IP. Per informazioni sulla configurazione delle regole del gruppo di sicurezza di rete per consentire il traffico in ingresso, vedere la sezione Usare le regole di sicurezza di Creare, modificare o eliminare un gruppo di sicurezza di rete.

  6. Inserire il file JAR eseguibile nella macchina virtuale.

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

    Dopo aver compilato l'app Spring Boot e averla caricata nella macchina virtuale, seguire questa procedura per eseguirla nella macchina virtuale e chiamare l'endpoint REST con curl.

  7. Usare SSH per connettersi alla macchina virtuale, quindi eseguire il file JAR eseguibile.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  8. Aprire una nuova shell Bash ed eseguire il comando seguente per verificare che il server presenti il certificato TLS/SSL.

    curl --insecure https://<your VM public IP address>:8443/ssl-test
    
  9. Richiamare il exit percorso per terminare il server e chiudere i socket di rete.

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

Ora che sono state visualizzate le azioni di caricamento e presentazione con un certificato TLS/SSL autofirmato, apportare alcune modifiche semplici all'app per visualizzare anche l'azione di accettazione .

Eseguire un'applicazione Spring Boot con connessioni in uscita sicure

In questa sezione si modifica il codice nella sezione precedente in modo che il certificato TLS/SSL per le connessioni in uscita provenga da Azure Key Vault. Di conseguenza, il caricamento, la presenza e l'accettazione delle azioni vengono soddisfatte da Azure Key Vault.

  1. Aggiungere la dipendenza client APACHE HTTP al file pom.xml :

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
       <version>4.5.13</version>
    </dependency>
    
  2. Aggiungere un nuovo endpoint rest denominato ssl-test-outbound. Questo endpoint apre un socket TLS a se stesso e verifica che la connessione TLS accetti il certificato TLS/SSL. Sostituire la parte precedente della classe di avvio con il codice seguente.

    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. Eseguire i comandi seguenti per compilare il codice e crearne il pacchetto in un file JAR eseguibile.

    mvn clean package
    
  4. Caricare di nuovo l'app usando lo stesso sftp comando riportato in precedenza in questo articolo.

    cd target
    sftp <your VM public IP address>
    put *.jar
    
  5. Eseguire l'app nella macchina virtuale.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  6. Dopo l'esecuzione del server, verificare che il server accetti il certificato TLS/SSL. Nella stessa shell Bash in cui è stato eseguito il comando precedente curl , eseguire il comando seguente.

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

    Dovrebbe essere visualizzato il messaggio Outbound TLS is working!!.

  7. Richiamare il exit percorso per terminare il server e chiudere i socket di rete.

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

È stata ora osservata una semplice illustrazione del caricamento, della presentazione e dell'accettazione di azioni con un certificato TLS/SSL autofirmato archiviato in Azure Key Vault.

Distribuire in Azure Spring Apps

Ora che l'applicazione Spring Boot è in esecuzione in locale, è possibile spostarla nell'ambiente di produzione. Azure Spring Apps semplifica la distribuzione di applicazioni Spring Boot in Azure senza modifiche al codice. Il servizio gestisce l'infrastruttura delle applicazioni Spring per consentire agli sviluppatori di concentrarsi sul codice. Azure Spring Apps offre la gestione del ciclo di vita usando monitoraggio e diagnostica completi, gestione della configurazione, individuazione dei servizi, integrazione CI/CD, distribuzioni blu-verde e altro ancora. Per distribuire l'applicazione in Azure Spring Apps, vedere Distribuire la prima applicazione in Azure Spring Apps.

Passaggi successivi

Per altre informazioni su Spring e Azure, passare al centro di documentazione di Spring in Azure.