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.
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: creare un account gratuitamente.
Java Development Kit (JDK) supportato con la versione 11.
Apache Maven versione 3.0 o successiva.
cURL o un'utilità HTTP simile per testare la funzionalità.
Istanza di macchina virtuale di Azure. Se non è disponibile, usare il comando az vm create e l'immagine Ubuntu fornita da UbuntuServer per creare un'istanza di macchina virtuale con un'identità gestita assegnata dal sistema abilitata. Concedere il
Contributor
ruolo all'identità gestita assegnata dal sistema e quindi impostare l'accessoscope
alla sottoscrizione.Istanza di Azure Key Vault. Se non è disponibile, vedere Avvio rapido: Creare un insieme di credenziali delle chiavi usando il portale di Azure.
Applicazione Spring Boot. Se non è disponibile, creare un progetto Maven con Spring Initializr. Assicurarsi di selezionare 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 è 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:
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>
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 aaz 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 daaz 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.
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 usareSystem.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
sullaSsltestApplication
classe generata da Spring Initializr. - Esiste un metodo annotato con
@GetMapping
, con pervalue
la chiamata HTTP eseguita. - Il
inbound
metodo restituisce semplicemente un messaggio di saluto quando un browser effettua una richiesta HTTPS al/ssl-test
percorso. Ilinbound
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.
- È ora disponibile un'annotazione
Eseguire i comandi seguenti per compilare il codice e crearne il pacchetto in un file JAR eseguibile.
mvn clean package
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.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
.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"
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
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.
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>
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); } }
Eseguire i comandi seguenti per compilare il codice e crearne il pacchetto in un file JAR eseguibile.
mvn clean package
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
Eseguire l'app nella macchina virtuale.
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
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!!
.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.