From f5259462e97526c70859af2472aeceaefd412ea7 Mon Sep 17 00:00:00 2001 From: Charles Connell Date: Fri, 29 Sep 2023 15:03:17 -0400 Subject: [PATCH 1/4] Support TLSv1.3 cipher suites --- .../hadoop/hbase/io/crypto/tls/X509Util.java | 47 ++++++++++--------- .../hbase/io/crypto/tls/TestX509Util.java | 8 ++-- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java index 7d16a82b1f3e..4ba95e44ea6e 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java @@ -115,6 +115,13 @@ public final class X509Util { "hbase.client.netty.tls.handshaketimeout"; public static final int DEFAULT_HANDSHAKE_DETECTION_TIMEOUT_MILLIS = 5000; + private static String[] getTls13Ciphers() { + return new String[] { + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384" + }; + } + private static String[] getGCMCiphers() { return new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", @@ -136,12 +143,15 @@ private static String[] getCBCCiphers() { // Note that this performance assumption might not hold true for architectures other than x86_64. private static final String[] DEFAULT_CIPHERS_JAVA9 = ObjectArrays.concat(getGCMCiphers(), getCBCCiphers(), String.class); + private static final String[] DEFAULT_CIPHERS_JAVA11 = + ObjectArrays.concat(ObjectArrays.concat(getTls13Ciphers(), getGCMCiphers(), String.class), + getCBCCiphers(), String.class); private static final String[] DEFAULT_CIPHERS_OPENSSL = getOpenSslFilteredDefaultCiphers(); /** * Not all of our default ciphers are available in OpenSSL. Takes our default cipher lists and - * filters them to only those available in OpenSsl. Does GCM first, then CBC because GCM tends to + * filters them to only those available in OpenSsl. Prefers TLS 1.3, then GCM, then CBC because GCM tends to * be better and faster, and we don't need to worry about the java8 vs 9 performance issue if * OpenSSL is handling it. */ @@ -152,16 +162,9 @@ private static String[] getOpenSslFilteredDefaultCiphers() { Set openSslSuites = OpenSsl.availableJavaCipherSuites(); List defaultSuites = new ArrayList<>(); - for (String cipher : getGCMCiphers()) { - if (openSslSuites.contains(cipher)) { - defaultSuites.add(cipher); - } - } - for (String cipher : getCBCCiphers()) { - if (openSslSuites.contains(cipher)) { - defaultSuites.add(cipher); - } - } + Arrays.stream(getTls13Ciphers()).filter(openSslSuites::contains).forEach(defaultSuites::add); + Arrays.stream(getGCMCiphers()).filter(openSslSuites::contains).forEach(defaultSuites::add); + Arrays.stream(getCBCCiphers()).filter(openSslSuites::contains).forEach(defaultSuites::add); return defaultSuites.toArray(new String[0]); } @@ -219,17 +222,17 @@ static String[] getDefaultCipherSuites(boolean useOpenSsl) { static String[] getDefaultCipherSuitesForJavaVersion(String javaVersion) { Objects.requireNonNull(javaVersion); - if (javaVersion.matches("\\d+")) { - // Must be Java 9 or later - LOG.debug("Using Java9+ optimized cipher suites for Java version {}", javaVersion); - return DEFAULT_CIPHERS_JAVA9; - } else if (javaVersion.startsWith("1.")) { - // Must be Java 1.8 or earlier - LOG.debug("Using Java8 optimized cipher suites for Java version {}", javaVersion); - return DEFAULT_CIPHERS_JAVA8; - } else { - LOG.debug("Could not parse java version {}, using Java8 optimized cipher suites", - javaVersion); + + try { + int javaVersionInt = Integer.parseInt(javaVersion); + if (javaVersionInt >= 11) { + return DEFAULT_CIPHERS_JAVA11; + } else if (javaVersionInt >= 9) { + return DEFAULT_CIPHERS_JAVA9; + } else { + return DEFAULT_CIPHERS_JAVA8; + } + } catch (NumberFormatException ignore) { return DEFAULT_CIPHERS_JAVA8; } } diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/io/crypto/tls/TestX509Util.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/io/crypto/tls/TestX509Util.java index dd81403af6f2..dd43f8be5cb8 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/io/crypto/tls/TestX509Util.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/io/crypto/tls/TestX509Util.java @@ -379,21 +379,21 @@ public void testGetDefaultCipherSuitesJava8() { public void testGetDefaultCipherSuitesJava9() { String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("9"); // Java 9+ default should have the GCM suites first - assertThat(cipherSuites[0], containsString("GCM")); + assertEquals(cipherSuites[0], "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); } @Test public void testGetDefaultCipherSuitesJava10() { String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("10"); // Java 9+ default should have the GCM suites first - assertThat(cipherSuites[0], containsString("GCM")); + assertEquals(cipherSuites[0], "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); } @Test public void testGetDefaultCipherSuitesJava11() { String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("11"); - // Java 9+ default should have the GCM suites first - assertThat(cipherSuites[0], containsString("GCM")); + // Java 11+ default should have the TLSv1.3 suites first + assertThat(cipherSuites[0], containsString("TLS_AES_128_GCM")); } @Test From 86ddbda70023f62d3441fe8a1ac9ec4761fdd183 Mon Sep 17 00:00:00 2001 From: Charles Connell Date: Fri, 29 Sep 2023 16:34:14 -0400 Subject: [PATCH 2/4] spotless:apply --- .../apache/hadoop/hbase/io/crypto/tls/X509Util.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java index 4ba95e44ea6e..947e4903b976 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java @@ -116,10 +116,7 @@ public final class X509Util { public static final int DEFAULT_HANDSHAKE_DETECTION_TIMEOUT_MILLIS = 5000; private static String[] getTls13Ciphers() { - return new String[] { - "TLS_AES_128_GCM_SHA256", - "TLS_AES_256_GCM_SHA384" - }; + return new String[] { "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384" }; } private static String[] getGCMCiphers() { @@ -151,9 +148,9 @@ private static String[] getCBCCiphers() { /** * Not all of our default ciphers are available in OpenSSL. Takes our default cipher lists and - * filters them to only those available in OpenSsl. Prefers TLS 1.3, then GCM, then CBC because GCM tends to - * be better and faster, and we don't need to worry about the java8 vs 9 performance issue if - * OpenSSL is handling it. + * filters them to only those available in OpenSsl. Prefers TLS 1.3, then GCM, then CBC because + * GCM tends to be better and faster, and we don't need to worry about the java8 vs 9 performance + * issue if OpenSSL is handling it. */ private static String[] getOpenSslFilteredDefaultCiphers() { if (!OpenSsl.isAvailable()) { From 8ed2f1684dda57dbe9331e9f92b688acc457da87 Mon Sep 17 00:00:00 2001 From: Charles Connell Date: Tue, 7 Nov 2023 10:40:59 -0500 Subject: [PATCH 3/4] Change Java version string parsing --- .../hadoop/hbase/io/crypto/tls/X509Util.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java index 947e4903b976..9aa7ad2a4570 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java @@ -220,16 +220,22 @@ static String[] getDefaultCipherSuites(boolean useOpenSsl) { static String[] getDefaultCipherSuitesForJavaVersion(String javaVersion) { Objects.requireNonNull(javaVersion); - try { + if (javaVersion.matches("\\d+")) { + // Must be Java 9 or later int javaVersionInt = Integer.parseInt(javaVersion); if (javaVersionInt >= 11) { return DEFAULT_CIPHERS_JAVA11; - } else if (javaVersionInt >= 9) { - return DEFAULT_CIPHERS_JAVA9; } else { - return DEFAULT_CIPHERS_JAVA8; + LOG.debug("Using Java9+ optimized cipher suites for Java version {}", javaVersion); + return DEFAULT_CIPHERS_JAVA9; } - } catch (NumberFormatException ignore) { + } else if (javaVersion.startsWith("1.")) { + // Must be Java 1.8 or earlier + LOG.debug("Using Java8 optimized cipher suites for Java version {}", javaVersion); + return DEFAULT_CIPHERS_JAVA8; + } else { + LOG.debug("Could not parse java version {}, using Java8 optimized cipher suites", + javaVersion); return DEFAULT_CIPHERS_JAVA8; } } From e9ea1abcd6858efd23a7a693b76658726d12eb37 Mon Sep 17 00:00:00 2001 From: Charles Connell Date: Wed, 8 Nov 2023 10:54:09 -0500 Subject: [PATCH 4/4] add log line --- .../java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java index 9aa7ad2a4570..41acfbbf48f4 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/X509Util.java @@ -224,6 +224,9 @@ static String[] getDefaultCipherSuitesForJavaVersion(String javaVersion) { // Must be Java 9 or later int javaVersionInt = Integer.parseInt(javaVersion); if (javaVersionInt >= 11) { + LOG.debug( + "Using Java11+ optimized cipher suites for Java version {}, including TLSv1.3 support", + javaVersion); return DEFAULT_CIPHERS_JAVA11; } else { LOG.debug("Using Java9+ optimized cipher suites for Java version {}", javaVersion);