Skip to content

Commit 86d70f7

Browse files
committed
MLE-16818 Defaulting protocol to "TLS"
Learned that this will allow Java to use the highest TLS protocol supported by the server.
1 parent 80ad5b3 commit 86d70f7

File tree

9 files changed

+62
-72
lines changed

9 files changed

+62
-72
lines changed

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestDatabaseClientConnection.java

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,14 @@
3030
import javax.xml.transform.TransformerException;
3131
import java.io.*;
3232
import java.security.KeyManagementException;
33-
import java.security.KeyStoreException;
3433
import java.security.NoSuchAlgorithmException;
35-
import java.security.UnrecoverableKeyException;
36-
import java.security.cert.CertificateException;
3734
import java.security.cert.X509Certificate;
3835
import java.text.DecimalFormat;
3936
import java.util.Iterator;
4037
import java.util.Map;
4138
import java.util.TreeMap;
4239

40+
import static junit.framework.Assert.assertFalse;
4341
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
4442
import static org.junit.jupiter.api.Assertions.assertEquals;
4543
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -88,49 +86,36 @@ public void testDatabaseClientConnectionExist() throws KeyManagementException, N
8886
client.release();
8987
}
9088

91-
// To test getters of SecurityContext
92-
@Test
93-
public void testDatabaseClientGetters() throws KeyManagementException, NoSuchAlgorithmException, IOException
94-
{
95-
System.out.println("Running testDatabaseClientGetters");
96-
97-
DatabaseClient client = null;
98-
SSLContext sslcontext = null;
99-
SecurityContext secContext = newSecurityContext("rest-reader", "x");
100-
101-
try {
102-
sslcontext = getSslContext();
103-
} catch (UnrecoverableKeyException | KeyStoreException | CertificateException e) {
104-
e.printStackTrace();
105-
}
89+
@Test
90+
public void testDatabaseClientGetters() throws Exception {
91+
SecurityContext secContext = newSecurityContext("rest-reader", "x");
92+
SSLContext sslcontext = getSslContext();
10693

10794
secContext.withSSLContext(sslcontext, new X509TrustManager() {
108-
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
109-
// nothing to do
110-
}
111-
112-
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
113-
// nothing to do
114-
}
115-
116-
public X509Certificate[] getAcceptedIssuers() {
117-
return new X509Certificate[0];
118-
}
119-
})
120-
.withSSLHostnameVerifier(SSLHostnameVerifier.ANY);
121-
122-
client = newDatabaseClientBuilder().withSecurityContext(secContext).build();
123-
SecurityContext readSecContext = client.getSecurityContext();
124-
String verifier = readSecContext.getSSLHostnameVerifier().toString();
125-
String protocol = readSecContext.getSSLContext().getProtocol();
126-
boolean needClient = readSecContext.getSSLContext().getSupportedSSLParameters().getNeedClientAuth();
127-
128-
assertTrue(verifier.contains("Builtin"));
129-
assertTrue(protocol.contains("TLSv1.2"));
130-
assertTrue(needClient == false);
131-
// release client
132-
client.release();
133-
}
95+
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
96+
// nothing to do
97+
}
98+
99+
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
100+
// nothing to do
101+
}
102+
103+
public X509Certificate[] getAcceptedIssuers() {
104+
return new X509Certificate[0];
105+
}
106+
})
107+
.withSSLHostnameVerifier(SSLHostnameVerifier.ANY);
108+
109+
try (DatabaseClient client = newDatabaseClientBuilder().withSecurityContext(secContext).build()) {
110+
SecurityContext readSecContext = client.getSecurityContext();
111+
String verifier = readSecContext.getSSLHostnameVerifier().toString();
112+
String protocol = readSecContext.getSSLContext().getProtocol();
113+
boolean needClient = readSecContext.getSSLContext().getSupportedSSLParameters().getNeedClientAuth();
114+
assertTrue(verifier.contains("Builtin"));
115+
assertTrue(protocol.contains("TLS"));
116+
assertFalse(needClient);
117+
}
118+
}
134119

135120

