Skip to content

Commit

Permalink
HBASE-28008 Add support for netty tcnative (apache#5363)
Browse files Browse the repository at this point in the history
Signed-off-by: Duo Zhang <[email protected]>
Reviewed-by: Andor Molnar <[email protected]>
  • Loading branch information
bbeaudreault authored and wchevreuil committed Nov 2, 2023
1 parent 78b76c7 commit 80b9d18
Showing 1 changed file with 68 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@
import java.security.Security;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.X509CertSelector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.KeyManager;
Expand All @@ -49,8 +52,10 @@
import org.slf4j.LoggerFactory;

import org.apache.hbase.thirdparty.com.google.common.collect.ObjectArrays;
import org.apache.hbase.thirdparty.io.netty.handler.ssl.OpenSsl;
import org.apache.hbase.thirdparty.io.netty.handler.ssl.SslContext;
import org.apache.hbase.thirdparty.io.netty.handler.ssl.SslContextBuilder;
import org.apache.hbase.thirdparty.io.netty.handler.ssl.SslProvider;

/**
* Utility code for X509 handling Default cipher suites: Performance testing done by Facebook
Expand Down Expand Up @@ -83,9 +88,10 @@ public final class X509Util {
public static final String TLS_CONFIG_OCSP = CONFIG_PREFIX + "ocsp";
public static final String TLS_CONFIG_REVERSE_DNS_LOOKUP_ENABLED =
CONFIG_PREFIX + "host-verification.reverse-dns.enabled";
private static final String TLS_ENABLED_PROTOCOLS = CONFIG_PREFIX + "enabledProtocols";
private static final String TLS_CIPHER_SUITES = CONFIG_PREFIX + "ciphersuites";
public static final String TLS_ENABLED_PROTOCOLS = CONFIG_PREFIX + "enabledProtocols";
public static final String TLS_CIPHER_SUITES = CONFIG_PREFIX + "ciphersuites";
public static final String TLS_CERT_RELOAD = CONFIG_PREFIX + "certReload";
public static final String TLS_USE_OPENSSL = CONFIG_PREFIX + "useOpenSsl";
public static final String DEFAULT_PROTOCOL = "TLSv1.2";

//
Expand Down Expand Up @@ -131,6 +137,34 @@ private static String[] getCBCCiphers() {
private static final String[] DEFAULT_CIPHERS_JAVA9 =
ObjectArrays.concat(getGCMCiphers(), 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
* 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()) {
return new String[0];
}

Set<String> openSslSuites = OpenSsl.availableJavaCipherSuites();
List<String> 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);
}
}
return defaultSuites.toArray(new String[0]);
}

/**
* Enum specifying the client auth requirement of server-side TLS sockets created by this
* X509Util.
Expand Down Expand Up @@ -176,7 +210,10 @@ private X509Util() {
// disabled
}

static String[] getDefaultCipherSuites() {
static String[] getDefaultCipherSuites(boolean useOpenSsl) {
if (useOpenSsl) {
return DEFAULT_CIPHERS_OPENSSL;
}
return getDefaultCipherSuitesForJavaVersion(System.getProperty("java.specification.version"));
}

Expand All @@ -202,6 +239,7 @@ public static SslContext createSslContextForClient(Configuration config)

SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();

boolean useOpenSsl = configureOpenSslIfAvailable(sslContextBuilder, config);
String keyStoreLocation = config.get(TLS_CONFIG_KEYSTORE_LOCATION, "");
char[] keyStorePassword = config.getPassword(TLS_CONFIG_KEYSTORE_PASSWORD);
String keyStoreType = config.get(TLS_CONFIG_KEYSTORE_TYPE, "");
Expand Down Expand Up @@ -234,11 +272,33 @@ public static SslContext createSslContextForClient(Configuration config)

sslContextBuilder.enableOcsp(sslOcspEnabled);
sslContextBuilder.protocols(getEnabledProtocols(config));
sslContextBuilder.ciphers(Arrays.asList(getCipherSuites(config)));
sslContextBuilder.ciphers(Arrays.asList(getCipherSuites(config, useOpenSsl)));

return sslContextBuilder.build();
}

/**
* Adds SslProvider.OPENSSL if OpenSsl is available and enabled. In order to make it available,
* one must ensure that a properly shaded netty-tcnative is on the classpath. Properly shaded
* means relocated to be prefixed with "org.apache.hbase.thirdparty" like the rest of the netty
* classes.
*/
private static boolean configureOpenSslIfAvailable(SslContextBuilder sslContextBuilder,
Configuration conf) {
if (OpenSsl.isAvailable() && conf.getBoolean(TLS_USE_OPENSSL, true)) {
LOG.debug("Using netty-tcnative to accelerate SSL handling");
sslContextBuilder.sslProvider(SslProvider.OPENSSL);
return true;
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Using default JDK SSL provider because netty-tcnative is not {}",
OpenSsl.isAvailable() ? "enabled" : "available");
}
sslContextBuilder.sslProvider(SslProvider.JDK);
return false;
}
}

public static SslContext createSslContextForServer(Configuration config)
throws X509Exception, IOException {
String keyStoreLocation = config.get(TLS_CONFIG_KEYSTORE_LOCATION, "");
Expand All @@ -254,6 +314,7 @@ public static SslContext createSslContextForServer(Configuration config)
sslContextBuilder = SslContextBuilder
.forServer(createKeyManager(keyStoreLocation, keyStorePassword, keyStoreType));

boolean useOpenSsl = configureOpenSslIfAvailable(sslContextBuilder, config);
String trustStoreLocation = config.get(TLS_CONFIG_TRUSTSTORE_LOCATION, "");
char[] trustStorePassword = config.getPassword(TLS_CONFIG_TRUSTSTORE_PASSWORD);
String trustStoreType = config.get(TLS_CONFIG_TRUSTSTORE_TYPE, "");
Expand All @@ -277,7 +338,7 @@ public static SslContext createSslContextForServer(Configuration config)

sslContextBuilder.enableOcsp(sslOcspEnabled);
sslContextBuilder.protocols(getEnabledProtocols(config));
sslContextBuilder.ciphers(Arrays.asList(getCipherSuites(config)));
sslContextBuilder.ciphers(Arrays.asList(getCipherSuites(config, useOpenSsl)));
sslContextBuilder.clientAuth(clientAuth.toNettyClientAuth());

return sslContextBuilder.build();
Expand Down Expand Up @@ -393,10 +454,10 @@ private static String[] getEnabledProtocols(Configuration config) {
return enabledProtocolsInput.split(",");
}

private static String[] getCipherSuites(Configuration config) {
private static String[] getCipherSuites(Configuration config, boolean useOpenSsl) {
String cipherSuitesInput = config.get(TLS_CIPHER_SUITES);
if (cipherSuitesInput == null) {
return getDefaultCipherSuites();
return getDefaultCipherSuites(useOpenSsl);
} else {
return cipherSuitesInput.split(",");
}
Expand Down

0 comments on commit 80b9d18

Please sign in to comment.