Condividi tramite


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 che incontri è 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.

Diagramma che mostra l'interazione degli elementi in questa esercitazione.

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

  • Una sottoscrizione di Azure: crearne una gratuitamente.

  • Un JDK (Java Development Kit) supportato con la versione 11.

  • Apache Maven versione 3.0 o successiva.

  • Azure CLI.

  • cURL o un'utilità HTTP simile per testare la funzionalità.

  • Istanza di macchina virtuale di Azure. Se non ne avete una, utilizzare il comando az vm create e l'immagine Ubuntu fornita da UbuntuServer per creare un'istanza di macchina virtuale con un'identità gestita con assegnazione di sistema abilitata. Concedere il ruolo Contributor all'identità gestita assegnata dal sistema e quindi impostare il scope di accesso alla sottoscrizione.

  • Istanza di Azure Key Vault. Se non ne hai uno, vedere Avvio rapido: Creare un vault delle chiavi usando il portale di Azure.

  • Applicazione Spring Boot. Se non ne hai uno, crea un progetto Maven con il Spring Initializr. Assicurarsi di selezionare il progetto Maven e, in Dipendenze, aggiungere la dipendenza Spring Web, quindi selezionare Java versione 8 o successiva.

Importante

Spring Boot versione 2.5 o successiva sono necessari 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 alla macchina virtuale l'accesso a Key Vault seguendo le istruzioni riportate in Impostare un criterio di accesso di Key Vault.

Connessione sicura tramite certificato TLS/SSL

Ora disponi di una macchina virtuale e di un'istanza di Key Vault e hai concesso l'accesso alla macchina virtuale al 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

Consiglio

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 ascoltare le 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 su una macchina virtuale la cui identità gestita assegnata dal sistema ha ricevuto l'accesso al Key Vault. Pertanto all'app è stato concesso anche l'accesso.

    Queste modifiche consentono all'app Spring Boot di caricare il certificato TLS/SSL. Nel passaggio successivo, abiliterai l'app a eseguire l'azione di accettare per il certificato TLS/SSL, come menzionato 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 di System.exit(0) dall'interno di una chiamata REST GET non autenticata è solo a scopo dimostrativo. Non usare System.exit(0) in un'applicazione reale.

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

    • È ora disponibile un'annotazione @RestController nella classe SsltestApplication generata da Spring Initializr.
    • Esiste un metodo annotato con @GetMapping, con un value per la chiamata HTTP eseguita.
    • Il metodo inbound restituisce semplicemente un messaggio di saluto quando un browser effettua una richiesta HTTPS al percorso /ssl-test. Il metodo inbound illustra come il server presenta il certificato TLS/SSL al browser.
    • Il metodo exit 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 traffico in ingresso sulle porte 22 e 8443 dal tuo 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 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 percorso exit per arrestare il server e chiudere i socket di rete.

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

Dopo aver visto il di caricamento e presentare azioni con un certificato TLS/SSL autofirmato, apportare alcune modifiche semplici all'app per visualizzare anche l'azione accettare.

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, le azioni di carico , presenza e accettazione sono soddisfatte da Azure Key Vault.

  1. Aggiungere la dipendenza del 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 comando sftp 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 curl precedente, eseguire il comando seguente.

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

    Verrà visualizzato il messaggio Outbound TLS is working!!.

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

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

Hai ora osservato una semplice illustrazione delle azioni di caricamento , presentaree accettare con un certificato TLS/SSL autofirmato archiviato in Azure Key Vault.

Distribuire su 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 in modo che gli sviluppatori possano 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 documentazione di Spring in Azure.