Присоединение AWS documentDB к приложению Spring Boot
Недавно я пытался использовать новый сервис AWS DocumentDB в качестве базы данных в приложении Spring.
Кластер был создан в том же VPC, что и EKS, на котором я развернул свое приложение. Группы безопасности разрешают соединения между всеми узлами в VPC.
AWS предоставляет такой моно URI для моего кластера БД:
mongodb://<my-user>:<insertYourPassword>@<my-cluster-endpoint>:27017/?ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs0
Мой вопрос:
Как мне заставить мой код Spring работать с этим типом соединения?
Я попытался добавить подписку к моему application.properties
файл:
spring.data.mongodb.uri=mongodb://<my-user>:<insertYourPassword>@<my-cluster-endpoint>:27017/admin?ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs00
spring.data.mongodb.database=admin
server.ssl.key-store=classpath:rds-combined-ca-bundle.pem
И поместив файл PEM в /src/main/resources
Однако код все еще не может подключиться к кластеру БД.
Я получаю это сообщение как ошибку: No server chosen by com.mongodb.client.internal.MongoClientDelegate
Вслед за Exception in monitor thread while connecting to server ...
И, наконец, исключение тайм-аута: com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
Это похоже на проблему группы безопасности, но у меня нет проблем с подключением к оболочке mongo из того же EC2, на котором запущен модуль Spring.
Есть идеи?
7 ответов
Как указано в документации,
По своей сути вы получаете доступ к ресурсам Amazon DocumentDB (с совместимостью с MongoDB) из экземпляра Amazon EC2 в том же Amazon VPC, что и ресурсы Amazon DocumentDB. Однако предположим, что ваш вариант использования требует, чтобы вы или ваше приложение обращались к ресурсам Amazon DocumentDB из-за пределов кластера Amazon VPC. В этом случае вы можете использовать SSH-туннелирование (также известное как "переадресация портов") для доступа к вашим ресурсам Amazon DocumentDB.
Ваш кластер Amazon DocumentDB должен работать в виртуальном частном облаке по умолчанию (VPC). Для взаимодействия с кластером Amazon DocumentDB необходимо запустить экземпляр Amazon Elastic Compute Cloud (Amazon EC2) в свой VPC по умолчанию, в том же регионе AWS, где вы создали кластер Amazon DocumentDB.
Следуйте инструкциям по подключению к кластеру AWS DocumentDB cluster
Обновление:
Чтобы подключиться через SSL, используйте следующую логику, установив SSL_CERTIFICATE, указывающий на промежуточный сертификат, специфичный для региона aws.
Это можно скачать из сертификатов SSL и скопировать его в базовый каталог. В качестве альтернативы вы можете указать абсолютный путь к переменной SSL_CERTIFICATE.
private static final String SSL_CERTIFICATE = "rds-ca-2015-us-east-1.pem";
private static final String KEY_STORE_TYPE = "JKS";
private static final String KEY_STORE_PROVIDER = "SUN";
private static final String KEY_STORE_FILE_PREFIX = "sys-connect-via-ssl-test-cacerts";
private static final String KEY_STORE_FILE_SUFFIX = ".jks";
private static final String DEFAULT_KEY_STORE_PASSWORD = "changeit";
public static void main(String[] args) {
SSLContextHelper.setSslProperties();
SpringApplication.run(Application.class, args);
}
protected static class SSLContextHelper{
/**
* This method sets the SSL properties which specify the key store file, its type and password:
* @throws Exception
*/
private static void setSslProperties() {
try {
System.setProperty("javax.net.ssl.trustStore", createKeyStoreFile());
} catch (Exception e) {
e.printStackTrace();
}
System.setProperty("javax.net.ssl.trustStoreType", KEY_STORE_TYPE);
System.setProperty("javax.net.ssl.trustStorePassword", DEFAULT_KEY_STORE_PASSWORD);
}
private static String createKeyStoreFile() throws Exception {
return createKeyStoreFile(createCertificate()).getPath();
}
/**
* This method generates the SSL certificate
* @return
* @throws Exception
*/
private static X509Certificate createCertificate() throws Exception {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
URL url = new File(SSL_CERTIFICATE).toURI().toURL();
if (url == null) {
throw new Exception();
}
try (InputStream certInputStream = url.openStream()) {
return (X509Certificate) certFactory.generateCertificate(certInputStream);
}
}
/**
* This method creates the Key Store File
* @param rootX509Certificate - the SSL certificate to be stored in the KeyStore
* @return
* @throws Exception
*/
private static File createKeyStoreFile(X509Certificate rootX509Certificate) throws Exception {
File keyStoreFile = File.createTempFile(KEY_STORE_FILE_PREFIX, KEY_STORE_FILE_SUFFIX);
try (FileOutputStream fos = new FileOutputStream(keyStoreFile.getPath())) {
KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE, KEY_STORE_PROVIDER);
ks.load(null);
ks.setCertificateEntry("rootCaCertificate", rootX509Certificate);
ks.store(fos, DEFAULT_KEY_STORE_PASSWORD.toCharArray());
}
return keyStoreFile;
}
}
выход подключения:
019-01-17 13:33:22.316 INFO 3598 --- [onaws.com:27017] org.mongodb.driver.cluster : Canonical address mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017 does not match server address. Removing mongodb.cluster-cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017 from client view of cluster
2019-01-17 13:33:22.401 INFO 3598 --- [onaws.com:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:2}] to mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017
2019-01-17 13:33:22.403 INFO 3598 --- [onaws.com:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017, type=REPLICA_SET_PRIMARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 6, 0]}, minWireVersion=0, maxWireVersion=6, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=null, roundTripTimeNanos=2132149, setName='rs0', canonicalAddress=mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017, hosts=[mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017], passives=[], arbiters=[], primary='mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017', tagSet=TagSet{[]}, electionId=7fffffff0000000000000001, setVersion=null, lastWriteDate=Thu Jan 17 13:33:21 UTC 2019, lastUpdateTimeNanos=516261208876}
2019-01-17 13:33:22.406 INFO 3598 --- [onaws.com:27017] org.mongodb.driver.cluster : Discovered replica set primary mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017
2019-01-17 13:33:22.595 INFO 3598 --- [ main] com.barath.app.CustomerService : Saving the customer with customer details com.barath.app.Customer@6c130c45
2019-01-17 13:33:22.912 INFO 3598 --- [ main] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3}] to mongodb.cktoiipu3bbd.us-east-1.docdb.amazonaws.com:27017
2019-01-17 13:33:23.936 INFO 3598 --- [ main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)]
Ссылка: aws-documentdb
Ответ, предоставленный Sunny Pelletier сработал для меня с гибридом Frank в нашей настройке Java.
Поэтому мне нужно было решение, которое работало бы для нашей локальной настройки докеров и для любой из наших сред AWS, в которых есть активные профили и другие переменные окружения, установленные в нашей среде через CDK.
Сначала я начал с простого POJO конфигурации, чтобы настроить свои свойства за пределами
spring.data.mongo.*
парадигма. Вам не обязательно этого делать, и вы можете просто позволить Spring обработать это, как обычно, для создания.
Мой локальный разработчик по умолчанию
application.yml
и соответствующий класс конфигурации.
mongo:
user: mongo
password: mongo
host: localhost
port: 27017
database: my-service
@Data
@Configuration
@ConfigurationProperties(prefix = "mongo")
public class MongoConnectConfig {
private int port;
private String host;
private String user;
private String database;
private String password;
}
Затем я создал два
AbstractMongoClientConfiguration
детские классы; один для местного и один для неместного. Ключевым моментом здесь является то, что я не создавал свой собственный. Причина в том, что мне нужны все хорошие вещи для инициализации Spring Boot, которые вы получаете с фреймворком. Например, авторегистрация всех конвертеров и тому подобное.
Вместо этого я использовал крючок настройки, предоставляемый
AbstractMongoClientConfiguration.configureClientSettings(MongoClientSettings.Builder builder)
чтобы затем объединить пользовательские настройки, такие как
.pem
кусок.
Другая часть заключается в том, что я использовал профили для включения / отключения конфигураций, чтобы сделать их «бесшовными» для местных разработчиков; мы не используем никаких профилей кроме
default
для локальной разработки, так что проще приступить к настройке, не «зная» так много с самого начала.
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
@Slf4j
@Configuration
@RequiredArgsConstructor
@Profile({"!dev && !qa && !prod"})
@EnableMongoRepositories(basePackages = "co.my.data.repositories")
public class LocalDevMongoConfig extends AbstractMongoClientConfiguration {
private final MongoConnectConfig config;
@Override
public String getDatabaseName() {
return config.getDatabase();
}
@Override
protected void configureClientSettings(MongoClientSettings.Builder builder) {
log.info("Applying Local Dev MongoDB Configuration");
builder.applyConnectionString(new ConnectionString(getConnectionString()));
}
//mongodb://${mongo.user}:${mongo.password}@${mongo.host}:${mongo.port}/${mongo.database}?authSource=admin
private String getConnectionString() {
return String.format("mongodb://%s:%s@%s:%s/%s?authSource=admin",
config.getUser(),
config.getPassword(),
config.getHost(),
config.getPort(),
config.getDatabase()
);
}
}
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.file.Files;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.stream.Collectors;
@Slf4j
@Configuration
@RequiredArgsConstructor
@Profile({"dev || qa || prod"})
@EnableMongoRepositories(basePackages = "co.my.data.repositories")
public class DocumentDbMongoConfig extends AbstractMongoClientConfiguration {
private final MongoConnectConfig config;
@Override
public String getDatabaseName() {
return config.getDatabase();
}
@SneakyThrows
@Override
protected void configureClientSettings(MongoClientSettings.Builder builder) {
log.info("Applying AWS DocumentDB Configuration");
builder.applyConnectionString(new ConnectionString(getConnectionString()));
var endOfCertificateDelimiter = "-----END CERTIFICATE-----";
File resource = new ClassPathResource("certs/rds-combined-ca-bundle.pem").getFile();
String pemContents = new String(Files.readAllBytes(resource.toPath()));
var allCertificates = Arrays.stream(pemContents
.split(endOfCertificateDelimiter))
.filter(line -> !line.isBlank())
.map(line -> line + endOfCertificateDelimiter)
.collect(Collectors.toUnmodifiableList());
var certificateFactory = CertificateFactory.getInstance("X.509");
var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
// This allows us to use an in-memory key-store
keyStore.load(null);
for (int i = 0; i < allCertificates.size(); i++) {
var certString = allCertificates.get(i);
var caCert = certificateFactory.generateCertificate(new ByteArrayInputStream(certString.getBytes()));
keyStore.setCertificateEntry(String.format("AWS-certificate-%s", i), caCert);
}
var trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
var sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
builder.applyToSslSettings(ssl -> {
ssl.enabled(true).context(sslContext);
});
}
/**
* Partly based on the AWS Console "Connectivity & security " section in the DocumentDB Cluster View.
* Since we register the pem above, we don't need to add the ssl & sslCAFile piece
* mongodb://${user}:${password}@${host}:${port}/?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
*/
private String getConnectionString() {
return String.format("mongodb://%s:%s@%s:%s/%s?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false",
config.getUser(),
config.getPassword(),
config.getHost(),
config.getPort(),
config.getDatabase()
);
}
}
Наконец, мы размещаем
rds-combined-ca-bundle.pem
в
src/main/resources/certs/
папка.
Боковые примечания:
- Опять же, я считаю, что вы сможете обойтись без использования значения по умолчанию
spring.data*
свойства и вашMongoClient
должен был их использовать. - Игнорировать
@SneakyThrows
здесь я сделал это только для краткости кода, обрабатывайте отмеченные исключения так, как считаете нужным. - Думаю, мы можем понять, почему синтаксис Kotlin можно считать «чище», да? :)
Я могу подтвердить, что решение, предоставленное @Barath, позволяет защитить TLS-соединение AWS DocumentDB внутри самого приложения Java. Это намного более чистый подход по сравнению с подходом, описанным AWS на https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html, который требует, чтобы вы запускали сценарий на своем сервере, который является более сложным и сложно для автоматического развертывания и т. д.
Для дальнейшей настройки самого соединения в приложении Spring я использовал следующий класс @Configuration, который позволяет подключаться к локальной MongoDB для тестирования во время разработки, и один AWS, развернутый с настройками из файла свойств.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
@Configuration
@EnableMongoRepositories(basePackages = "YOUR.PACKAGE.WITH.repository")
public class MongoDbConfig extends AbstractMongoClientConfiguration {
@Value("${spring.profiles.active}")
private String activeProfile;
@Value("${mongodb.host:localhost}")
private String dbUri;
@Value("${mongodb.port:27017}")
private int dbPort;
@Value("${mongodb.database.name:YOUR_DOCUMENTDB_NAME}")
private String dbName;
@Value("${mongodb.username:}")
private String dbUser;
@Value("${mongodb.password:}")
private String dbPassword;
@Override
public String getDatabaseName() {
return dbName;
}
@Override
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString(getConnectionString());
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
private String getConnectionString() {
if (activeProfile.contains("local")) {
return String.format("mongodb://%s:%s/%s", dbUri, dbPort, dbName);
}
return String.format("mongodb://%s:%s@%s:%s/%s?ssl=true&replicaSet=rs0&readpreference=secondaryPreferred&retrywrites=false",
dbUser, dbPassword, dbUri, dbPort, dbName);
}
}
На самом деле я столкнулся с той же проблемой, что и вы, но теперь AWS использует, который объединяет множество сертификатов в один.
Если вы не хотите создавать трастовое хранилище, используя их устаревшую документацию, вы можете сделать это самостоятельно и получить
rds-combined-ca-bundle.pem
в ваше приложение, генерирующее хранилище ключей во время выполнения.
Мне удалось заставить это работать с этим образцом кода. Это было протестировано с
spring:2.4
,
mongo-driver: 4.1.1
и documentDB, используя
mongo 4.0
совместимость.
val endOfCertificateDelimiter = "-----END CERTIFICATE-----"
// rds-combined-ca-bundle.pem contains more than one certificate. We need to add them all to the trust-store independantly.
val allCertificates = ClassPathResource("certificates/rds-combined-ca-bundle.pem").file.readText()
.split(endOfCertificateDelimiter)
.filter { it.isNotBlank() }
.map { it + endOfCertificateDelimiter }
val certificateFactory = CertificateFactory.getInstance("X.509")
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null) // This allows us to use an in-memory key-store
allCertificates.forEachIndexed { index, certificate ->
val caCert = certificateFactory.generateCertificate(certificate.byteInputStream()) as X509Certificate
keyStore.setCertificateEntry("AWS-certificate-$index", caCert)
}
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStore)
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustManagerFactory.trustManagers, null)
builder.applyToSslSettings {
it.enabled(true)
.context(sslContext)
}
Как отметил @mmr25 в комментариях к ответу @Barath, решение работает только в том случае, когда сервису нужно только подключиться к documentDB. Вы начинаете получать «Сбой при построении пути PKIX: sun.security.provider.certpath.SunCertPathBuilderException: невозможно найти действительный путь сертификации для запрошенного» для других HTTP-запросов.
Чтобы решить эту проблему, нам нужно включить sslcontext только для соединений documentdb. Для этого мы можем использовать Netty в качестве HttpClient для соединений mongodb. Чтобы включить netty, нам нужно добавить следующую зависимость maven в ваш проект весенней загрузки:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.53.Final</version>
</dependency>
и поместите файл pem в папку ресурсов и определите следующие bean-компоненты в одном из классов, аннотированных аннотациями @Configutation.
@Slf4j
@Configuration
public class MongoDbConfiguration {
private static final String AWS_PUBLIC_KEY_NAME = "rds-ca-2019-root.pem";
private final String mongoConnectionUri;
private final String databaseName;
public MongoDbConfiguration(@Value("${spring.data.mongodb.uri}") String mongoConnectionUri, @Value("${spring.data.mongodb.database}") String databaseName) {
this.mongoConnectionUri = mongoConnectionUri;
this.databaseName = databaseName;
}
@Bean
@Primary
@SneakyThrows
@Profile("!default")
public MongoClient mongoClient() {
SslContext sslContext = SslContextBuilder.forClient()
.sslProvider(SslProvider.OPENSSL)
.trustManager(new ClassPathResource(AWS_PUBLIC_KEY_NAME).getInputStream())
.build();
ConnectionString connectionString = new ConnectionString(mongoConnectionUri);
return MongoClients.create(
MongoClientSettings.builder()
.applyConnectionString(connectionString)
.applyToSslSettings(builder -> {
builder.enabled((null == connectionString.getSslEnabled()) ? false : connectionString.getSslEnabled());
builder.invalidHostNameAllowed((null == connectionString.getSslInvalidHostnameAllowed()) ? false : connectionString.getSslInvalidHostnameAllowed());
})
.streamFactoryFactory(NettyStreamFactoryFactory.builder()
.sslContext(sslContext)
.build())
.build());
}
}
Заявления об импорте:
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.connection.netty.NettyStreamFactoryFactory;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.MongoTransactionManager;
Теперь вы сможете подключиться к своей базе данных документов, и другие http-соединения также должны работать должным образом.
Вот решение, которое сработало для меня, просто вызовите метод setSslProperties перед подключением к своей базе данных документа.
/**
* This method sets the SSL properties which specify the key store file, its type and password.
*
* @throws Exception
*/
private static void setSslProperties() throws Exception {
System.setProperty("javax.net.ssl.trustStore", createKeyStoreFile());
System.setProperty("javax.net.ssl.trustStoreType", KEY_STORE_TYPE);
System.setProperty("javax.net.ssl.trustStorePassword", DEFAULT_KEY_STORE_PASSWORD);
}
/**
* This method returns the path of the Key Store File needed for the SSL verification during the IAM Database Authentication to
* the db instance.
*
* @return
* @throws Exception
*/
private static String createKeyStoreFile() throws Exception {
return createKeyStoreFile(createCertificate()).getPath();
}
/**
* This method generates the SSL certificate.
*
* @return
* @throws Exception
*/
private static X509Certificate createCertificate() throws Exception {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
final ClassLoader classLoader = MyClass.class.getClassLoader();
final InputStream is = classLoader.getResourceAsStream(SSL_CERTIFICATE);
return (X509Certificate) certFactory.generateCertificate(is);
}
/**
* This method creates the Key Store File.
*
* @param rootX509Certificate - the SSL certificate to be stored in the KeyStore
* @return
* @throws Exception
*/
private static File createKeyStoreFile(final X509Certificate rootX509Certificate) throws Exception {
final File keyStoreFile = File.createTempFile(KEY_STORE_FILE_PREFIX, KEY_STORE_FILE_SUFFIX);
try (final FileOutputStream fos = new FileOutputStream(keyStoreFile.getPath())) {
final KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE, KEY_STORE_PROVIDER);
ks.load(null);
ks.setCertificateEntry("rootCaCertificate", rootX509Certificate);
ks.store(fos, DEFAULT_KEY_STORE_PASSWORD.toCharArray());
}
return keyStoreFile;
}
Вот константы.
public static final String SSL_CERTIFICATE = "rds-ca-2019-root.pem";
public static final String KEY_STORE_TYPE = "JKS";
public static final String KEY_STORE_PROVIDER = "SUN";
public static final String KEY_STORE_FILE_PREFIX = "sys-connect-via-ssl-test-cacerts";
public static final String KEY_STORE_FILE_SUFFIX = ".jks";
public static final String DEFAULT_KEY_STORE_PASSWORD = "changeit";
Вот ссылка на файл rds-ca-2019-root.pem, помещающий этот файл в папку ресурсов.
дайте мне знать, что это работает для вас.
Вот образец
setSslProperties();
final MongoCredential credential = MongoCredential.createCredential(userName, mongoProps.getDatabaseName(), password.toCharArray());
final MongoClientSettings settings = MongoClientSettings.builder()
.credential(credential)
.readPreference(ReadPreference.secondaryPreferred())
.retryWrites(false)
.applyToSslSettings(builder -> builder.enabled(true))
.applyToConnectionPoolSettings(connPoolBuilder ->
ConnectionPoolSettings.builder().
maxSize(1).build())
.applyToClusterSettings(builder ->
builder.hosts(Arrays.asList(new ServerAddress(clusterEndPoint, 27017))))
.build();
mongoClient = MongoClients.create(settings);
Простое решение - вы можете удалить опцию TLS (SSL) в AWS, а затем удалить "ssl_ca_certs=rds-comdated-ca-bundle.pem" из строки подключения. Но если приложению требуется подключение к базе данных SSL, вы можете использовать Руководство AWS.