I am facing problems connecting with my DocumentDB cluster with plain Java over TLS/SSL
The procedure I followed as per the AWS docs is this:
I downloaded the .pem
file from AWS and copied in the root of my java project, from where I executed:
keytool -importcert -trustcacerts -file rds-combined-ca-bundle.pem -alias certAlias -keystore rds-ca-certs -storepass keyStorePassword
This has created the rds-ca-certs
at the root of my project which now looks like this:
And, the java code in Main.java is:
package com.example.documentdb;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.ServerAddress;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
public final class Main {
private Main() {
}
public static void main(String[] args) {
String template = "mongodb://%s:%s@%s/test?ssl=true&replicaSet=rs0&readpreference=%s";
String username = "myUsernameInCluster";
String password = "myPasswordInCluster";
String clusterEndpoint = "mycluster.node.us-east-1.docdb.amazonaws.com:27017";
String readPreference = "secondaryPreferred";
String connectionString = String.format(template, username, password, clusterEndpoint, readPreference);
String keystore = "rds-ca-certs";
String keystorePassword = "keyStorePassword";
System.setProperty("javax.net.ssl.trustStore", keystore);
System.setProperty("javax.net.ssl.trustStorePassword", keystorePassword);
MongoClientURI clientURI = new MongoClientURI(connectionString);
MongoClient mongoClient = new MongoClient(clientURI);
MongoDatabase testDB = mongoClient.getDatabase("test");
MongoCollection<Document> numbersCollection = testDB.getCollection("numbers");
Document doc = new Document("name", "pi").append("value", 3.14159);
numbersCollection.insertOne(doc);
MongoCursor<Document> cursor = numbersCollection.find().iterator();
try {
while (cursor.hasNext()) {
System.out.println(cursor.next().toJson());
}
} finally {
cursor.close();
}
}
}
It gives me this ugly error:
com.mongodb.MongoSocketWriteException: Exception sending message
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Interestingly, when I use the mongo CLI to connect over SSL/TLS, like this:
mongo --ssl --host mycluster.node.eu-central-1.docdb.amazonaws.com:27017 --sslCAFile rds-combined-ca-bundle.pem --username myUsernameInCluster --password myPasswordInCluster
It works perfectly, so I have discarded a networking issue and I think the problem is in the Java code itself or in the keytool
command executed.
Additionally, with TLS disabled in the cluster this java code provided by AWS (that only differs in the keystore configuration) works.
PD: I know there are a bunch of other questions regarding SSL/TLS connection with AWS DocumentDB, but none of them address my issue specifically. Moreover, I have also checked plain mongodb TLS/SSL connection questions and the process differ so they are not valid for me.
The issue seems to be related to the process of importing the certificates within the bundle, under the same alias.
So I have had to stop using the bundled option (rds-combined-ca-bundle.pem) and start using this one rds-ca-2019-root.pem
After importing the keystore using the following command:
keytool -importcert -trustcacerts -file rds-ca-2019-root.pem -alias rds19 -keystore rds-ca-certs -storepass keyStorePassword
Connectivity with the database under TLS was achieved.
You can add the AWS provided certificate to the java's trust store then java will trust requests to AWS service by default.
You will have to find your java cacerts file. Depending on your OS and java version it should be in ..lib/security/cacerts
.
I am using OSX and it was in/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts
Then you cause keytool to import it the default java keystore password is change it:
keytool -import -trustcacerts -keystore /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts -storepass changeit -noprompt -alias aws-rds -file rds-combined-ca-bundle.pem
To check if the certificate was imported you can use:keytool -list -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre/lib/security/cacerts | grep aws
Post back if that worked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With