共用方式為


使用 Azure Key Vault 憑證在 Spring Boot 中啟用 HTTPS

本教學課程說明如何使用 Azure Key Vault 和 Azure 資源的受控識別,使用 TLS/SSL 憑證來保護 Spring Boot(包括 Azure Spring Apps)應用程式。

生產等級的 Spring Boot 應用程式,無論是在雲端還是內部部署,都需要使用標準 TLS 通訊協定進行網路流量的端對端加密。 您遇到的大部分 TLS/SSL 憑證都可以從公用根憑證授權機構(CA)尋找到。 不過,有時候無法進行此探索。 當憑證無法被發現時,應用程式必須有某種方式來讀取這些憑證,並將它們呈現給入站網路連線,並從出站網路連線接受憑證。

Spring Boot 應用程式通常會藉由安裝憑證來啟用 TLS。 憑證會安裝到執行 Spring Boot 應用程式的 JVM 本機密鑰存放區。 在 Azure 上使用 Spring 時,憑證不會安裝在本機。 相反地,Microsoft Azure 的 Spring 整合提供了安全且無摩擦的方式,可透過 Azure Key Vault 和 Azure 資源的受控識別來啟用 TLS。

此教學課程中顯示元素互動的圖表。

重要

目前,Spring Cloud Azure 憑證入門 4.x 版或更新版本不支援 TLS/mTLS,它們只會自動設定 Key Vault 憑證用戶端。 因此,如果您想要使用 TLS/mTLS,則無法移轉至 4.x 版。

先決條件

  • Azure 訂用帳戶 - 建立一個免費的訂用帳戶

  • 第 11 版支援的 Java 開發工具套件 (JDK)

  • Apache Maven 3.0 版或更高版本。

  • Azure CLI

  • cURL 或類似的 HTTP 公用程式來測試功能。

  • Azure 虛擬機 (VM) 實例。 如果您沒有虛擬機器,請使用 az vm create 命令及 UbuntuServer 提供的 Ubuntu 映像,建立已啟用系統指派的受控身分識別的 VM 實例。 將 Contributor 角色授與系統指派的受控識別,然後將存取 scope 設定為您的訂用帳戶。

  • Azure Key Vault 實例。 如果您沒有金鑰儲存庫,請參閱 快速入門:使用 Azure 入口網站建立金鑰保存庫

  • Spring Boot 應用程式。 如果您還沒有 Maven 專案,請使用 Spring Initializr來建立一個 Maven 專案。 請務必選取 Maven 專案,然後在 [相依性] 底下,新增 Spring Web 相依性,然後選取 [Java 第 8 版] 或更新版本。

重要

需要 Spring Boot 2.5 版或更高版本,才能完成本文中的步驟。

設定自我簽署 TLS/SSL 憑證

本教學課程中的步驟適用於直接儲存在 Azure Key Vault 中的任何 TLS/SSL 憑證(包括自我簽署)。 自我簽署憑證不適用於生產環境,但對開發和測試應用程式很有用。

本教學課程使用自我簽署憑證。 若要設定憑證,請參閱 快速入門:使用 Azure 入口網站從 Azure Key Vault 設定及擷取憑證

注意

設定憑證之後,請依照 中的指示來將密鑰保存庫的存取原則指派給,以授予虛擬機器 (VM) 訪問 Key Vault 的權限。

透過 TLS/SSL 憑證保護連線

您現在有 VM 和金鑰保存庫的實例,並已授予該 VM 對金鑰保存庫的存取權限。 下列各節說明如何在 Spring Boot 應用程式中透過來自 Azure Key Vault 的 TLS/SSL 憑證安全地連線。 本教學課程示範下列兩個案例:

  • 執行具有安全輸入連線的 Spring Boot 應用程式
  • 執行具有安全輸出連線的 Spring Boot 應用程式

提示

在下列步驟中,程式代碼會封裝成可執行檔,並上傳至 VM。 別忘了在 VM 中安裝 OpenJDK

執行具有安全輸入連線的 Spring Boot 應用程式

