DailyJSX

How to securely connect to an AWS DocumentDb using SpringBoot

May 31, 2022 • ☕️ 2 min read

Related tags: AWSspringbootdocumentdb

Problem statement

If you are trying to connect to an AWS DocumentDB using a secure connection, In Java spring-boot there are two possible scenarios we can follow,

However, neither of the above would not work if you need to connect using TLS to a DocumentDB if it is executed in AWS Lambda. Lambda doesn’t expose this particular VM option to modify, even for the second approach it is complex to refer to a certificate in an S3 bucket (I couldn’t sort that out at the moment, please let me know if you have done the second approach)

Solution

Considering all the facts, my final solution was downloading .pem file and converting it to a certificate as well as keeping that as a Keystore. All of the above should be done using the Lambda code.

Please find the code below that can use as the MongoClientSettings config for your spring-boot application,

import com.mongodb.MongoClientSettings;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.autoconfigure.mongo.MongoPropertiesClientSettingsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

@Configuration
public class MongoSSLConfig {
    @Bean
    public MongoClientSettings mongoClientSettings(
            MongoProperties properties,
            Environment environment
    ) throws GeneralSecurityException, IOException {
        // Declare path of trust store and create file
        String trustStorePath = "/tmp/trust";
        // try creating above directory and path if you get error no such file

        // Create Truststore using Key store api
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

        keyStore.load(null);
        // Add Certificate to Key store
        CertificateFactory certF = CertificateFactory.getInstance("X.509");
        // URL can pass as an env variable
        Certificate cert = certF.generateCertificate(new URL("https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem").openStream());
        keyStore.setCertificateEntry("mongo-cert", cert);

        // Write Key Store
        try (FileOutputStream out = new FileOutputStream(trustStorePath)) {
            keyStore.store(out, "pass".toCharArray());
        }

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

        MongoClientSettings.Builder builder = MongoClientSettings.builder();
        builder.applyToSslSettings(b -> {
            b.enabled(true);
            b.context(sslContext);
        });
        new MongoPropertiesClientSettingsBuilderCustomizer(properties, environment).customize(builder);
        return builder.build();
    }
}