Skip to content
Advertisement

Spring boot / Java, mongodb SSL / TLS connectivity

I have two projects where I use spring boot + mongodb. In one project the spring boot version is 1.4.1.RELEASE and other project is 2.1.3.RELEASE. I have certificate(s), key in PEM format to onboard into truststore and keystore – One server certificate chain and other a client certificate and private key. I programmatically load the certificates into truststore and keystore.

I have configured a certificate path in yml file, where in it would consist of a client and server folder, where client and server certs or key would be stored respectively. From there below is the code which I use to programmatically load the certs into the truststore and keystore.

final KeyStore trustStore = loadTrustStore(...); // Gets and loads server certificates
final TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
final TrustManager[] trustManagers = tmf.getTrustManagers();

final KeyStore keyStore = loadKeyStore(...); // Gets and loads client certs and key
final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, password.toCharArray());
keyManagers = kmf.getKeyManagers();

sslContext.init(keyManagers, trustManagers, null);

The above code is working fine for mongodb or even http client certificates in spring boot versions 2.1.3.RELEASE and in other tools such as mongodb clients (studio3t or mongo compass for example), but in 1.4.1.RELEASE unfortunately the above code is resulting in

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)

Now there is a difference in the API I found both in later and older versions. In older version of mongodb lib, the MongoClientOptions.Builder takes only socketFactory as its parameter, but in later version it takes SSLContext as parameters. Both code fragments below.

spring-boot-starter-data-mongodb – 1.4.1.RELEASE

final MongoClientOptions.Builder builder = MongoClientOptions.builder(config.getOptions());
final SSLContext sslContext = certificateUtil.buildSslContext(...);
builder.socketFactory(sslContext.getSocketFactory());

spring-boot-starter-data-mongodb – 2.3.1.RELEASE

final MongoClientOptions.Builder builder = MongoClientOptions.builder(config.getOptions());
final SSLContext sslContext = certificateUtil.buildSslContext(...);
builder.sslContext(sslContext);

I tried to user MongoUri option with older version was unsuccessful, because could not find a document to connect to mongodb using URI and SSL certificates (Since older version, could not use TLS params as in new mongodb specs).

Any pointers towards above is highly appreciated, SSLContext way or also can turn to MongoUri if required.

Advertisement

Answer

For anyone if they get into this issue, for now, I figured out one solution by upgrading the mongo driver version to 3.5, where they have added support for SSL/TLS configuration through SSL context. Through this I am able to connect to the database with certificates. I will be doing extensive test of the application though because the version is different than one which was default – 3.2

Reference https://mongodb.github.io/mongo-java-driver/3.5/driver/tutorials/ssl/

POM changes

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
   <groupId>org.mongodb</groupId>
   <artifactId>mongodb-driver</artifactId>
   <version>3.5.0</version>
</dependency>

Use the mongo options config using following after loading required certificates and keys for clients and server in the truststore and keystore.

final MongoClientOptions.Builder builder = MongoClientOptions.builder(config.getOptions());
final SSLContext sslContext = certificateUtil.buildSslContext(...);
builder.sslContext(sslContext);
4 People found this is helpful
Advertisement