Home > Enterprise >  Custom RestTemplate with CA and client certificates without importing crts to jvm keystore
Custom RestTemplate with CA and client certificates without importing crts to jvm keystore

Time:08-12

I have a Spring Boot app with a custom RestTemplate which loads client cert from file (from resource folder).

How can I now also add CA certificate (PEM file) to this RestTemplate as well from file? (or any other way to achieve the goal with spring boot?)

@Bean public RestTemplate restTemplate() ... {

  SSLContext sslContext = new SSLContextBuilder()
          .loadTrustMaterial(new URL(clientCert), str.toCharArray()).build();
  SSLConnectionSocketFactory sslConFactory = new SSLConnectionSocketFactory(sslContext);
  CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConFactory).build();
  ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
  return new RestTemplate(requestFactory);
}

CodePudding user response:

Some time ago I came across some code that could be of help in your use case.

It is available at Github under MIT license at this repository.

The important artifacts are defined in this package.

Basically, the library proposes a helper class named SSLContextFactory.

This class defines a method for creating a SSLContext with a client certificate, its password, and the corresponding CA certificate, the last one from a cert file, named makeContext, copied here for convenience:

public SSLContext makeContext(File clientCertFile, String clientCertPassword, String caCertString) throws Exception {
  final KeyStore keyStore = loadPKCS12KeyStore(clientCertFile, clientCertPassword);
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
  kmf.init(keyStore, clientCertPassword.toCharArray());
  KeyManager[] keyManagers = kmf.getKeyManagers();


  final KeyStore trustStore = loadPEMTrustStore(caCertString);
  TrustManager[] trustManagers = {new CustomTrustManager(trustStore)};


  SSLContext sslContext = SSLContext.getInstance("TLS");
  sslContext.init(keyManagers, trustManagers, null);


  return sslContext;
}

As you can see, it uses different helpers methods and the helper class CustomTrustManager.

Please, be aware that the solution is quite dated but I think it is still suitable.

Then, use the the makeContext method when constructing your RestTemplate:

@Bean public RestTemplate restTemplate() {
    SSLContextFactory sslContextFactory = SSLContextFactory.getInstance();
    SSLContext sslContext = sslContextFactory.makeContext(clientCert, str.toCharArray(), caCertPem);
    SSLConnectionSocketFactory sslConFactory = new SSLConnectionSocketFactory(sslContext);
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConFactory).build();
    ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
    return new RestTemplate(requestFactory);
}
  • Related