April 11th, 2025

Introducing Spring Cloud Azure Starter Key Vault JCA: Streamlined TLS and mTLS for Spring Boot

Moary Chen
Software Engineer

We’re excited to unveil Spring Cloud Azure Starter Key Vault Java Crypto Architecture (JCA), a new addition to the Spring Cloud Azure family, arriving with version 5.21.0. Designed for Spring Boot 3.1+, this starter applies the Spring SSL Bundles abstraction and the JCA Provider for Azure Key Vault to simplify secure communication in your Spring Boot applications. Whether you’re enabling TLS for your server or setting up mutual TLS (mTLS) for client-server authentication, this starter integrates Azure Key Vault’s certificate management with Spring’s modern security framework.

In this blog post, we dive into the starter’s capabilities and demonstrate its usage with practical examples for enabling embedded server TLS, securing RestTemplate, securing WebClient, and configuring mTLS communication. Let’s get started!

What is Spring Cloud Azure Starter Key Vault JCA?

The Spring Cloud Azure Starter Key Vault JCA combines the power of Spring Boot’s SSL Bundles (introduced in Spring Boot 3.1) with Azure Key Vault’s 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, Securing Spring Boot applications based on older version. For a deeper dive into Spring SSL Bundles, see Spring SSL Bundles.

Get started

Add the following dependency to your pom.xml file:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-keyvault-jca</artifactId>
    <version>5.21.0</version>
</dependency>

Complete the following steps to prepare the Azure resources:

  1. Create two self-signed certificates in two Key Vault resources by following the steps at Add a self-signed certificate to Key Vault. The certificate names are server and client, respectively. Assume that keyvault1 stores the server certificate and keyvault2 stores the client certificate.
  2. Create a Service Principal for accessing Key Vault by following the steps at Create a Service Principal.
  3. Grant role Key Vault Certificate User to the Service Principal for each Key Vault instance by following the steps at Role assignment.

Note: Environment variables prefixed with KEY_VAULT_SSL_BUNDLES represent the connection information for your Key Vault instances and Service Principal.

Enable embedded server TLS

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.

Update your application.yml file:

spring:
  application:
    name: ssl-bundles-server
  ssl:
    bundle:
      keyvault:
        tlsServerBundle:
          key:
            alias: server
          keystore:
            keyvault-ref: keyvault1
  cloud:
    azure:
      keyvault:
        jca:
          vaults:
            keyvault1:
              endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
              profile:
                tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}
              credential:
                client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}
                client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}
server:
  ssl:
    bundle: tlsServerBundle

Secure RestTemplate

Secure outbound HTTP calls with RestTemplate using a Key Vault SSL Bundle.

  1. Update your application.yml file:
    spring:
    ssl:
      bundle:
        keyvault:
          tlsClientBundle:
            truststore:
              keyvault-ref: keyvault1
    cloud:
      azure:
        keyvault:
          jca:
            vaults:
              keyvault1:
                endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
                profile:
                  tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}
                credential:
                  client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}
                  client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}
  2. Update your RestTemplate configuration to set the Key Vault SSL Bundle:
    @Bean
    RestTemplate restTemplateWithTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
      return restTemplateBuilder.sslBundle(sslBundles.getBundle("tlsClientBundle")).build();
    }

Then you can use bean restTemplateWithTLS to access the HTTPS resource owned by app ssl-bundles-server.

Secure WebClient

Secure outbound HTTP calls with WebClient using a Key Vault SSL Bundle.

  1. Update your application.yml file according to the configuration of the Secure RestTemplate scenario.
  2. Update your WebClient bean configuration to apply the Key Vault SSL Bundle:
    @Bean
    WebClient webClientWithTLS(WebClientSsl ssl) {
      return WebClient.builder().apply(ssl.fromBundle("tlsClientBundle")).build();
    }

Then you can use bean webClientWithTLS to access the HTTPS resource owned by app ssl-bundles-server.

Enable mTLS communication

Set up mTLS for two-way authentication between client and server.

Server side

Update your application.yml file to trust the client certificates in Key Vault keyvault2, and enable the client authentication:

spring:
  application:
    name: ssl-bundles-server
  ssl:
    bundle:
      keyvault:
        tlsServerBundle:
          key:
            alias: server
          keystore:
            keyvault-ref: keyvault1
          truststore:
            keyvault-ref: keyvault2
  cloud:
    azure:
      keyvault:
        jca:
          vaults:
            keyvault1:
              endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
              profile:
                tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}
              credential:
                client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}
                client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}
            keyvault2:
              endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_02}
              profile:
                tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}
              credential:
                client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}
                client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}
server:
  ssl:
    bundle: tlsServerBundle
    client-auth: NEED

Client side

Complete the following steps:

  1. Update your application.yml file to provide keystore for client authentication in Key Vault keyvault2:
    spring:
    ssl:
      bundle:
        keyvault:
          mtlsClientBundle:
            key:
              alias: client
            for-client-auth: true
            keystore:
              keyvault-ref: keyvault2
            truststore:
              keyvault-ref: keyvault1
    cloud:
      azure:
        keyvault:
          jca:
            vaults:
              keyvault1:
                endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_01}
                profile:
                  tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}
                credential:
                  client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}
                  client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}
              keyvault2:
                endpoint: ${KEY_VAULT_SSL_BUNDLES_KEYVAULT_URI_02}
                profile:
                  tenant-id: ${KEY_VAULT_SSL_BUNDLES_TENANT_ID}
                credential:
                  client-id: ${KEY_VAULT_SSL_BUNDLES_CLIENT_ID}
                  client-secret: ${KEY_VAULT_SSL_BUNDLES_CLIENT_SECRET}
  2. Register another RestTemplate bean for mTLS connection, and the same if you use WebClient:
    @Bean
    RestTemplate restTemplateWithMTLS(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
      return restTemplateBuilder.sslBundle(sslBundles.getBundle("mtlsClientBundle")).build();
    }
    
    // or you can use WebClient instead
    @Bean
    WebClient webClientWithMTLS(WebClientSsl ssl) {
      return WebClient.builder().apply(ssl.fromBundle("mtlsClientBundle")).build();
    }

Now you can use beans restTemplateWithMTLS or webClientWithMTLS to access the HTTPS resource owned by app ssl-bundles-server.

Feedback

Your feedback and contributions are always welcome on StackOverflow or GitHub.

Resources

To learn more about Spring Cloud Azure, visit the following links:

Author

Moary Chen
Software Engineer

0 comments

'; block.insertAdjacentElement('beforebegin', codeheader); let button = codeheader.querySelector('.copy-button'); button.addEventListener("click", async () => { let blockToCopy = block; await copyCode(blockToCopy, button); }); } }); async function copyCode(blockToCopy, button) { let code = blockToCopy.querySelector("code"); let text = ''; if (code) { text = code.innerText; } else { text = blockToCopy.innerText; } try { await navigator.clipboard.writeText(text); } catch (err) { console.error('Failed to copy:', err); } button.innerText = "Copied"; setTimeout(() => { button.innerHTML = '' + svgCodeIcon + ' Copy'; }, 1400); }