ctubbsii commented on code in PR #1919:
URL: https://github.com/apache/zookeeper/pull/1919#discussion_r1336181672
##########
zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java:
##########
@@ -81,7 +87,32 @@ public abstract class X509Util implements Closeable,
AutoCloseable {
}
}
- public static final String DEFAULT_PROTOCOL = "TLSv1.2";
+ public static final String DEFAULT_PROTOCOL = defaultTlsProtocol();
+
+ /**
+ * Return TLSv1.3 or TLSv1.2 depending on Java runtime version being used.
+ * TLSv1.3 was first introduced in JDK11 and back-ported to OpenJDK 8u272.
+ */
+ private static String defaultTlsProtocol() {
+ String defaultProtocol = "TLSv1.2";
+ List<String> supported = new ArrayList<>();
+ try {
+ supported =
Arrays.asList(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());
+ if (supported.contains("TLSv1.3")) {
+ defaultProtocol = "TLSv1.3";
+ }
+ } catch (NoSuchAlgorithmException e) {
+ // Ignore.
+ }
+ LOG.info("Default TLS protocol is {}, supported TLS protocols are {}",
defaultProtocol, supported);
+ return defaultProtocol;
+ }
+
+ // ChaCha20 was introduced in OpenJDK 11.0.15 and it is not supported by
JDK8.
+ private static String[] getTLSv13Ciphers() {
+ return new String[]{"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256"};
+ }
Review Comment:
It kind of feels wrong that ZK is hard-coding lists of ciphers to use. It
seems that users should be able to control their preferred ciphers in their
normal Java security configuration settings. One reason a user might want to do
that is to enforce a system-wide security policy.
Filtering out these lists by what is supported by the JDK also limits the
user to what is in these lists, rather than being able to use something newer
that might be available in their JDK.
##########
zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java:
##########
@@ -102,6 +106,19 @@ public void testCreateSSLContextWithoutCustomProtocol(
init(caKeyType, certKeyType, keyPassword, paramIndex);
SSLContext sslContext = x509Util.getDefaultSSLContext();
assertEquals(X509Util.DEFAULT_PROTOCOL, sslContext.getProtocol());
+
+ // Check that TLSv1.3 is selected in JDKs that support it (OpenJDK
8u272 and later).
+ List<String> supported =
Arrays.asList(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());
+ if (supported.contains("TLSv1.3")) {
+ // SSLContext protocol.
+ assertEquals("TLSv1.3", sslContext.getProtocol());
+ // Enabled protocols.
+
assertThat(Arrays.asList(sslContext.getDefaultSSLParameters().getProtocols()),
+ Matchers.containsInAnyOrder(new String[] {"TLSv1.2",
"TLSv1.3"}));
Review Comment:
You don't actually need to use the hamcrest matcher here. It'd be better to
avoid it, to help phase out its use, which probably isn't needed at all with
JUnit5.
```suggestion
List<String> protos =
Arrays.asList(sslContext.getDefaultSSLParameters().getProtocols());
assertTrue(protos.contains("TLSv1.2"));
assertTrue(protos.contains("TLSv1.3"));
```
##########
zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java:
##########
@@ -90,18 +121,30 @@ private static String[] getCBCCiphers() {
return new String[]{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"};
}
- private static String[] concatArrays(String[] left, String[] right) {
- String[] result = new String[left.length + right.length];
- System.arraycopy(left, 0, result, 0, left.length);
- System.arraycopy(right, 0, result, left.length, right.length);
- return result;
+ /**
+ * Returns a filtered set of ciphers, where ciphers not supported by the
JDK are removed.
+ */
+ private static String[] getSupportedCiphers(String[]... cipherLists) {
Review Comment:
This method returns an array. It'd be a bigger change to return an
unmodifiable list, but it might be worth it in a future change, because this
gets converted back to a list later, and it's probably better to keep it as a
list here, then only convert it to an array when needed, rather than convert it
to an array now and then convert it back to a list later. That could probably
be done in a subsequent change, though, rather than making that change in this
PR.
##########
zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java:
##########
@@ -81,7 +87,32 @@ public abstract class X509Util implements Closeable,
AutoCloseable {
}
}
- public static final String DEFAULT_PROTOCOL = "TLSv1.2";
+ public static final String DEFAULT_PROTOCOL = defaultTlsProtocol();
+
+ /**
+ * Return TLSv1.3 or TLSv1.2 depending on Java runtime version being used.
+ * TLSv1.3 was first introduced in JDK11 and back-ported to OpenJDK 8u272.
+ */
+ private static String defaultTlsProtocol() {
+ String defaultProtocol = "TLSv1.2";
Review Comment:
There are a lot of places where "TLSv1.2" and "TLSv1.3" are used as String
literals. It'd be good to make those constants somewhere, to avoid typos.
##########
zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java:
##########
@@ -90,18 +121,30 @@ private static String[] getCBCCiphers() {
return new String[]{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"};
}
- private static String[] concatArrays(String[] left, String[] right) {
- String[] result = new String[left.length + right.length];
- System.arraycopy(left, 0, result, 0, left.length);
- System.arraycopy(right, 0, result, left.length, right.length);
- return result;
+ /**
+ * Returns a filtered set of ciphers, where ciphers not supported by the
JDK are removed.
+ */
+ private static String[] getSupportedCiphers(String[]... cipherLists) {
+ Set<String> supported = new HashSet<>(Arrays.asList(
+ ((SSLServerSocketFactory)
SSLServerSocketFactory.getDefault()).getSupportedCipherSuites()));
Review Comment:
This list doesn't need to be placed inside a set. The `.contains` check will
work on the list.
```suggestion
List<String> supported = Arrays.asList(
((SSLServerSocketFactory)
SSLServerSocketFactory.getDefault()).getSupportedCipherSuites());
```
##########
zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java:
##########
@@ -90,18 +121,30 @@ private static String[] getCBCCiphers() {
return new String[]{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"};
}
- private static String[] concatArrays(String[] left, String[] right) {
- String[] result = new String[left.length + right.length];
- System.arraycopy(left, 0, result, 0, left.length);
- System.arraycopy(right, 0, result, left.length, right.length);
- return result;
+ /**
+ * Returns a filtered set of ciphers, where ciphers not supported by the
JDK are removed.
+ */
+ private static String[] getSupportedCiphers(String[]... cipherLists) {
+ Set<String> supported = new HashSet<>(Arrays.asList(
+ ((SSLServerSocketFactory)
SSLServerSocketFactory.getDefault()).getSupportedCipherSuites()));
+
+ List<String> chosen = new ArrayList<>();
+ for (String[] ciphers : cipherLists) {
+ for (String cipher : ciphers) {
+ if (supported.contains(cipher)) {
+ chosen.add(cipher);
+ }
+ }
+ }
+ return chosen.toArray(new String[0]);
Review Comment:
This is a pretty simple Stream operation that concatenates the lists,
filters on whether the elements exist in the supported list, and then collects
them into the list, all in one line (2 when wrapped):
```suggestion
return
Arrays.stream(cipherLists).flatMap(Arrays::stream).filter(supported::contains)
.collect(Collectors.toList()).toArray(new String[0]);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]