Skip to content

MLE-30239 Use secure trust store#1945

Open
rjdew-progress wants to merge 1 commit into
developfrom
MLE-30239
Open

MLE-30239 Use secure trust store#1945
rjdew-progress wants to merge 1 commit into
developfrom
MLE-30239

Conversation

@rjdew-progress

Copy link
Copy Markdown

Replace trust-all TrustManager in SSL cookbook example with a trust-store-based approach

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the MarkLogic Java Client SSL examples/tests to avoid “trust-all” trust managers and instead rely on certificate validation via a configured truststore (or the JVM default trust managers where applicable).

Changes:

  • Replaces a trust-all TrustManager in the SSL cookbook example with a truststore-backed TrustManagerFactory approach and switches to STRICT hostname verification.
  • Updates functional test SSLContext creation to use a truststore (classpath resource) when configured, falling back to JVM default trust managers otherwise.
  • Adds/updates properties and a new test asserting handshake failure when the server CA is not trusted.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
marklogic-client-api/src/test/java/com/marklogic/client/test/ssl/OneWaySSLTest.java Adds a test validating TLS handshake fails when using default JVM trust managers that don’t trust the test CA.
marklogic-client-api-functionaltests/src/test/resources/test.properties Documents optional truststore properties for SSL-enabled functional test runs.
marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/functionaltest/ConnectedRESTQA.java Replaces trust-all trust manager with truststore/JVM-default trust managers for SSLContext initialization.
examples/src/main/resources/Example.properties Documents truststore configuration for the SSL cookbook example.
examples/src/main/java/com/marklogic/client/example/cookbook/Util.java Adds truststore fields to example configuration parsing.
examples/src/main/java/com/marklogic/client/example/cookbook/SSLClientCreator.java Loads truststore and uses a real trust manager + STRICT hostname verification for the SSL example.

*/
public class SSLClientCreator {
public static void main(String[] args) throws IOException, KeyManagementException, NoSuchAlgorithmException {
public static void main(String[] args) throws IOException, KeyManagementException, NoSuchAlgorithmException,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should instead use the support in DatabaseClientFactory to configure trusted SSL via properties so that the user doesn't have to deal with all this boilerplate. Check out the public static DatabaseClient newClient(Function<String, Object> propertySource) { method. It handles all of this plumbing.

// When ml_truststore_file is configured, a TrustManagerFactory is initialised
// from that truststore (which must contain the MarkLogic server's CA certificate).
// Otherwise the JVM's default trust managers are used as a safe fallback.
final TrustManager[] trustManagers;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here - try reworking this to use the support in DatabaseClientFactory for doing all of this for the user.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

jonmille
jonmille previously approved these changes Jun 23, 2026
// server certificate
// CN/SANs are checked against the connected host.
try (DatabaseClient client = DatabaseClientFactory.newClient(propertyName -> switch (propertyName) {
case "marklogic.client.host" -> props.host;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but I would just update the example properties file to use these "marklogic.client." properties instead so that no translation is needed.

@rjdew-progress

Copy link
Copy Markdown
Author

I've verified that the TLS is being tested end to end.

Screenshot 2026-06-25 at 10 49 41 AM Screenshot 2026-06-25 at 10 45 46 AM

@RitaChen609

RitaChen609 commented Jun 26, 2026

Copy link
Copy Markdown

Got one failed test

OneWaySSLTest > tLS12ClientWithTLS13ServerShouldFail() FAILED
org.opentest4j.AssertionFailedError: expected: <Error occurred while calling https://localhost:8012/v1/ping; javax.net.ssl.SSLHandshakeException: Received fatal alert: protocol_version ; possible reasons for the error include that a MarkLogic app server may not be listening on the port, or MarkLogic was stopped or restarted during the request; check the MarkLogic server logs for more information.> but was: <Error occurred while calling https://localhost:8012/v1/ping; javax.net.ssl.SSLHandshakeException: (protocol_version) Received fatal alert: protocol_version ; possible reasons for the error include that a MarkLogic app server may not be listening on the port, or MarkLogic was stopped or restarted during the request; check the MarkLogic server logs for more information.>

Copilot root cause analysis: newer JDKs prefix the SSLHandshakeException message with the alert type in parentheses — (protocol_version) Received fatal alert: protocol_version — while older JDKs emit just Received fatal alert: protocol_version. The hardcoded assertEquals against the old format fails on your JDK 17+

@RitaChen609

RitaChen609 commented Jun 26, 2026

Copy link
Copy Markdown

Got an error when I enabled the trust store (still keep restSSLset=false) and created a self-signed java-client-api\marklogic-client-api-functionaltests\src\test\resources\truststore.jks

ml_truststore_file=/truststore.jks
ml_truststore_password=xxx

./gradlew :marklogic-client-api-functionaltests:test --tests "com.marklogic.client.fastfunctest.TestDatabaseClientConnection.testDatabaseClientGetters"

TestDatabaseClientConnection > testDatabaseClientGetters() FAILED
java.io.IOException: Truststore resource not found on classpath: /truststore.jks. Ensure the file exists under the test resources directory.

Copilot suggested to fix ConnectedRESTQA.java Line 811:
InputStream tsInput = ConnectedRESTQA.class.getResourceAsStream(ml_truststore_file);

@rjdew-progress

Copy link
Copy Markdown
Author

@RitaChen609 I updated ConnectedRESTQA.java Line 811

I wasn't able to reproduce the other failure for OneWaySSLTest > tLS12ClientWithTLS13ServerShouldFail() FAILED. The test doesn't check the wording of the message. It only checks if the cause is an instance of SSLHandshakeException.

		assertTrue(ex.getCause() instanceof SSLHandshakeException,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants