{"id":3370,"date":"2025-04-11T14:11:34","date_gmt":"2025-04-11T21:11:34","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=3370"},"modified":"2025-04-11T14:11:34","modified_gmt":"2025-04-11T21:11:34","slug":"introducing-spring-cloud-azure-starter-key-vault-jca-streamlined-tls-and-mtls-for-spring-boot","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/introducing-spring-cloud-azure-starter-key-vault-jca-streamlined-tls-and-mtls-for-spring-boot\/","title":{"rendered":"Introducing Spring Cloud Azure Starter Key Vault JCA: Streamlined TLS and mTLS for Spring Boot"},"content":{"rendered":"<p>We\u2019re excited to unveil <strong>Spring Cloud Azure Starter Key Vault Java Crypto Architecture (JCA)<\/strong>, a new addition to the Spring Cloud Azure family, arriving with version <strong>5.21.0<\/strong>. Designed for <strong>Spring Boot 3.1+<\/strong>, this starter applies the <strong>Spring SSL Bundles<\/strong> abstraction and the <strong>JCA Provider for Azure Key Vault<\/strong> to simplify secure communication in your Spring Boot applications. Whether you\u2019re enabling TLS for your server or setting up mutual TLS (mTLS) for client-server authentication, this starter integrates Azure Key Vault\u2019s certificate management with Spring\u2019s modern security framework.<\/p>\n<p>In this blog post, we dive into the starter\u2019s capabilities and demonstrate its usage with practical examples for enabling embedded server TLS, securing <code>RestTemplate<\/code>, securing <code>WebClient<\/code>, and configuring mTLS communication. Let\u2019s get started!<\/p>\n<h2>What is Spring Cloud Azure Starter Key Vault JCA?<\/h2>\n<p>The Spring Cloud Azure Starter Key Vault JCA combines the power of Spring Boot\u2019s SSL Bundles (introduced in Spring Boot 3.1) with Azure Key Vault\u2019s JCA provider. This integration allows developers to use certificates stored in Key Vault directly within Spring applications, eliminating the complexity of traditional keystore management seen in older configurations. For example, <a href=\"https:\/\/learn.microsoft.com\/azure\/developer\/java\/spring-framework\/configure-spring-boot-starter-java-app-with-azure-key-vault-certificates\">Securing Spring Boot applications based on older version<\/a>. For a deeper dive into Spring SSL Bundles, see <a href=\"https:\/\/docs.spring.io\/spring-boot\/reference\/features\/ssl.html\">Spring SSL Bundles<\/a>.<\/p>\n<h2>Get started<\/h2>\n<p>Add the following dependency to your <code>pom.xml<\/code> file:<\/p>\n<pre><code class=\"language-xml\">&lt;dependency&gt;\r\n    &lt;groupId&gt;com.azure.spring&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-cloud-azure-starter-keyvault-jca&lt;\/artifactId&gt;\r\n    &lt;version&gt;5.21.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/code><\/pre>\n<p>Complete the following steps to prepare the Azure resources:<\/p>\n<ol>\n<li>Create two self-signed certificates in two Key Vault resources by following the steps at <a href=\"https:\/\/learn.microsoft.com\/azure\/key-vault\/certificates\/quick-create-portal#add-a-certificate-to-key-vault\">Add a self-signed certificate to Key Vault<\/a>. The certificate names are <code>server<\/code> and <code>client<\/code>, respectively. Assume that <code>keyvault1<\/code> stores the <code>server<\/code> certificate and <code>keyvault2<\/code> stores the <code>client<\/code> certificate.<\/li>\n<li>Create a Service Principal for accessing Key Vault by following the steps at <a href=\"https:\/\/learn.microsoft.com\/entra\/identity-platform\/howto-create-service-principal-portal\">Create a Service Principal<\/a>.<\/li>\n<li>Grant role <code>Key Vault Certificate User<\/code> to the Service Principal for each Key Vault instance by following the steps at <a href=\"https:\/\/learn.microsoft.com\/azure\/key-vault\/general\/rbac-guide\">Role assignment<\/a>.<\/li>\n<\/ol>\n<blockquote><p>Note:\nEnvironment variables prefixed with <code>KEY_VAULT_SSL_BUNDLES<\/code> represent the connection information for your Key Vault instances and Service Principal.<\/p><\/blockquote>\n<h2>Enable embedded server TLS<\/h2>\n<p>Secure inbound HTTP calls for the embedded server. The embedded server applies the Key Vault SSL Bundle to enable Server TLS and that applies to all web servers supported by Spring Boot.<\/p>\n<p>Update your <code>application.yml<\/code> file:<\/p>\n<pre><code class=\"language-yaml\">spring:\r\n  application:\r\n    name: ssl-bundles-server\r\n  ssl:\r\n    bundle:\r\n      keyvault:\r\n        tlsServerBundle:\r\n          key:\r\n            alias: server\r\n          keystore:\r\n            keyvault-ref: keyvault1\r\n  cloud:\r\n    azure:\r\n      keyvault:\r\n        jca:\r\n          vaults:\r\n            keyvault1:\r\n              endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}\r\n              profile:\r\n                tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}\r\n              credential:\r\n                client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}\r\n                client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}\r\nserver:\r\n  ssl:\r\n    bundle: tlsServerBundle<\/code><\/pre>\n<h2>Secure RestTemplate<\/h2>\n<p>Secure outbound HTTP calls with <code>RestTemplate<\/code> using a Key Vault SSL Bundle.<\/p>\n<ol>\n<li>Update your <code>application.yml<\/code> file:\n<pre><code class=\"language-yaml\">spring:\r\nssl:\r\n  bundle:\r\n    keyvault:\r\n      tlsClientBundle:\r\n        truststore:\r\n          keyvault-ref: keyvault1\r\ncloud:\r\n  azure:\r\n    keyvault:\r\n      jca:\r\n        vaults:\r\n          keyvault1:\r\n            endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}\r\n            profile:\r\n              tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}\r\n            credential:\r\n              client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}\r\n              client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}<\/code><\/pre>\n<\/li>\n<li>Update your <code>RestTemplate<\/code> configuration to set the Key Vault SSL Bundle:\n<pre><code class=\"language-java\">@Bean\r\nRestTemplate restTemplateWithTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {\r\n  return restTemplateBuilder.sslBundle(sslBundles.getBundle(\"tlsClientBundle\")).build();\r\n}<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>Then you can use bean <code>restTemplateWithTLS<\/code> to access the HTTPS resource owned by app <code>ssl-bundles-server<\/code>.<\/p>\n<h2>Secure WebClient<\/h2>\n<p>Secure outbound HTTP calls with <code>WebClient<\/code> using a Key Vault SSL Bundle.<\/p>\n<ol>\n<li>Update your <code>application.yml<\/code> file according to the configuration of the <code>Secure RestTemplate<\/code> scenario.<\/li>\n<li>Update your <code>WebClient<\/code> bean configuration to apply the Key Vault SSL Bundle:\n<pre><code class=\"language-java\">@Bean\r\nWebClient webClientWithTLS(WebClientSsl ssl) {\r\n  return WebClient.builder().apply(ssl.fromBundle(\"tlsClientBundle\")).build();\r\n}<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>Then you can use bean <code>webClientWithTLS<\/code> to access the HTTPS resource owned by app <code>ssl-bundles-server<\/code>.<\/p>\n<h2>Enable mTLS communication<\/h2>\n<p>Set up mTLS for two-way authentication between client and server.<\/p>\n<h3>Server side<\/h3>\n<p>Update your <code>application.yml<\/code> file to trust the client certificates in Key Vault <code>keyvault2<\/code>, and enable the client authentication:<\/p>\n<pre><code class=\"language-yaml\">spring:\r\n  application:\r\n    name: ssl-bundles-server\r\n  ssl:\r\n    bundle:\r\n      keyvault:\r\n        tlsServerBundle:\r\n          key:\r\n            alias: server\r\n          keystore:\r\n            keyvault-ref: keyvault1\r\n          truststore:\r\n            keyvault-ref: keyvault2\r\n  cloud:\r\n    azure:\r\n      keyvault:\r\n        jca:\r\n          vaults:\r\n            keyvault1:\r\n              endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}\r\n              profile:\r\n                tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}\r\n              credential:\r\n                client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}\r\n                client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}\r\n            keyvault2:\r\n              endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_02}\r\n              profile:\r\n                tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}\r\n              credential:\r\n                client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}\r\n                client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}\r\nserver:\r\n  ssl:\r\n    bundle: tlsServerBundle\r\n    client-auth: NEED<\/code><\/pre>\n<h3>Client side<\/h3>\n<p>Complete the following steps:<\/p>\n<ol>\n<li>Update your <code>application.yml<\/code> file to provide keystore for client authentication in Key Vault <code>keyvault2<\/code>:\n<pre><code class=\"language-yaml\">spring:\r\nssl:\r\n  bundle:\r\n    keyvault:\r\n      mtlsClientBundle:\r\n        key:\r\n          alias: client\r\n        for-client-auth: true\r\n        keystore:\r\n          keyvault-ref: keyvault2\r\n        truststore:\r\n          keyvault-ref: keyvault1\r\ncloud:\r\n  azure:\r\n    keyvault:\r\n      jca:\r\n        vaults:\r\n          keyvault1:\r\n            endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}\r\n            profile:\r\n              tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}\r\n            credential:\r\n              client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}\r\n              client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}\r\n          keyvault2:\r\n            endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_02}\r\n            profile:\r\n              tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}\r\n            credential:\r\n              client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}\r\n              client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}<\/code><\/pre>\n<\/li>\n<li>Register another <code>RestTemplate<\/code> bean for mTLS connection, and the same if you use <code>WebClient<\/code>:\n<pre><code class=\"language-java\">@Bean\r\nRestTemplate restTemplateWithMTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {\r\n  return restTemplateBuilder.sslBundle(sslBundles.getBundle(\"mtlsClientBundle\")).build();\r\n}\r\n\r\n\/\/ or you can use WebClient instead\r\n@Bean\r\nWebClient webClientWithMTLS(WebClientSsl ssl) {\r\n  return WebClient.builder().apply(ssl.fromBundle(\"mtlsClientBundle\")).build();\r\n}<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>Now you can use beans <code>restTemplateWithMTLS<\/code> or <code>webClientWithMTLS<\/code> to access the HTTPS resource owned by app <code>ssl-bundles-server<\/code>.<\/p>\n<h2>Feedback<\/h2>\n<p>Your feedback and contributions are always welcome on <a href=\"https:\/\/stackoverflow.com\/questions\/tagged\/spring-cloud-azure\">StackOverflow<\/a> or <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/issues?q=is%3Aissue+is%3Aopen+label%3Aazure-spring\">GitHub<\/a>.<\/p>\n<h2>Resources<\/h2>\n<p>To learn more about Spring Cloud Azure, visit the following links:<\/p>\n<ul>\n<li><a href=\"https:\/\/learn.microsoft.com\/azure\/developer\/java\/spring-framework\/configure-spring-boot-starter-java-app-with-azure-key-vault-certificates\">Enable HTTPS in Spring Boot application (Legacy)<\/a>.<\/li>\n<li><a href=\"https:\/\/techcommunity.microsoft.com\/blog\/appsonazureblog\/seamlessly-integrating-azure-keyvault-with-jarsigner-for-enhanced-security\/4125770\">Sign and verify jar files<\/a>.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/azure\/developer\/java\/fundamentals\/java-azure-keyvault-ssl-integration-jvm\">Use Azure Key Vault to deliver TLS\/SSL certificates to the Java Virtual Machine<\/a>.<\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/azure\/developer\/java\/fundamentals\/java-azure-keyvault-tomcat-integration?tabs=windows\">Use Azure Key Vault to deliver TLS\/SSL certificates to Apache Tomcat<\/a>.<\/li>\n<li><a href=\"https:\/\/aka.ms\/spring\/docs\">Reference Documentation<\/a><\/li>\n<li><a href=\"https:\/\/aka.ms\/spring\/msdocs\">Conceptual Documentation<\/a><\/li>\n<li><a href=\"https:\/\/aka.ms\/spring\/samples\">Code Samples<\/a><\/li>\n<li><a href=\"https:\/\/aka.ms\/spring\/versions\">Spring Version Mapping<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/blob\/main\/sdk\/spring\/CHANGELOG.md\">CHANGELOGs of Spring Cloud Azure<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This blog post shows the Spring Cloud Azure Starter Key Vault Java Crypto Architecture (JCA).<\/p>\n","protected":false},"author":109450,"featured_media":3371,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[160,871,872],"class_list":["post-3370","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-java","tag-spring","tag-spring-cloud-azure"],"acf":[],"blog_post_summary":"<p>This blog post shows the Spring Cloud Azure Starter Key Vault Java Crypto Architecture (JCA).<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/3370","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/users\/109450"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=3370"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/3370\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/3371"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=3370"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=3370"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=3370"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}