當輸入連線的 TLS/SSL 憑證來自 Azure Key Vault 時,請遵循下列步驟來設定應用程式:

  1. 將下列相依性新增至 pom.xml 檔案:

    <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId>
       <version>3.14.0</version>
    </dependency>
    
  2. application.properties 組態檔中設定 Key Vault 認證。

    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>
    

    這些值可讓 Spring Boot 應用程式執行 TLS/SSL 憑證的 載入 動作,如教學課程開頭所述。 下表描述屬性值。

    財產 描述
    server.ssl.key-alias 您傳遞給 --nameaz keyvault certificate create 參數的值。
    server.ssl.key-store-type 必須是 AzureKeyVault
    server.ssl.trust-store-type 必須是 AzureKeyVault
    server.port 要接聽 HTTPS 連線的本機 TCP 連接埠。
    azure.keyvault.uri vaultUri傳回的 JSON 中的 az keyvault create 屬性。 您已將此值儲存在環境變數中。

    Key Vault 特有的唯一屬性是 azure.keyvault.uri。 應用程式正在一個虛擬機器上執行,而該虛擬機器的系統指派身分已獲授予金鑰保存庫的存取權。 因此,應用程式也已獲得存取權。

    這些變更可讓 Spring Boot 應用程式載入 TLS/SSL 憑證。 在下一個步驟中,您將讓應用程式執行 接受 TLS/SSL 憑證的 動作,如教學課程開頭所述。

  3. 編輯啟動類別檔案,使其具有下列內容。

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

    在未經驗證的 REST GET 呼叫中調用 System.exit(0) 僅供示範之用。 請勿在實際應用程式中使用 System.exit(0)

    此程式代碼說明本教學課程開頭所述的 動作。 下列清單會醒目提示此程式碼的一些詳細資料:

    • 現在,Spring Initializr 生成的 @RestController 類別上有 SsltestApplication 註解。
    • 有一個以 @GetMapping標註的方法,並附有您進行的 HTTP 呼叫的相關描述 value
    • 當瀏覽器向 inbound 路徑提出 HTTPS 要求時,/ssl-test 方法只會傳回問候語。 inbound 方法說明伺服器如何將 TLS/SSL 憑證呈現給瀏覽器。
    • exit 方法會導致 JVM 在叫用時結束。 此方法旨在提高便利性,使範例能在本教學內容中輕鬆執行。
  4. 執行下列命令來編譯程序代碼,並將其封裝成可執行的 JAR 檔案。

    mvn clean package
    
  5. 確認在 <your-resource-group-name> 中建立的網路安全組允許來自您的IP位址的端口 22 和 8443 的輸入流量。 若要瞭解如何設定網路安全組規則以允許輸入流量,請參閱 建立、變更或刪除網路安全組內的 使用安全性規則 一節。

  6. 將可執行檔 JAR 檔案放在 VM 上。

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

    既然您已建置 Spring Boot 應用程式並將其上傳至 VM,請使用下列步驟在 VM 上執行,並使用 curl呼叫 REST 端點。

  7. 使用 SSH 連線到 VM,然後執行可執行的 JAR。

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  8. 開啟新的 Bash 殼層,然後執行下列命令來確認伺服器是否顯示 TLS/SSL 憑證。

    curl --insecure https://<your VM public IP address>:8443/ssl-test
    
  9. 叫用 exit 路徑來終止伺服器並關閉網路插孔。

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

既然您已看到 載入,並 使用自我簽署的 TLS/SSL 憑證呈現 動作,請對應用程式進行一些微不足道的變更,以查看 接受 動作。

執行具有安全輸出連線的 Spring Boot 應用程式

在本節中,您會修改上一節中的程式代碼,讓輸出連線的 TLS/SSL 憑證來自 Azure Key Vault。 因此,Azure Key Vault 會滿足 載入呈現,以及 接受 的動作。

  1. 將 Apache HTTP 用戶端相依性新增至您的 pom.xml 檔案:

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
       <version>4.5.13</version>
    </dependency>
    
  2. 新增名為 ssl-test-outbound的新 rest 端點。 此端點會自行開啟 TLS 套接字,並驗證 TLS 連線是否接受 TLS/SSL 憑證。 以下列程式代碼取代啟動類別的上一個部分。

    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. 執行下列命令來編譯程序代碼,並將其封裝成可執行的 JAR 檔案。

    mvn clean package
    
  4. 使用本文稍早的相同 sftp 命令,再次上傳應用程式。

    cd target
    sftp <your VM public IP address>
    put *.jar
    
  5. 在 VM 上執行應用程式。

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  6. 執行伺服器之後,請確認伺服器接受 TLS/SSL 憑證。 在發出上一個 curl 命令的同一個 Bash 殼層中,執行下列命令。

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

    您應該看到訊息 Outbound TLS is working!!

  7. 叫用 exit 路徑來終止伺服器並關閉網路插孔。

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

您現在已觀察到 載入的簡單圖例,呈現,且 接受儲存在 Azure Key Vault 中自我簽署 TLS/SSL 憑證的 動作。

部署至 Azure Spring Apps

現在您已在本機執行 Spring Boot 應用程式,現在可以將其移至生產環境。 Azure Spring Apps 可讓您輕鬆地將 Spring Boot 應用程式部署至 Azure,而不需要變更任何程式代碼。 服務會管理 Spring 應用程式的基礎結構,讓開發人員能夠專注於其程式代碼。 Azure Spring Apps 使用完整的監視和診斷、組態管理、服務探索、CI/CD 整合、藍綠部署等,提供生命週期管理。 若要將應用程式部署至 Azure Spring Apps,請參閱 將第一個應用程式部署至 Azure Spring Apps

後續步驟

若要深入瞭解 Spring 和 Azure,請繼續前往 Azure 上的 Spring 檔中心。