From 65daf5530b9eb27eecca5b6abfcd62f1de51c6e7 Mon Sep 17 00:00:00 2001 From: Zixuan Liu Date: Tue, 22 Mar 2022 15:30:36 +0800 Subject: [PATCH] [feat][broker] Full-support set ssl provider, ciphers and protocols Signed-off-by: Zixuan Liu --- conf/broker.conf | 8 +- conf/standalone.conf | 8 +- .../pulsar/broker/ServiceConfiguration.java | 4 +- .../service/PulsarChannelInitializer.java | 15 +- .../internal/http/AsyncHttpConnector.java | 26 +++- .../apache/pulsar/client/impl/HttpClient.java | 25 +++- .../client/impl/PulsarChannelInitializer.java | 34 +++-- .../util/NettyClientSslContextRefresher.java | 33 +++-- .../util/NettyServerSslContextBuilder.java | 16 ++- .../pulsar/common/util/SecurityUtility.java | 69 ++++++--- .../util/FileModifiedTimeUpdaterTest.java | 4 +- .../common/util/netty/SslContextTest.java | 132 ++++++++++++++++++ .../src/test/resources/ssl/my-ca/ca.pem | 18 +++ .../test/resources/ssl/my-ca/client-ca.pem | 19 +++ .../test/resources/ssl/my-ca/client-key.pem | 28 ++++ .../test/resources/ssl/my-ca/server-ca.pem | 19 +++ .../test/resources/ssl/my-ca/server-key.pem | 28 ++++ .../proxy/server/ProxyConfiguration.java | 4 +- .../server/ServiceChannelInitializer.java | 19 ++- 19 files changed, 433 insertions(+), 76 deletions(-) create mode 100644 pulsar-common/src/test/java/org/apache/pulsar/common/util/netty/SslContextTest.java create mode 100644 pulsar-common/src/test/resources/ssl/my-ca/ca.pem create mode 100644 pulsar-common/src/test/resources/ssl/my-ca/client-ca.pem create mode 100644 pulsar-common/src/test/resources/ssl/my-ca/client-key.pem create mode 100644 pulsar-common/src/test/resources/ssl/my-ca/server-ca.pem create mode 100644 pulsar-common/src/test/resources/ssl/my-ca/server-key.pem diff --git a/conf/broker.conf b/conf/broker.conf index a373dc4650e69..c3bb447a80b1e 100644 --- a/conf/broker.conf +++ b/conf/broker.conf @@ -618,13 +618,15 @@ tlsCiphers= # authentication. tlsRequireTrustedClientCertOnConnect=false +# Specify the TLS provider for the broker service: +# When using TLS authentication with CACert, the valid value is either OPENSSL or JDK. +# When using TLS authentication with KeyStore, available values can be SunJSSE, Conscrypt and etc. +tlsProvider= + ### --- KeyStore TLS config variables --- ### # Enable TLS with KeyStore type configuration in broker. tlsEnabledWithKeyStore=false -# TLS Provider for KeyStore type -tlsProvider= - # TLS KeyStore type configuration in broker: JKS, PKCS12 tlsKeyStoreType=JKS diff --git a/conf/standalone.conf b/conf/standalone.conf index 3a9143f5cbf1f..3ea8664f6952e 100644 --- a/conf/standalone.conf +++ b/conf/standalone.conf @@ -379,13 +379,15 @@ tlsCiphers= # authentication. tlsRequireTrustedClientCertOnConnect=false +# Specify the TLS provider for the broker service: +# When using TLS authentication with CACert, the valid value is either OPENSSL or JDK. +# When using TLS authentication with KeyStore, available values can be SunJSSE, Conscrypt and etc. +tlsProvider= + ### --- KeyStore TLS config variables --- ### # Enable TLS with KeyStore type configuration in broker. tlsEnabledWithKeyStore=false -# TLS Provider for KeyStore type -tlsProvider= - # TLS KeyStore type configuration in broker: JKS, PKCS12 tlsKeyStoreType=JKS diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java index 3148f085b7fdb..f5b60893d6eda 100644 --- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java +++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java @@ -2478,7 +2478,9 @@ public class ServiceConfiguration implements PulsarConfiguration { @FieldContext( category = CATEGORY_KEYSTORE_TLS, - doc = "TLS Provider for KeyStore type" + doc = "TLS Provider for Specify the SSL provider for the broker service: \n" + + "When using TLS authentication with CACert, the valid value is either OPENSSL or JDK.\n" + + "When using TLS authentication with KeyStore, available values can be SunJSSE, Conscrypt and etc." ) private String tlsProvider = null; diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/PulsarChannelInitializer.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/PulsarChannelInitializer.java index 831e56f4f5d53..e75c518a50f02 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/PulsarChannelInitializer.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/PulsarChannelInitializer.java @@ -28,6 +28,7 @@ import io.netty.handler.flow.FlowControlHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; import java.net.SocketAddress; import java.util.concurrent.TimeUnit; import lombok.Builder; @@ -92,10 +93,18 @@ public PulsarChannelInitializer(PulsarService pulsar, PulsarChannelOptions opts) serviceConfig.getTlsProtocols(), serviceConfig.getTlsCertRefreshCheckDurationSec()); } else { - sslCtxRefresher = new NettyServerSslContextBuilder(serviceConfig.isTlsAllowInsecureConnection(), - serviceConfig.getTlsTrustCertsFilePath(), serviceConfig.getTlsCertificateFilePath(), + SslProvider sslProvider = null; + if (serviceConfig.getTlsProvider() != null) { + sslProvider = SslProvider.valueOf(serviceConfig.getTlsProvider()); + } + sslCtxRefresher = new NettyServerSslContextBuilder( + sslProvider, + serviceConfig.isTlsAllowInsecureConnection(), + serviceConfig.getTlsTrustCertsFilePath(), + serviceConfig.getTlsCertificateFilePath(), serviceConfig.getTlsKeyFilePath(), - serviceConfig.getTlsCiphers(), serviceConfig.getTlsProtocols(), + serviceConfig.getTlsCiphers(), + serviceConfig.getTlsProtocols(), serviceConfig.isTlsRequireTrustedClientCertOnConnect(), serviceConfig.getTlsCertRefreshCheckDurationSec()); } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnector.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnector.java index 3e17a38da2b34..1f302f6586cd5 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnector.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnector.java @@ -21,6 +21,7 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslProvider; import io.netty.util.concurrent.DefaultThreadFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -137,21 +138,32 @@ public boolean keepAlive(InetSocketAddress remoteAddress, Request ahcRequest, JsseSslEngineFactory sslEngineFactory = new JsseSslEngineFactory(sslCtx); confBuilder.setSslEngineFactory(sslEngineFactory); } else { + SslProvider sslProvider = null; + if (conf.getSslProvider() != null) { + sslProvider = SslProvider.valueOf(conf.getSslProvider()); + } SslContext sslCtx = null; if (authData.hasDataForTls()) { sslCtx = authData.getTlsTrustStoreStream() == null ? SecurityUtility.createAutoRefreshSslContextForClient( - conf.isTlsAllowInsecureConnection() || !conf.isTlsHostnameVerificationEnable(), - conf.getTlsTrustCertsFilePath(), authData.getTlsCerificateFilePath(), - authData.getTlsPrivateKeyFilePath(), null, autoCertRefreshTimeSeconds, delayer) + sslProvider, + conf.isTlsAllowInsecureConnection() || !conf.isTlsHostnameVerificationEnable(), + conf.getTlsTrustCertsFilePath(), authData.getTlsCerificateFilePath(), + authData.getTlsPrivateKeyFilePath(), null, autoCertRefreshTimeSeconds, delayer) : SecurityUtility.createNettySslContextForClient( - conf.isTlsAllowInsecureConnection() || !conf.isTlsHostnameVerificationEnable(), - authData.getTlsTrustStoreStream(), authData.getTlsCertificates(), - authData.getTlsPrivateKey()); + sslProvider, + conf.isTlsAllowInsecureConnection() || !conf.isTlsHostnameVerificationEnable(), + authData.getTlsTrustStoreStream(), authData.getTlsCertificates(), + authData.getTlsPrivateKey(), + conf.getTlsCiphers(), + conf.getTlsProtocols()); } else { sslCtx = SecurityUtility.createNettySslContextForClient( + sslProvider, conf.isTlsAllowInsecureConnection() || !conf.isTlsHostnameVerificationEnable(), - conf.getTlsTrustCertsFilePath()); + conf.getTlsTrustCertsFilePath(), + conf.getTlsCiphers(), + conf.getTlsProtocols()); } confBuilder.setSslContext(sslCtx); } diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpClient.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpClient.java index 15e07072d067e..eb988528cb555 100644 --- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpClient.java +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpClient.java @@ -22,12 +22,14 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslProvider; import java.io.Closeable; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; +import java.security.GeneralSecurityException; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -109,24 +111,33 @@ public boolean keepAlive(InetSocketAddress remoteAddress, Request ahcRequest, JsseSslEngineFactory sslEngineFactory = new JsseSslEngineFactory(sslCtx); confBuilder.setSslEngineFactory(sslEngineFactory); } else { + SslProvider sslProvider = null; + if (conf.getSslProvider() != null) { + sslProvider = SslProvider.valueOf(conf.getSslProvider()); + } SslContext sslCtx = null; if (authData.hasDataForTls()) { sslCtx = authData.getTlsTrustStoreStream() == null - ? SecurityUtility.createNettySslContextForClient(conf.isTlsAllowInsecureConnection(), - conf.getTlsTrustCertsFilePath(), authData.getTlsCertificates(), - authData.getTlsPrivateKey()) - : SecurityUtility.createNettySslContextForClient(conf.isTlsAllowInsecureConnection(), - authData.getTlsTrustStoreStream(), authData.getTlsCertificates(), - authData.getTlsPrivateKey()); + ? SecurityUtility.createNettySslContextForClient(sslProvider, + conf.isTlsAllowInsecureConnection(), + conf.getTlsTrustCertsFilePath(), authData.getTlsCertificates(), + authData.getTlsPrivateKey(), conf.getTlsCiphers(), conf.getTlsProtocols()) + : SecurityUtility.createNettySslContextForClient(sslProvider, + conf.isTlsAllowInsecureConnection(), + authData.getTlsTrustStoreStream(), authData.getTlsCertificates(), + authData.getTlsPrivateKey(), conf.getTlsCiphers(), conf.getTlsProtocols()); } else { sslCtx = SecurityUtility.createNettySslContextForClient( + sslProvider, conf.isTlsAllowInsecureConnection(), - conf.getTlsTrustCertsFilePath()); + conf.getTlsTrustCertsFilePath(), conf.getTlsCiphers(), conf.getTlsProtocols()); } confBuilder.setSslContext(sslCtx); } confBuilder.setUseInsecureTrustManager(conf.isTlsAllowInsecureConnection()); + } catch (GeneralSecurityException e) { + throw new PulsarClientException.InvalidConfigurationException(e); } catch (Exception e) { throw new PulsarClientException.InvalidConfigurationException(e); } diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/PulsarChannelInitializer.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/PulsarChannelInitializer.java index bf94da045f9bc..1899728b763ec 100644 --- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/PulsarChannelInitializer.java +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/PulsarChannelInitializer.java @@ -25,6 +25,7 @@ import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; import java.net.InetSocketAddress; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -92,19 +93,36 @@ public PulsarChannelInitializer(ClientConfigurationData conf, Supplier(() -> { try { + SslProvider sslProvider = null; + if (conf.getSslProvider() != null) { + sslProvider = SslProvider.valueOf(conf.getSslProvider()); + } + // Set client certificate if available AuthenticationDataProvider authData = conf.getAuthentication().getAuthData(); if (authData.hasDataForTls()) { return authData.getTlsTrustStoreStream() == null - ? SecurityUtility.createNettySslContextForClient(conf.isTlsAllowInsecureConnection(), - conf.getTlsTrustCertsFilePath(), - authData.getTlsCertificates(), authData.getTlsPrivateKey()) - : SecurityUtility.createNettySslContextForClient(conf.isTlsAllowInsecureConnection(), - authData.getTlsTrustStoreStream(), - authData.getTlsCertificates(), authData.getTlsPrivateKey()); + ? SecurityUtility.createNettySslContextForClient( + sslProvider, + conf.isTlsAllowInsecureConnection(), + conf.getTlsTrustCertsFilePath(), + authData.getTlsCertificates(), + authData.getTlsPrivateKey(), + conf.getTlsCiphers(), + conf.getTlsProtocols()) + : SecurityUtility.createNettySslContextForClient(sslProvider, + conf.isTlsAllowInsecureConnection(), + authData.getTlsTrustStoreStream(), + authData.getTlsCertificates(), authData.getTlsPrivateKey(), + conf.getTlsCiphers(), + conf.getTlsProtocols()); } else { - return SecurityUtility.createNettySslContextForClient(conf.isTlsAllowInsecureConnection(), - conf.getTlsTrustCertsFilePath()); + return SecurityUtility.createNettySslContextForClient( + sslProvider, + conf.isTlsAllowInsecureConnection(), + conf.getTlsTrustCertsFilePath(), + conf.getTlsCiphers(), + conf.getTlsProtocols()); } } catch (Exception e) { throw new RuntimeException("Failed to create TLS context", e); diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyClientSslContextRefresher.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyClientSslContextRefresher.java index 0016d98206e18..e1fef9aaa9b10 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyClientSslContextRefresher.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyClientSslContextRefresher.java @@ -19,10 +19,12 @@ package org.apache.pulsar.common.util; import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslProvider; import java.io.FileNotFoundException; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.cert.X509Certificate; +import java.util.Set; import javax.net.ssl.SSLException; import lombok.extern.slf4j.Slf4j; import org.apache.pulsar.client.api.AuthenticationDataProvider; @@ -33,15 +35,20 @@ @Slf4j public class NettyClientSslContextRefresher extends SslContextAutoRefreshBuilder { private volatile SslContext sslNettyContext; - private boolean tlsAllowInsecureConnection; + private final boolean tlsAllowInsecureConnection; protected final FileModifiedTimeUpdater tlsTrustCertsFilePath; protected final FileModifiedTimeUpdater tlsCertsFilePath; protected final FileModifiedTimeUpdater tlsPrivateKeyFilePath; - private AuthenticationDataProvider authData; + private final AuthenticationDataProvider authData; + private final SslProvider sslProvider; + private final Set ciphers; + private final Set protocols; - public NettyClientSslContextRefresher(boolean allowInsecure, + public NettyClientSslContextRefresher(SslProvider sslProvider, boolean allowInsecure, String trustCertsFilePath, AuthenticationDataProvider authData, + Set ciphers, + Set protocols, long delayInSeconds) throws IOException, GeneralSecurityException { super(delayInSeconds); @@ -52,6 +59,9 @@ public NettyClientSslContextRefresher(boolean allowInsecure, authData != null ? authData.getTlsCerificateFilePath() : null); this.tlsPrivateKeyFilePath = new FileModifiedTimeUpdater( authData != null ? authData.getTlsPrivateKeyFilePath() : null); + this.sslProvider = sslProvider; + this.ciphers = ciphers; + this.protocols = protocols; } @Override @@ -59,15 +69,16 @@ public synchronized SslContext update() throws SSLException, FileNotFoundException, GeneralSecurityException, IOException { if (authData != null && authData.hasDataForTls()) { this.sslNettyContext = authData.getTlsTrustStoreStream() == null - ? SecurityUtility.createNettySslContextForClient(this.tlsAllowInsecureConnection, - tlsTrustCertsFilePath.getFileName(), (X509Certificate[]) authData.getTlsCertificates(), - authData.getTlsPrivateKey()) - : SecurityUtility.createNettySslContextForClient(this.tlsAllowInsecureConnection, - authData.getTlsTrustStoreStream(), (X509Certificate[]) authData.getTlsCertificates(), - authData.getTlsPrivateKey()); + ? SecurityUtility.createNettySslContextForClient(this.sslProvider, this.tlsAllowInsecureConnection, + tlsTrustCertsFilePath.getFileName(), (X509Certificate[]) authData.getTlsCertificates(), + authData.getTlsPrivateKey(), this.ciphers, this.protocols) + : SecurityUtility.createNettySslContextForClient(this.sslProvider, this.tlsAllowInsecureConnection, + authData.getTlsTrustStoreStream(), (X509Certificate[]) authData.getTlsCertificates(), + authData.getTlsPrivateKey(), this.ciphers, this.protocols); } else { - this.sslNettyContext = SecurityUtility.createNettySslContextForClient(this.tlsAllowInsecureConnection, - this.tlsTrustCertsFilePath.getFileName()); + this.sslNettyContext = + SecurityUtility.createNettySslContextForClient(this.sslProvider, this.tlsAllowInsecureConnection, + this.tlsTrustCertsFilePath.getFileName(), this.ciphers, this.protocols); } return this.sslNettyContext; } diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyServerSslContextBuilder.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyServerSslContextBuilder.java index 250e628f0def7..e9fbb1f5e3ecf 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyServerSslContextBuilder.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/NettyServerSslContextBuilder.java @@ -19,6 +19,7 @@ package org.apache.pulsar.common.util; import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslProvider; import java.io.FileNotFoundException; import java.io.IOException; import java.security.GeneralSecurityException; @@ -36,8 +37,10 @@ public class NettyServerSslContextBuilder extends SslContextAutoRefreshBuilder tlsCiphers; protected final Set tlsProtocols; protected final boolean tlsRequireTrustedClientCertOnConnect; + protected final SslProvider sslProvider; - public NettyServerSslContextBuilder(boolean allowInsecure, String trustCertsFilePath, String certificateFilePath, + public NettyServerSslContextBuilder(SslProvider sslProvider, boolean allowInsecure, String trustCertsFilePath, + String certificateFilePath, String keyFilePath, Set ciphers, Set protocols, boolean requireTrustedClientCertOnConnect, long delayInSeconds) { @@ -49,14 +52,17 @@ public NettyServerSslContextBuilder(boolean allowInsecure, String trustCertsFile this.tlsCiphers = ciphers; this.tlsProtocols = protocols; this.tlsRequireTrustedClientCertOnConnect = requireTrustedClientCertOnConnect; + this.sslProvider = sslProvider; } @Override public synchronized SslContext update() - throws SSLException, FileNotFoundException, GeneralSecurityException, IOException { - this.sslNettyContext = SecurityUtility.createNettySslContextForServer(tlsAllowInsecureConnection, - tlsTrustCertsFilePath.getFileName(), tlsCertificateFilePath.getFileName(), tlsKeyFilePath.getFileName(), - tlsCiphers, tlsProtocols, tlsRequireTrustedClientCertOnConnect); + throws SSLException, FileNotFoundException, GeneralSecurityException, IOException { + this.sslNettyContext = + SecurityUtility.createNettySslContextForServer(this.sslProvider, tlsAllowInsecureConnection, + tlsTrustCertsFilePath.getFileName(), tlsCertificateFilePath.getFileName(), + tlsKeyFilePath.getFileName(), + tlsCiphers, tlsProtocols, tlsRequireTrustedClientCertOnConnect); return this.sslNettyContext; } diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java index a1f4350b1d155..4560113ff6728 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java @@ -21,6 +21,7 @@ import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import java.io.BufferedReader; import java.io.File; @@ -200,10 +201,13 @@ public static SSLContext createSslContext(boolean allowInsecureConnection, Certi return createSslContext(allowInsecureConnection, trustCertificates, (Certificate[]) null, (PrivateKey) null); } - public static SslContext createNettySslContextForClient(boolean allowInsecureConnection, String trustCertsFilePath) + public static SslContext createNettySslContextForClient(SslProvider sslProvider, boolean allowInsecureConnection, + String trustCertsFilePath, Set ciphers, + Set protocols) throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { - return createNettySslContextForClient(allowInsecureConnection, trustCertsFilePath, (Certificate[]) null, - (PrivateKey) null); + return createNettySslContextForClient(sslProvider, allowInsecureConnection, trustCertsFilePath, + (Certificate[]) null, + (PrivateKey) null, ciphers, protocols); } public static SSLContext createSslContext(boolean allowInsecureConnection, String trustCertsFilePath, @@ -229,12 +233,15 @@ public static SSLContext createSslContext(boolean allowInsecureConnection, Strin * @throws FileNotFoundException * @throws IOException */ - public static SslContext createAutoRefreshSslContextForClient(boolean allowInsecureConnection, - String trustCertsFilePath, String certFilePath, String keyFilePath, String sslContextAlgorithm, - int refreshDurationSec, ScheduledExecutorService executor) + public static SslContext createAutoRefreshSslContextForClient(SslProvider sslProvider, + boolean allowInsecureConnection, + String trustCertsFilePath, String certFilePath, + String keyFilePath, String sslContextAlgorithm, + int refreshDurationSec, + ScheduledExecutorService executor) throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { KeyManagerProxy keyManager = new KeyManagerProxy(certFilePath, keyFilePath, refreshDurationSec, executor); - SslContextBuilder sslContexBuilder = SslContextBuilder.forClient(); + SslContextBuilder sslContexBuilder = SslContextBuilder.forClient().sslProvider(sslProvider); sslContexBuilder.keyManager(keyManager); if (allowInsecureConnection) { sslContexBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); @@ -245,46 +252,62 @@ public static SslContext createAutoRefreshSslContextForClient(boolean allowInsec return sslContexBuilder.build(); } - public static SslContext createNettySslContextForClient(boolean allowInsecureConnection, String trustCertsFilePath, - String certFilePath, String keyFilePath) + public static SslContext createNettySslContextForClient(SslProvider sslProvider, boolean allowInsecureConnection, + String trustCertsFilePath, + String certFilePath, String keyFilePath, + Set ciphers, + Set protocols) throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { X509Certificate[] certificates = loadCertificatesFromPemFile(certFilePath); PrivateKey privateKey = loadPrivateKeyFromPemFile(keyFilePath); - return createNettySslContextForClient(allowInsecureConnection, trustCertsFilePath, certificates, privateKey); + return createNettySslContextForClient(sslProvider, allowInsecureConnection, trustCertsFilePath, certificates, + privateKey, ciphers, protocols); } - public static SslContext createNettySslContextForClient(boolean allowInsecureConnection, String trustCertsFilePath, - Certificate[] certificates, PrivateKey privateKey) + public static SslContext createNettySslContextForClient(SslProvider sslProvider, boolean allowInsecureConnection, + String trustCertsFilePath, + Certificate[] certificates, PrivateKey privateKey, + Set ciphers, + Set protocols) throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { if (StringUtils.isNotBlank(trustCertsFilePath)) { try (FileInputStream trustCertsStream = new FileInputStream(trustCertsFilePath)) { - return createNettySslContextForClient(allowInsecureConnection, trustCertsStream, certificates, - privateKey); + return createNettySslContextForClient(sslProvider, allowInsecureConnection, trustCertsStream, + certificates, + privateKey, ciphers, protocols); } } else { - return createNettySslContextForClient(allowInsecureConnection, (InputStream) null, certificates, - privateKey); + return createNettySslContextForClient(sslProvider, allowInsecureConnection, (InputStream) null, + certificates, + privateKey, ciphers, protocols); } } - public static SslContext createNettySslContextForClient(boolean allowInsecureConnection, - InputStream trustCertsStream, Certificate[] certificates, PrivateKey privateKey) + public static SslContext createNettySslContextForClient(SslProvider sslProvider, boolean allowInsecureConnection, + InputStream trustCertsStream, Certificate[] certificates, + PrivateKey privateKey, Set ciphers, + Set protocols) throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { - SslContextBuilder builder = SslContextBuilder.forClient(); + SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(sslProvider); setupTrustCerts(builder, allowInsecureConnection, trustCertsStream); setupKeyManager(builder, privateKey, (X509Certificate[]) certificates); + setupCiphers(builder, ciphers); + setupProtocols(builder, protocols); return builder.build(); } - public static SslContext createNettySslContextForServer(boolean allowInsecureConnection, String trustCertsFilePath, - String certFilePath, String keyFilePath, Set ciphers, Set protocols, - boolean requireTrustedClientCertOnConnect) + public static SslContext createNettySslContextForServer(SslProvider sslProvider, boolean allowInsecureConnection, + String trustCertsFilePath, + String certFilePath, String keyFilePath, + Set ciphers, Set protocols, + boolean requireTrustedClientCertOnConnect) throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { X509Certificate[] certificates = loadCertificatesFromPemFile(certFilePath); PrivateKey privateKey = loadPrivateKeyFromPemFile(keyFilePath); - SslContextBuilder builder = SslContextBuilder.forServer(privateKey, (X509Certificate[]) certificates); + SslContextBuilder builder = + SslContextBuilder.forServer(privateKey, (X509Certificate[]) certificates).sslProvider(sslProvider); setupCiphers(builder, ciphers); setupProtocols(builder, protocols); if (StringUtils.isNotBlank(trustCertsFilePath)) { diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/util/FileModifiedTimeUpdaterTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/util/FileModifiedTimeUpdaterTest.java index 8e6094e0eb087..0b093e7740014 100644 --- a/pulsar-common/src/test/java/org/apache/pulsar/common/util/FileModifiedTimeUpdaterTest.java +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/util/FileModifiedTimeUpdaterTest.java @@ -108,8 +108,8 @@ public void testNettyClientSslContextRefresher() throws Exception { createFile(Paths.get(certFile)); provider.certFilePath = certFile; provider.keyFilePath = certFile; - NettyClientSslContextRefresher refresher = new NettyClientSslContextRefresher(false, certFile, - provider, 1); + NettyClientSslContextRefresher refresher = new NettyClientSslContextRefresher(null, false, certFile, + provider, null, null, 1); Thread.sleep(5000); Paths.get(certFile).toFile().delete(); // update the file diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/util/netty/SslContextTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/util/netty/SslContextTest.java new file mode 100644 index 0000000000000..0fbd2521ae08d --- /dev/null +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/util/netty/SslContextTest.java @@ -0,0 +1,132 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.pulsar.common.util.netty; + +import static org.testng.Assert.assertThrows; +import com.google.common.io.Resources; +import io.netty.handler.ssl.SslProvider; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.HashSet; +import java.util.Set; +import javax.net.ssl.SSLException; +import org.apache.pulsar.client.api.AuthenticationDataProvider; +import org.apache.pulsar.client.api.KeyStoreParams; +import org.apache.pulsar.common.util.NettyClientSslContextRefresher; +import org.apache.pulsar.common.util.NettyServerSslContextBuilder; +import org.apache.pulsar.common.util.keystoretls.NettySSLContextAutoRefreshBuilder; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class SslContextTest { + @DataProvider(name = "caCertSslContextDataProvider") + public static Object[][] getSslContextDataProvider() { + Set ciphers = new HashSet<>(); + ciphers.add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"); + ciphers.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); + ciphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); + ciphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); + ciphers.add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"); + + // Note: OPENSSL doesn't support these ciphers. + return new Object[][]{ + new Object[]{SslProvider.JDK, ciphers}, + new Object[]{SslProvider.JDK, null}, + + new Object[]{SslProvider.OPENSSL, ciphers}, + new Object[]{SslProvider.OPENSSL, null}, + + new Object[]{null, ciphers}, + new Object[]{null, null}, + }; + } + + @DataProvider(name = "cipherDataProvider") + public static Object[] getCipher() { + Set cipher = new HashSet<>(); + cipher.add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"); + cipher.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); + cipher.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); + cipher.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); + cipher.add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"); + + return new Object[]{null, cipher}; + } + + @Test(dataProvider = "cipherDataProvider") + public void testServerKeyStoreSSLContext(Set cipher) throws Exception { + NettySSLContextAutoRefreshBuilder contextAutoRefreshBuilder = new NettySSLContextAutoRefreshBuilder(null, + "JKS", Resources.getResource("ssl/jetty_server_key.jks").getPath(), + "jetty_server_pwd", false, "JKS", + Resources.getResource("ssl/jetty_server_trust.jks").getPath(), + "jetty_server_pwd", true, cipher, + null, 600); + contextAutoRefreshBuilder.update(); + } + + private static class ClientAuthenticationData implements AuthenticationDataProvider { + @Override + public KeyStoreParams getTlsKeyStoreParams() { + return null; + } + } + + @Test(dataProvider = "cipherDataProvider") + public void testClientKeyStoreSSLContext(Set cipher) throws Exception { + NettySSLContextAutoRefreshBuilder contextAutoRefreshBuilder = new NettySSLContextAutoRefreshBuilder(null, + false, "JKS", Resources.getResource("ssl/jetty_server_trust.jks").getPath(), + "jetty_server_pwd", cipher, null, 0, new ClientAuthenticationData()); + contextAutoRefreshBuilder.update(); + } + + @Test(dataProvider = "caCertSslContextDataProvider") + public void testServerCaCertSslContextWithSslProvider(SslProvider sslProvider, Set ciphers) + throws GeneralSecurityException, IOException { + NettyServerSslContextBuilder sslContext = new NettyServerSslContextBuilder(sslProvider, + true, Resources.getResource("ssl/my-ca/ca.pem").getPath(), + Resources.getResource("ssl/my-ca/server-ca.pem").getPath(), + Resources.getResource("ssl/my-ca/server-key.pem").getPath(), + ciphers, + null, + true, 60); + if (ciphers != null) { + if (sslProvider == null || sslProvider == SslProvider.OPENSSL) { + assertThrows(SSLException.class, sslContext::update); + return; + } + } + sslContext.update(); + } + + @Test(dataProvider = "caCertSslContextDataProvider") + public void testClientCaCertSslContextWithSslProvider(SslProvider sslProvider, Set ciphers) + throws GeneralSecurityException, IOException { + NettyClientSslContextRefresher sslContext = new NettyClientSslContextRefresher(sslProvider, + true, Resources.getResource("ssl/my-ca/ca.pem").getPath(), + null, ciphers, null, 0); + if (ciphers != null) { + if (sslProvider == null || sslProvider == SslProvider.OPENSSL) { + assertThrows(SSLException.class, sslContext::update); + return; + } + } + sslContext.update(); + } +} diff --git a/pulsar-common/src/test/resources/ssl/my-ca/ca.pem b/pulsar-common/src/test/resources/ssl/my-ca/ca.pem new file mode 100644 index 0000000000000..3d5a80e234784 --- /dev/null +++ b/pulsar-common/src/test/resources/ssl/my-ca/ca.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC9DCCAdygAwIBAgIUNbNkV2+K2Hf4Q1V5gdAENZQiLokwDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAxMGUHVsc2FyMCAXDTIyMDExNDA0MjgwMFoYDzIxMjIwMTE2 +MDQyODAwWjARMQ8wDQYDVQQDEwZQdWxzYXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDBR2K5EKVziLqdsz78efEW4lOwKiJ32e97uxn1Z6oKgkgImpVP +Z9aoJB4EwSnDg+6FV2YULdWPm7C6W33tDmWRaU/Hlo/cOejnK8UmiMu/EyDpE2Wj +n0RimGmwOkBi2IWIcIzWMmPDZ9kZc65OUeEmwZedKRy62PQyfCeNU4OOHQn3PXjI +NbXJZD5TvBmn4SJn2RP9EgmIPaBAh/Mng045ZeHHLhwMKC8EOyHc2aB7AL6brymR +xzsiYWdcJn4mqqMvT82mVvhkgAMOcR4CXYF8eYnsG6ZbDHb13CawcvLVREJZk7AB +XZi9Rd5xczxHILM8rdkIZfunaG1X5hbih5wJAgMBAAGjQjBAMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTCC1lYG+62cUPjNk9q4jCm +Ps65njANBgkqhkiG9w0BAQsFAAOCAQEAKV2Lpu5cH5EsG53EWsYxEKvuQZ0LTxCE +wCDf/NxJaQbzfv0tsbZatMge0vcZ/5r8tZZoOC+pGTwk6MaRbEFH8PmvlH1LIQvu +Y34/YQZOy8wBTWwaIfFMnYWc0iAFoFt2Lzuq+GOI+svTFp729Ae8r7UxY/f9Lioc +ttdGr7vA6PpcIMoEIPjVp+m41uL9IDfX8eOxg4gVlwtqpbHdTzMrOz0YY+3qH/WK +6Qffw4pwitzAEj2zCn2lvGC5cbpd13SAaqtB3xL/Aet0SS2r3g9qDo1RruQhXUng +06U/Hqtn5K1fNQv3pivi3Jg5z1DfJWHkH37luAoIlOZHRmPK6rhp/g== +-----END CERTIFICATE----- diff --git a/pulsar-common/src/test/resources/ssl/my-ca/client-ca.pem b/pulsar-common/src/test/resources/ssl/my-ca/client-ca.pem new file mode 100644 index 0000000000000..adcae3393ade1 --- /dev/null +++ b/pulsar-common/src/test/resources/ssl/my-ca/client-ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDHDCCAgSgAwIBAgIUJJpmKX3DnbUwJ7tUhCt8MTiwz0owDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAxMGUHVsc2FyMCAXDTIyMDExNDA0MjgwMFoYDzIxMjExMjIx +MDQyODAwWjARMQ8wDQYDVQQDEwZQdWxzYXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDZN+CNZ1i1WaXulbwSASOfXErWXhGV9DHqavPp3DohgQdundfS +648T/X80uWQlyxu4L4j0oc97jtzc1AyZFXj5nocVsveEO9aDjnYCc5NdBNJLQHgl +IO59fEpTd55NO24g9a8/sxgn0ADCenMlngk1Ou+2QJBONw7W12/WUSUg6ICe+b+x +qPzgApue16oGw9HxhPwa3oEvVZrEnFIWLjsSWtezhgFHMCH9/ngk0KlRyes/EZCz +ZgkO5mgii2fmNDg+yuWUfw7Q0x6BJskGIrxisJiJBRR1+DIvJqgqxJsNmeeEQrZK +YHBukj5RWDFOpOHgqFbPsv45sVKoLrGFrMnNAgMBAAGjajBoMA4GA1UdDwEB/wQE +AwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQW +BBSwkx93xjYP4I+dcFF3xS9NLesmFjAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJ +KoZIhvcNAQELBQADggEBAAK3ZF63w46pT76QIOeSM3ocUm6izvW/IrxLUESfgRC4 +gg0/5VfPiHHUe6orn15KuPXHe7xCUFqc2oFn5aIU1B/6iOPeNItvMJidU0a3UAiw +hFK9MSFgESNBiEnu1dE5tPcIIxTyCFQ/8loeY3dsdcNVoguH/2J9v/XcMMga46A1 +wudaaa1nb+ZYnXkRuyObKVJQN7EqC+4edinMOTPBbF9wtRMAMBRHXXENXb9zFthi +Dbdn4YvadYsNHxh5ar+hQn/HSPMuCUPY/uUqxtBagb6aS0YnSoUscSLs1Jizg5NX +d+QV8X/5E6W4xWnptUZwVxOemkdnr6A8MH1eQKKFZTM= +-----END CERTIFICATE----- diff --git a/pulsar-common/src/test/resources/ssl/my-ca/client-key.pem b/pulsar-common/src/test/resources/ssl/my-ca/client-key.pem new file mode 100644 index 0000000000000..5b08b151c8094 --- /dev/null +++ b/pulsar-common/src/test/resources/ssl/my-ca/client-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDZN+CNZ1i1WaXu +lbwSASOfXErWXhGV9DHqavPp3DohgQdundfS648T/X80uWQlyxu4L4j0oc97jtzc +1AyZFXj5nocVsveEO9aDjnYCc5NdBNJLQHglIO59fEpTd55NO24g9a8/sxgn0ADC +enMlngk1Ou+2QJBONw7W12/WUSUg6ICe+b+xqPzgApue16oGw9HxhPwa3oEvVZrE +nFIWLjsSWtezhgFHMCH9/ngk0KlRyes/EZCzZgkO5mgii2fmNDg+yuWUfw7Q0x6B +JskGIrxisJiJBRR1+DIvJqgqxJsNmeeEQrZKYHBukj5RWDFOpOHgqFbPsv45sVKo +LrGFrMnNAgMBAAECggEATeVZ45uiFja16J9NuG8sJSPluoY1bD8L/3KnUcAmIImy +7powIXVT8+k+StwI6/ywThbN2FyGmVqcHZz1f5hRr8KH0uJBHOyQetEFxM9Jk1v9 +Rfsymq36mImP5erJnAyp66vvUrqY+P4Ap71duam4x5wBBqyUk1fvPGA5vPOQiwHs +TN9JHizGobY25fpigWKIMamyE7HWXEUzVdOo83ZiNx53ths+WcF/kqto2v5LtyfJ +HgoPocfZI8tRz9tfgc8zOkvyjsvgdd6rLhd0r2oExnyQBJdktGFpQZMGambU328u +NqcdJscjP/HWAHRzuSdOvCMOEn8E5GIjcWEnQqOmSQKBgQDcpb655/UdcVxrv2Ou +8juucDJMpf6i/UcmlXVXx+3zGSuQZcCC2fupe3JcxPdK7bo65YlC3OoRihggh2sS +cnFMNHMfyoE3G/doXIr3QyL9UAQt4yb+7Nz7jRXYcg4Ytv+FVS6BSzIDEK17v+es +GuWDM3JwtigtzYS4tRh7lgmuBwKBgQD8BXp7yIyVv657B8OJJSoeGataziFPhZux +WKoS3gq24169ZWXwLc+nwrdgvBNrRaHuX+cYh93RF9+2WZrRcRL41XqN938adasY +zPsfOJa9IOgUzQtGUMSe1/WqvHfcvqZCqYq4u/LSdf+I67woP4tCqqn4E928aIZb +6PjLH+dUiwKBgH1ntn7y1t1lEKIspPtJsaHzIqNttMvuKAJF7+t0Nkl0hM4NBt1Y +BzDMeLNBP0vW0YGn89uMs3xEgHH8hV52rO4i4UuwTMCFpJgsAM+H2NsgHz/1WrSI +6xANn9zk9h4V5CRjxYq2sjYLxI4RBBtNLiTjmKd24F8n78cLJl8XZ2kBAoGAGoHF +ATH1v2ZaxqvpYApdpK7UfAeEL2YBGyUVNkjOXbAKbec1Uo6u8ZkkSnNdo4G+Z2EE +4Gqh5PUa3YYNJ4w6D5v8eOQYJUNNDJ26p+z+xcOpRU7PqcSi+YYDW8LY5InU2NwW +MBnsj0BD8TXCI4WTcx6aI/KK9t8TiqU1Tb/8R8MCgYANVinOLz2enB+Qzu4o88W/ +witKHI3D9+z/uWjp0Q4rwmr3OL4FD9vZWvL4qwbDgpfLirJ4e3UVfN1/FoytAKlk +Kykf8oDWciCIdxStt/yUpgQv78IL3vM5d9B8Qb7KCRtJ0BIXGJ7Gle3xJeuduZLe ++F+hwI3Dpv5HPqa9o6ttJw== +-----END PRIVATE KEY----- diff --git a/pulsar-common/src/test/resources/ssl/my-ca/server-ca.pem b/pulsar-common/src/test/resources/ssl/my-ca/server-ca.pem new file mode 100644 index 0000000000000..df5f69298e258 --- /dev/null +++ b/pulsar-common/src/test/resources/ssl/my-ca/server-ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDHDCCAgSgAwIBAgIUVQHD0/oi9Ca50HA7DFLYOO2wEzYwDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAxMGUHVsc2FyMCAXDTIyMDExNDA0MjgwMFoYDzIxMjExMjIx +MDQyODAwWjARMQ8wDQYDVQQDEwZQdWxzYXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDBcqDkMhjLd9ik//UQijqbajQP5t6dvVZNn9gODQrS9oB/URur +NzCcPWYPJZfEJlTkV8mlmgq4dBjwghpy5ALOGiERk55JPIN4cy01hQ6j7YSPFvMv +BjqZvm5dpGDNTr7GY7THegMM1wpk9EaUOm7tBOHtf6ZnANjSMcQM74RCSBt0Koqw +06CKVDCbgJ5NNE1LgwYeVQAwtQAhY8rqqQKJvCorFbq7OiisFBnz5pRBT6N4kMo1 +9LZo3Oe2F2w9eH9vacQ0NjSOCNXqal9Xl/Pwy9JgKKppwZ/3nCgRc+yfjrnkRz0f +b+llb2NpR5Ge+tNMakqelE8bDSw/5BPjRPftAgMBAAGjajBoMA4GA1UdDwEB/wQE +AwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQW +BBRXws5mmLbW+xOLflUyUZ0I0uN96zAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJ +KoZIhvcNAQELBQADggEBAKMklpYJIkp4icz9Ea5wWQiRXWb94lGdyCA833VHeGB2 +fKvNXj1d6lEiy26pOjhDmycroKelj70WqOsqVgi4xh4Y9sj6pwb8Q423Tu3qNO1k +qaScTar2DANSigNzqlSbLshPWQ2ZyDwkvZPuqPgHzOXekzbUGwxgCiySaQkl2mCS +mBaG3XnESwiMIKkLphEv0MAvTVaImbSRWYEQ4OECwcHXxx+14wK8NLcdDIHcSzki +8Eq24CxDOeL5QxciGMi5tylsdCpT+D/BXTKiu46yoRjXUsTLYL53yUZZIqQ3A4CV +enZ/vHhP0Ev9RcRigFTqrBm7EC3b2AUpvqgRMnPwQZo= +-----END CERTIFICATE----- diff --git a/pulsar-common/src/test/resources/ssl/my-ca/server-key.pem b/pulsar-common/src/test/resources/ssl/my-ca/server-key.pem new file mode 100644 index 0000000000000..a3f3a36b73c37 --- /dev/null +++ b/pulsar-common/src/test/resources/ssl/my-ca/server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBcqDkMhjLd9ik +//UQijqbajQP5t6dvVZNn9gODQrS9oB/URurNzCcPWYPJZfEJlTkV8mlmgq4dBjw +ghpy5ALOGiERk55JPIN4cy01hQ6j7YSPFvMvBjqZvm5dpGDNTr7GY7THegMM1wpk +9EaUOm7tBOHtf6ZnANjSMcQM74RCSBt0Koqw06CKVDCbgJ5NNE1LgwYeVQAwtQAh +Y8rqqQKJvCorFbq7OiisFBnz5pRBT6N4kMo19LZo3Oe2F2w9eH9vacQ0NjSOCNXq +al9Xl/Pwy9JgKKppwZ/3nCgRc+yfjrnkRz0fb+llb2NpR5Ge+tNMakqelE8bDSw/ +5BPjRPftAgMBAAECggEBAJm2JsgMUo1ihn/dbnIdFCKoCgRUs7FtYCVADOJlVKN7 +AXGpFi4/JV4Qn4cLnQNcXfovE2iF9VzJy4NYLgH60YvJUVtxC8Yv0lukUVkEiDST +p9A3MTa9YVUG7xVzZwPcPVTQpzYV6lSKjpTXUTm5EKk/RvJ7itKv5plmt9x7eYFb +/JwqXo1Z6C4gfIFR85LWmrCsNUK5T9oooLz88D6+ZH3+fWlr75RDff2kqdLshMTs +N0Ov7NXcRFeruFs/IPrgTxjBMeNa2LFdYVPeeQ41L4uOI49uVBAmSn1be+THvDoj +Do+6wTEF/h6/VLoOaIFZZdHlqd4is+xcEg8gwVkCn2ECgYEAxqVvGKc9qaqEVwBx +U5Ru9OFx0NqEBvkYZRbCg1REcMFd3lqFTHvHiF3pmCp0XgLJKYuy42618IJXhj6D +Y15/p9jX0025MpnH/AdwpO6x5pv6gb/JOMnHOnq8sI3R+V6TVsv1WZj0sOj94mF0 ++Od++bQkUnSlfE4X7v+cJfo/Q8UCgYEA+Uz1yOyI9Dv1dEdBMdBA8MTriYU0uJCV +dVKzL/uC9XyguVBWu1HX0MvEKyjPRycvLB7TuQqAFLgCtC8EEuPGBpWtyXOm9Jxw +ToCfUZFuBQeMuf4vZcFgJjiEKTdKBxrvjkhyIhPR6JAy0WUr8Ry+ZtqvmG5NOEz5 +ptm1tznYngkCgYEAlckeyV8p/uqF2biKu3QcamgoU0zB6yQfAfK0fySmasNTzZtC +EhbvsOLnhgbVMiI1ny8ol5fedtlBuAchOWeDKIQ40as0r3QHuQG/LY6S9Im+zeFY +kIqNwInWB+cYYkmvHe6zNXlBYLh+4BmOgzTDqPPtw4MTWXTlVSDGlFhrJeUCgYBX +7rlS4Xt9ChkNpoRsWZROWGbr3rw1zWmqND1X01Lh28+lDZ1J/RguYXET+BUEd+G/ +oi/zuKxsomrxuxOoxgZ3FBx0TgK5jORgDCYl0zIHPB57DBkTvx123cBf+Ux3LR0K +BqubMXp8mUATc6gIJ6dRCBmfnmhGT4BPRcM+mXy6YQKBgGEGH37VABus+Oi3g1bk +qEAaUI1asRLJIfbY2ImxEroLIQAbTFuIQUsZTKpT7jJZubjYvy1Fev0LU/n7Kv2w +7ym41z70ro5uxwUBfJjnF3RtgncNcftn4b3siNzvBfKEBuhegMeS5YAbBIwABUpR +4mVpm9BLOiX4yENIT6JdUQFc +-----END PRIVATE KEY----- diff --git a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyConfiguration.java b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyConfiguration.java index 0affe1d126ef1..e387401dc612a 100644 --- a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyConfiguration.java +++ b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyConfiguration.java @@ -469,7 +469,9 @@ public class ProxyConfiguration implements PulsarConfiguration { @FieldContext( category = CATEGORY_KEYSTORE_TLS, - doc = "TLS Provider" + doc = "Specify the TLS provider for the broker service: \n" + + "When using TLS authentication with CACert, the valid value is either OPENSSL or JDK.\n" + + "When using TLS authentication with KeyStore, available values can be SunJSSE, Conscrypt and etc." ) private String tlsProvider = null; diff --git a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ServiceChannelInitializer.java b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ServiceChannelInitializer.java index e78db847658bb..e5f15b66d31cc 100644 --- a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ServiceChannelInitializer.java +++ b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ServiceChannelInitializer.java @@ -24,6 +24,7 @@ import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslProvider; import io.netty.handler.timeout.ReadTimeoutHandler; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -77,7 +78,13 @@ public ServiceChannelInitializer(ProxyService proxyService, ProxyConfiguration s serviceConfig.getTlsProtocols(), serviceConfig.getTlsCertRefreshCheckDurationSec()); } else { - serverSslCtxRefresher = new NettyServerSslContextBuilder(serviceConfig.isTlsAllowInsecureConnection(), + SslProvider sslProvider = null; + if (serviceConfig.getTlsProvider() != null) { + sslProvider = SslProvider.valueOf(serviceConfig.getTlsProvider()); + } + serverSslCtxRefresher = new NettyServerSslContextBuilder( + sslProvider, + serviceConfig.isTlsAllowInsecureConnection(), serviceConfig.getTlsTrustCertsFilePath(), serviceConfig.getTlsCertificateFilePath(), serviceConfig.getTlsKeyFilePath(), serviceConfig.getTlsCiphers(), serviceConfig.getTlsProtocols(), @@ -108,11 +115,19 @@ public ServiceChannelInitializer(ProxyService proxyService, ProxyConfiguration s serviceConfig.getTlsCertRefreshCheckDurationSec(), authData); } else { + SslProvider sslProvider = null; + if (serviceConfig.getBrokerClientSslProvider() != null) { + sslProvider = SslProvider.valueOf(serviceConfig.getBrokerClientSslProvider()); + } clientSslCtxRefresher = new NettyClientSslContextRefresher( + sslProvider, serviceConfig.isTlsAllowInsecureConnection(), serviceConfig.getBrokerClientTrustCertsFilePath(), authData, - serviceConfig.getTlsCertRefreshCheckDurationSec()); + serviceConfig.getBrokerClientTlsCiphers(), + serviceConfig.getBrokerClientTlsProtocols(), + serviceConfig.getTlsCertRefreshCheckDurationSec() + ); } } else { this.clientSslCtxRefresher = null;