diff --git a/conf/broker.conf b/conf/broker.conf index e36892e358427..849121f9fe8c9 100644 --- a/conf/broker.conf +++ b/conf/broker.conf @@ -594,13 +594,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 577a6ffad42cd..16312125a0254 100644 --- a/conf/standalone.conf +++ b/conf/standalone.conf @@ -357,13 +357,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 fa8464376fce6..1e7eac5ef9a1a 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 @@ -2237,7 +2237,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 c295975ecd36a..2a7e434cd3885 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 @@ -18,24 +18,24 @@ */ package org.apache.pulsar.client.impl; +import io.netty.channel.EventLoopGroup; +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; import java.util.concurrent.CompletableFuture; - -import io.netty.channel.EventLoopGroup; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.ssl.SslContext; import javax.net.ssl.SSLContext; import lombok.extern.slf4j.Slf4j; - import org.apache.pulsar.PulsarVersion; import org.apache.pulsar.client.api.Authentication; import org.apache.pulsar.client.api.AuthenticationDataProvider; @@ -111,25 +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()); - } - else { + ? 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 b7a5fbadb4237..497793d792d8e 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 @@ -18,6 +18,13 @@ */ package org.apache.pulsar.client.impl; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.SocketChannel; +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 java.net.InetSocketAddress; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -36,13 +43,6 @@ import org.apache.pulsar.common.util.SecurityUtility; import org.apache.pulsar.common.util.keystoretls.NettySSLContextAutoRefreshBuilder; -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslHandler; - @Slf4j public class PulsarChannelInitializer extends ChannelInitializer { @@ -93,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 560746df7f608..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,19 +35,33 @@ @Slf4j public class NettyClientSslContextRefresher extends SslContextAutoRefreshBuilder { private volatile SslContext sslNettyContext; - private boolean tlsAllowInsecureConnection; + private final boolean tlsAllowInsecureConnection; protected final FileModifiedTimeUpdater tlsTrustCertsFilePath; - private AuthenticationDataProvider authData; + protected final FileModifiedTimeUpdater tlsCertsFilePath; + protected final FileModifiedTimeUpdater tlsPrivateKeyFilePath; + 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); this.tlsAllowInsecureConnection = allowInsecure; this.tlsTrustCertsFilePath = new FileModifiedTimeUpdater(trustCertsFilePath); this.authData = authData; + this.tlsCertsFilePath = new FileModifiedTimeUpdater( + authData != null ? authData.getTlsCerificateFilePath() : null); + this.tlsPrivateKeyFilePath = new FileModifiedTimeUpdater( + authData != null ? authData.getTlsPrivateKeyFilePath() : null); + this.sslProvider = sslProvider; + this.ciphers = ciphers; + this.protocols = protocols; } @Override @@ -53,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; } @@ -73,6 +90,8 @@ public SslContext getSslContext() { @Override public boolean needUpdate() { - return tlsTrustCertsFilePath.checkAndRefresh(); + return tlsTrustCertsFilePath.checkAndRefresh() || tlsCertsFilePath.checkAndRefresh() + || tlsPrivateKeyFilePath.checkAndRefresh(); + } } 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 db8f861c789a3..d5a0c5a576722 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; @@ -111,7 +112,7 @@ public static Provider getProvider() { return getBCProviderFromClassPath(); } catch (Exception e) { log.warn("Not able to get Bouncy Castle provider for both FIPS and Non-FIPS from class path:", e); - throw new RuntimeException(e); + return null; } } @@ -201,10 +202,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, @@ -230,12 +234,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); @@ -246,46 +253,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/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/jetty_client_key.jks b/pulsar-common/src/test/resources/ssl/jetty_client_key.jks new file mode 100644 index 0000000000000..2b8ea64347ddc Binary files /dev/null and b/pulsar-common/src/test/resources/ssl/jetty_client_key.jks differ diff --git a/pulsar-common/src/test/resources/ssl/jetty_client_trust.jks b/pulsar-common/src/test/resources/ssl/jetty_client_trust.jks new file mode 100644 index 0000000000000..166a2e00fb371 Binary files /dev/null and b/pulsar-common/src/test/resources/ssl/jetty_client_trust.jks differ diff --git a/pulsar-common/src/test/resources/ssl/jetty_server_key.jks b/pulsar-common/src/test/resources/ssl/jetty_server_key.jks new file mode 100644 index 0000000000000..b6189b75c8ad0 Binary files /dev/null and b/pulsar-common/src/test/resources/ssl/jetty_server_key.jks differ diff --git a/pulsar-common/src/test/resources/ssl/jetty_server_trust.jks b/pulsar-common/src/test/resources/ssl/jetty_server_trust.jks new file mode 100644 index 0000000000000..b09cc030a71c3 Binary files /dev/null and b/pulsar-common/src/test/resources/ssl/jetty_server_trust.jks differ 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 0231251e3f79c..a29158f39026c 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 @@ -410,7 +410,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 a033a87912d87..12abf871b5078 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 @@ -21,6 +21,7 @@ import static org.apache.commons.lang3.StringUtils.isEmpty; 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; @@ -79,7 +80,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(), serviceConfig.isTlsRequireTrustedClientCertOnConnect(), @@ -109,11 +116,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;