136121
@Test

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/functionaltest/ConnectedRESTQA.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.marklogic.client.DatabaseClientBuilder;
1515
import com.marklogic.client.DatabaseClientFactory;
1616
import com.marklogic.client.admin.ServerConfigurationManager;
17+
import com.marklogic.client.impl.SSLUtil;
1718
import com.marklogic.client.io.DocumentMetadataHandle;
1819
import com.marklogic.client.io.DocumentMetadataHandle.Capability;
1920
import com.marklogic.client.query.QueryManager;
@@ -800,7 +801,7 @@ public X509Certificate[] getAcceptedIssuers() {
800801
KeyManager[] keyMgr = keyManagerFactory.getKeyManagers();
801802

802803
// create an SSL context
803-
SSLContext mlsslContext = SSLContext.getInstance("TLSv1.2");
804+
SSLContext mlsslContext = SSLContext.getInstance(SSLUtil.DEFAULT_PROTOCOL);
804805
mlsslContext.init(keyMgr, new TrustManager[] { tm }, null);
805806

806807
return mlsslContext;

marklogic-client-api/src/main/java/com/marklogic/client/DatabaseClientFactory.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,6 @@ public Map<String, String> toOptions() {
969969
}
970970

971971
public static class CertificateAuthContext extends AuthContext {
972-
private static final String DEFAULT_SSL_PROTOCOL = "TLSv1.2";
973972
String certFile;
974973
String certPassword;
975974

@@ -1087,7 +1086,7 @@ public CertificateAuthContext(String certFile, String certPassword, X509TrustMan
10871086
this.certFile = certFile;
10881087
this.certPassword = certPassword;
10891088
this.trustManager = trustManager;
1090-
this.sslContext = createSSLContext(DEFAULT_SSL_PROTOCOL);
1089+
this.sslContext = createSSLContext(SSLUtil.DEFAULT_PROTOCOL);
10911090
}
10921091

10931092
/**
@@ -1148,11 +1147,9 @@ private SSLContext createSSLContext(String sslProtocol)
11481147
}
11491148
keyManagerFactory.init(keyStore, certPassword.toCharArray());
11501149
keyMgr = keyManagerFactory.getKeyManagers();
1151-
if (sslProtocol == null) {
1152-
sslContext = SSLContext.getInstance(DEFAULT_SSL_PROTOCOL);
1153-
} else {
1154-
sslContext = SSLContext.getInstance(sslProtocol);
1155-
}
1150+
sslContext = sslProtocol == null ?
1151+
SSLContext.getInstance(SSLUtil.DEFAULT_PROTOCOL) :
1152+
SSLContext.getInstance(sslProtocol);
11561153
} catch (NoSuchAlgorithmException | KeyStoreException e) {
11571154
SSLUtil.logSecurityRelatedException(e);
11581155
throw new IllegalStateException("The certificate algorithm used or the Key store "

marklogic-client-api/src/main/java/com/marklogic/client/impl/DatabaseClientPropertySource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ private SSLUtil.SSLInputs useKeyStoreForTwoWaySSL(String keyStorePath, X509Trust
411411
final String keyStoreType = getNullableStringValue("ssl.keystore.type", "JKS");
412412
final String algorithm = getNullableStringValue("ssl.keystore.algorithm", "SunX509");
413413
final char[] charPassword = password != null ? password.toCharArray() : null;
414-
final String sslProtocol = getNullableStringValue("sslProtocol", "TLSv1.2");
414+
final String sslProtocol = getNullableStringValue("sslProtocol", SSLUtil.DEFAULT_PROTOCOL);
415415
return SSLUtil.createSSLContextFromKeyStore(keyStorePath, charPassword, keyStoreType, algorithm, sslProtocol, userTrustManager);
416416
}
417417

marklogic-client-api/src/main/java/com/marklogic/client/impl/SSLUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public abstract class SSLUtil {
2222

2323
private final static Logger LOGGER = LoggerFactory.getLogger("com.marklogic.client.security");
2424

25+
// Added in 7.2.0 so that clients using MarkLogic 12 will default to TLSv1.3, while clients using MarkLogic 11
26+
// or older will default to TLSv1.2.
27+
public static final String DEFAULT_PROTOCOL = "TLS";
28+
2529
/**
2630
* Included to satisfy Polaris, which requires that security-related exceptions be logged, in addition to being
2731
* thrown. This is logged at the debug level to avoid cluttering logs in an application that is likely already

marklogic-client-api/src/test/java/com/marklogic/client/test/DatabaseClientBuilderTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.marklogic.client.DatabaseClientBuilder;
55
import com.marklogic.client.DatabaseClientFactory;
66
import com.marklogic.client.ext.modulesloader.ssl.SimpleX509TrustManager;
7+
import com.marklogic.client.impl.SSLUtil;
78
import org.junit.jupiter.api.Test;
89
import org.junit.jupiter.params.ParameterizedTest;
910
import org.junit.jupiter.params.provider.ValueSource;
@@ -343,7 +344,7 @@ void defaultSslContext() throws Exception {
343344
@Test
344345
void sslProtocol() {
345346
bean = Common.newClientBuilder()
346-
.withSSLProtocol("TLSv1.2")
347+
.withSSLProtocol(SSLUtil.DEFAULT_PROTOCOL)
347348
.buildBean();
348349

349350
assertNotNull(bean.getSecurityContext().getSSLContext());
@@ -390,7 +391,7 @@ void invalidSslProtocol() {
390391
@Test
391392
void sslProtocolAndTrustManager() {
392393
bean = Common.newClientBuilder()
393-
.withSSLProtocol("TLSv1.2")
394+
.withSSLProtocol(SSLUtil.DEFAULT_PROTOCOL)
394395
.withTrustManager(Common.TRUST_ALL_MANAGER)
395396
.buildBean();
396397

@@ -409,7 +410,7 @@ void sslProtocolAndTrustManager() {
409410
@Test
410411
void sslProtocolAndTrustManagerAndHostnameVerifier() {
411412
bean = Common.newClientBuilder()
412-
.withSSLProtocol("TLSv1.2")
413+
.withSSLProtocol(SSLUtil.DEFAULT_PROTOCOL)
413414
.withSSLHostnameVerifier(DatabaseClientFactory.SSLHostnameVerifier.COMMON)
414415
.withTrustManager(Common.TRUST_ALL_MANAGER)
415416
.buildBean();

marklogic-client-api/src/test/java/com/marklogic/client/test/ssl/OneWaySSLTest.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.marklogic.client.DatabaseClientFactory;
55
import com.marklogic.client.ForbiddenUserException;
66
import com.marklogic.client.MarkLogicIOException;
7+
import com.marklogic.client.impl.SSLUtil;
78
import com.marklogic.client.test.Common;
89
import com.marklogic.client.test.MarkLogicVersion;
910
import com.marklogic.client.test.junit5.DisabledWhenUsingReverseProxyServer;
@@ -65,7 +66,7 @@ private static void setAppServerMinimumTLSVersion(String minTLSVersion) {
6566
*/
6667
@Test
6768
void trustAllManager() throws Exception {
68-
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
69+
SSLContext sslContext = SSLContext.getInstance(SSLUtil.DEFAULT_PROTOCOL);
6970
sslContext.init(null, new TrustManager[]{Common.TRUST_ALL_MANAGER}, null);
7071

7172
DatabaseClient client = Common.newClientBuilder()
@@ -87,7 +88,7 @@ void trustAllManager() throws Exception {
8788
@Test
8889
void trustManagerThatOnlyTrustsTheCertificateFromTheCertificateTemplate() {
8990
DatabaseClient client = Common.newClientBuilder()
90-
.withSSLProtocol("TLSv1.2")
91+
.withSSLProtocol(SSLUtil.DEFAULT_PROTOCOL)
9192
.withTrustManager(RequireSSLExtension.newSecureTrustManager())
9293
.withSSLHostnameVerifier(DatabaseClientFactory.SSLHostnameVerifier.ANY)
9394
.build();
@@ -113,7 +114,7 @@ void defaultSslContext() throws Exception {
113114

114115
@ExtendWith(RequiresML11OrLower.class)
115116
@Test
116-
void noSslContext() throws Exception {
117+
void noSslContext() {
117118
DatabaseClient client = Common.newClientBuilder().build();
118119

119120
DatabaseClient.ConnectionResult result = client.checkConnection();
@@ -132,22 +133,21 @@ void noSslContext() throws Exception {
132133
);
133134
}
134135

135-
// The TLS tests are failing on Java 8, because TLSv1.3 is disabled with our version of Java 8.
136-
// There may be a way to configure Java 8 to use TLSv1.3, but it is not currently working.
137-
@DisabledOnJre(JRE.JAVA_8)
138136
@Test
139-
void tLS13ClientWithTLS12Server() throws Exception {
140-
DatabaseClient client = buildTrustAllClientWithSSLProtocol("TLSv1.3");
137+
void tLS13ClientWithTLS12Server() {
138+
DatabaseClient client = buildTrustAllClientWithSSLProtocol(SSLUtil.DEFAULT_PROTOCOL);
141139
DatabaseClient.ConnectionResult result = client.checkConnection();
142140
assertEquals(0, result.getStatusCode(), "A value of zero implies that a connection was successfully made, " +
143141
"which should happen since a 'trust all' manager is being used");
144142
assertNull(result.getErrorMessage());
145143
}
146144

147145
@ExtendWith(RequiresML12.class)
146+
// The TLSv1.3 tests are failing on Java 8, because TLSv1.3 is disabled with our version of Java 8.
147+
// There may be a way to configure Java 8 to use TLSv1.3, but it is not currently working.
148148
@DisabledOnJre(JRE.JAVA_8)
149149
@Test
150-
void tLS13ClientWithTLS13Server() throws Exception {
150+
void tLS13ClientWithTLS13Server() {
151151
setAppServerMinimumTLSVersion("TLSv1.3");
152152

153153
DatabaseClient client = buildTrustAllClientWithSSLProtocol("TLSv1.3");
@@ -160,7 +160,7 @@ void tLS13ClientWithTLS13Server() throws Exception {
160160
@ExtendWith(RequiresML12.class)
161161
@DisabledOnJre(JRE.JAVA_8)
162162
@Test
163-
void tLS12ClientWithTLS13ServerShouldFail() throws Exception {
163+
void tLS12ClientWithTLS13ServerShouldFail() {
164164
setAppServerMinimumTLSVersion("TLSv1.3");
165165

166166
DatabaseClient client = buildTrustAllClientWithSSLProtocol("TLSv1.2");

marklogic-client-api/src/test/java/com/marklogic/client/test/ssl/TwoWaySSLTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.marklogic.client.MarkLogicIOException;
88
import com.marklogic.client.document.DocumentDescriptor;
99
import com.marklogic.client.eval.EvalResultIterator;
10+
import com.marklogic.client.impl.SSLUtil;
1011
import com.marklogic.client.io.StringHandle;
1112
import com.marklogic.client.test.Common;
1213
import com.marklogic.client.test.junit5.DisabledWhenUsingReverseProxyServer;
@@ -42,7 +43,7 @@
4243
DisabledWhenUsingReverseProxyServer.class,
4344
RequireSSLExtension.class
4445
})
45-
public class TwoWaySSLTest {
46+
class TwoWaySSLTest {
4647

4748
private static final String TEST_DOCUMENT_URI = "/optic/test/musician1.json";
4849
private static final String KEYSTORE_PASSWORD = "password";
@@ -64,7 +65,7 @@ public static void setup() throws Exception {
6465
// talks to the Security database.
6566
securityClient = Common.newClientBuilder()
6667
.withUsername(Common.SERVER_ADMIN_USER).withPassword(Common.SERVER_ADMIN_PASS)
67-
.withSSLProtocol("TLSv1.2")
68+
.withSSLProtocol(SSLUtil.DEFAULT_PROTOCOL)
6869
.withTrustManager(Common.TRUST_ALL_MANAGER)
6970
.withSSLHostnameVerifier(DatabaseClientFactory.SSLHostnameVerifier.ANY)
7071
.withDatabase("Security").build();
@@ -101,7 +102,7 @@ public static void teardown() {
101102
*/
102103
@ExtendWith(RequiresML11OrLower.class)
103104
@Test
104-
void digestAuthentication() throws NoSuchAlgorithmException, KeyManagementException {
105+
void digestAuthentication() {
105106
// This client uses our Java KeyStore file with a client certificate in it, so it should work.
106107
DatabaseClient clientWithCert = Common.newClientBuilder()
107108
.withKeyStorePath(keyStoreFile.getAbsolutePath())
@@ -122,7 +123,7 @@ void digestAuthentication() throws NoSuchAlgorithmException, KeyManagementExcept
122123
// This client uses a new SSL context without the client certificate, so it should fail.
123124
DatabaseClient clientWithoutCert = Common.newClientBuilder()
124125
.withSSLHostnameVerifier(DatabaseClientFactory.SSLHostnameVerifier.ANY)
125-
.withSSLProtocol("TLSv1.2")
126+
.withSSLProtocol(SSLUtil.DEFAULT_PROTOCOL)
126127
.withTrustManager(RequireSSLExtension.newSecureTrustManager())
127128
.build();
128129

@@ -261,7 +262,7 @@ private SSLContext createSSLContextWithClientCertificate(File keystoreFile) thro
261262
keyStore.load(new FileInputStream(keystoreFile), KEYSTORE_PASSWORD.toCharArray());
262263
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
263264
keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());
264-
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
265+
SSLContext sslContext = SSLContext.getInstance(SSLUtil.DEFAULT_PROTOCOL);
265266
sslContext.init(
266267
keyManagerFactory.getKeyManagers(),
267268
new X509TrustManager[]{RequireSSLExtension.newSecureTrustManager()},

test-app/src/main/java/com/marklogic/client/test/ReverseProxyServer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ private SSLContext buildSSLContext() throws Exception {
205205
}
206206
kmf.init(keyStore, keyStorePassword.toCharArray());
207207

208-
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
208+
// Using TLS to support MarkLogic 12
209+
SSLContext sslContext = SSLContext.getInstance("TLS");
209210
// Use a "trust-everything" approach for now; the client doesn't have to do this, but we don't have a use case
210211
// yet for having our reverse proxy server validate certificates.
211212
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{new SimpleX509TrustManager()}, null);

0 commit comments

Comments
 (0)