使用 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 订阅 - 免费创建订阅。
受支持的 Java 开发工具包 (JDK) 版本 11。
Apache Maven 3.0 或更高版本。
cURL 或类似的 HTTP 实用工具来测试功能。
Azure 虚拟机(VM)实例。 如果没有,请使用 az vm create 命令和 UbuntuServer 提供的 Ubuntu 映像创建启用了系统分配的托管标识的 VM 实例。 授予
Contributor
角色到系统分配的受管身份,然后将访问权限设置为scope
到您的订阅。Azure Key Vault 实例。 如果没有密钥保管库,请参阅 快速入门:使用 Azure 门户创建密钥保管库。
Spring Boot 应用程序。 如果没有,请使用 Spring Initializr创建 Maven 项目。 请务必选择 Maven 项目,在“依赖项”下,添加 Spring Web 依赖项,然后选择 Java 版本 8 或更高版本。
重要
完成本文中的步骤需要 Spring Boot 2.5 或更高版本。
设置自签名 TLS/SSL 证书
本教程中的步骤适用于直接存储在 Azure Key Vault 中的任何 TLS/SSL 证书(包括自签名证书)。 自签名证书不适合在生产环境中使用,但对于开发和测试应用程序非常有用。
本教程使用自签名证书。 若要设置证书,请参阅 快速入门:使用 Azure 门户设置和检索 Azure Key Vault 中的证书。
通过 TLS/SSL 证书保护连接
现在已有一个 VM 和一个 Key Vault 实例,并已授予 VM 对 Key Vault 的访问权限。 以下部分介绍如何在 Spring Boot 应用程序中通过 Azure Key Vault 中的 TLS/SSL 证书安全地连接。 本教程演示了以下两种方案:
- 运行具有安全入站连接的 Spring Boot 应用程序
- 运行具有安全出站连接的 Spring Boot 应用程序
提示
在以下步骤中,代码将打包到可执行文件中,并上传到 VM。 不要忘记在 VM 中安装 OpenJDK。
运行具有安全入站连接的 Spring Boot 应用程序
当入站连接的 TLS/SSL 证书来自 Azure Key Vault 时,请按照以下步骤配置应用程序:
将以下依赖项添加到 pom.xml 文件:
<dependency> <groupId>com.azure.spring</groupId> <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId> <version>3.14.0</version> </dependency>
在 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
的值 --name
参数的az keyvault certificate create
.server.ssl.key-store-type
必须是 AzureKeyVault
。server.ssl.trust-store-type
必须是 AzureKeyVault
。server.port
用于监听 HTTPS 连接的本地 TCP 端口。 azure.keyvault.uri
的 vaultUri
属性中的az keyvault create
. 在环境变量中保存了此值。密钥保管库的唯一特定属性是
azure.keyvault.uri
. 应用程序在具有系统分配的托管标识,并已被授予密钥库访问权限的虚拟机上运行。 因此,应用也被授予访问权限。这些更改使 Spring Boot 应用能够加载 TLS/SSL 证书。 在下一步中,你将使应用能够执行 接受 TLS/SSL 证书的 操作,如本教程开头所述。
编辑启动类文件,使其包含以下内容。
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)
。这段代码说明了 礼品 本教程开头提到的操作。 以下列表突出显示了有关此代码的一些详细信息:
- 现在有一个
@RestController
上的SsltestApplication
类由 Spring Initializr 生成。 - 有一个用
@GetMapping
注释的方法,其中value
用于你发出的 HTTP 调用。 - 当浏览器向
/ssl-test
路径发出 HTTPS 请求时,inbound
方法只会返回问候语。inbound
方法说明了服务器如何将 TLS/SSL 证书呈现给浏览器。 exit
方法导致 JVM 在调用时退出。 此方法便于在本教程的上下文中轻松运行示例。
- 现在有一个
运行以下命令以编译代码并将其打包到可执行的 JAR 文件中。
mvn clean package
验证在
<your-resource-group-name>
允许从您的 IP 地址通过端口 22 和 8443 输入流量。 若要了解如何配置网络安全组规则以允许入站流量,请参阅 创建、更改或删除网络安全组中的 使用安全规则 部分。将可执行文件放在 VM 上。
cd target sftp azureuser@<your VM public IP address> put *.jar
生成 Spring Boot 应用并将其上传到 VM 后,请使用以下步骤在 VM 上运行它,并使用
curl
调用 REST 终结点。使用 SSH 连接到 VM,然后运行可执行的 JAR。
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
打开新的 Bash shell 并执行以下命令以验证服务器是否提供 TLS/SSL 证书。
curl --insecure https://<your VM public IP address>:8443/ssl-test
调用
exit
路径来杀死服务器并关闭网络套接字。curl --insecure https://<your VM public IP address>:8443/exit
现在你已经看到了 负荷 和 礼品 使用自签名的 TLS/SSL 证书进行操作,对应用程序做一些微不足道的更改,以查看 接受 行动。
运行具有安全出站连接的 Spring Boot 应用程序
在本部分中,将修改上一部分中的代码,以便出站连接的 TLS/SSL 证书来自 Azure Key Vault。 因此,在 负荷, 礼品, 和 accept Azure 密钥库满足这些要求。
将 Apache HTTP 客户端依赖项添加到 pom.xml 文件:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
添加一个名为
ssl-test-outbound
. 此终结点向自身打开 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); } }
运行以下命令以编译代码并将其打包到可执行的 JAR 文件中。
mvn clean package
使用本文前面的相同
sftp
命令再次上传应用。cd target sftp <your VM public IP address> put *.jar
在 VM 上运行应用。
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
服务器运行后,请验证服务器是否接受 TLS/SSL 证书。 在发出上一
curl
命令的同一 Bash shell 中,运行以下命令。curl --insecure https://<your VM public IP address>:8443/ssl-test-outbound
应该看到消息
Outbound TLS is working!!
。调用
exit
路径来杀死服务器并关闭网络套接字。curl --insecure https://<your VM public IP address>:8443/exit
您现在已经看到了一个简单的示例 负荷, 礼品, 和 接受 使用存储在 Azure 密钥库中的自签名 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 文档中心。