You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by pe...@apache.org on 2022/04/21 03:09:11 UTC
[pulsar] branch branch-2.9 updated: [branch-2.9][broker] Full-support set ssl provider, ciphers and protocols (#15226)
This is an automated email from the ASF dual-hosted git repository.
penghui pushed a commit to branch branch-2.9
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/branch-2.9 by this push:
new 6b6a32d6cb1 [branch-2.9][broker] Full-support set ssl provider, ciphers and protocols (#15226)
6b6a32d6cb1 is described below
commit 6b6a32d6cb1f6f11d5c7e82cffd30a64ee11492e
Author: Zixuan Liu <no...@gmail.com>
AuthorDate: Thu Apr 21 11:09:05 2022 +0800
[branch-2.9][broker] Full-support set ssl provider, ciphers and protocols (#15226)
---
conf/broker.conf | 8 +-
conf/standalone.conf | 8 +-
.../apache/pulsar/broker/ServiceConfiguration.java | 4 +-
.../broker/service/PulsarChannelInitializer.java | 15 ++-
.../admin/internal/http/AsyncHttpConnector.java | 26 ++--
.../org/apache/pulsar/client/impl/HttpClient.java | 38 +++---
.../client/impl/PulsarChannelInitializer.java | 47 +++++---
.../util/NettyClientSslContextRefresher.java | 43 +++++--
.../common/util/NettyServerSslContextBuilder.java | 16 ++-
.../apache/pulsar/common/util/SecurityUtility.java | 71 +++++++----
.../pulsar/common/util/netty/SslContextTest.java | 132 +++++++++++++++++++++
.../src/test/resources/ssl/jetty_client_key.jks | Bin 0 -> 2679 bytes
.../src/test/resources/ssl/jetty_client_trust.jks | Bin 0 -> 1207 bytes
.../src/test/resources/ssl/jetty_server_key.jks | Bin 0 -> 2679 bytes
.../src/test/resources/ssl/jetty_server_trust.jks | Bin 0 -> 1207 bytes
pulsar-common/src/test/resources/ssl/my-ca/ca.pem | 18 +++
.../src/test/resources/ssl/my-ca/client-ca.pem | 19 +++
.../src/test/resources/ssl/my-ca/client-key.pem | 28 +++++
.../src/test/resources/ssl/my-ca/server-ca.pem | 19 +++
.../src/test/resources/ssl/my-ca/server-key.pem | 28 +++++
.../pulsar/proxy/server/ProxyConfiguration.java | 4 +-
.../proxy/server/ServiceChannelInitializer.java | 19 ++-
22 files changed, 452 insertions(+), 91 deletions(-)
diff --git a/conf/broker.conf b/conf/broker.conf
index e36892e3584..849121f9fe8 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 577a6ffad42..16312125a02 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 fa8464376fc..1e7eac5ef9a 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 831e56f4f5d..e75c518a50f 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.codec.LengthFieldBasedFrameDecoder;
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 class PulsarChannelInitializer extends ChannelInitializer<SocketChannel>
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 3e17a38da2b..1f302f6586c 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 @@ package org.apache.pulsar.client.admin.internal.http;
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 class AsyncHttpConnector implements Connector {
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 c295975ecd3..2a7e434cd38 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 class HttpClient implements Closeable {
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 b7a5fbadb42..497793d792d 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.protocol.Commands;
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<SocketChannel> {
@@ -93,19 +93,36 @@ public class PulsarChannelInitializer extends ChannelInitializer<SocketChannel>
sslContextSupplier = new ObjectCache<SslContext>(() -> {
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 560746df7f6..e1fef9aaa9b 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 @@ import org.apache.pulsar.client.api.AuthenticationDataProvider;
@Slf4j
public class NettyClientSslContextRefresher extends SslContextAutoRefreshBuilder<SslContext> {
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<String> ciphers;
+ private final Set<String> protocols;
- public NettyClientSslContextRefresher(boolean allowInsecure,
+ public NettyClientSslContextRefresher(SslProvider sslProvider, boolean allowInsecure,
String trustCertsFilePath,
AuthenticationDataProvider authData,
+ Set<String> ciphers,
+ Set<String> 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 class NettyClientSslContextRefresher extends SslContextAutoRefreshBuilder
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 class NettyClientSslContextRefresher extends SslContextAutoRefreshBuilder
@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 250e628f0de..e9fbb1f5e3e 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<S
protected final Set<String> tlsCiphers;
protected final Set<String> 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<String> ciphers, Set<String> protocols,
boolean requireTrustedClientCertOnConnect,
long delayInSeconds) {
@@ -49,14 +52,17 @@ public class NettyServerSslContextBuilder extends SslContextAutoRefreshBuilder<S
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 db8f861c789..d5a0c5a5767 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 @@ package org.apache.pulsar.common.util;
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 class SecurityUtility {
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 class SecurityUtility {
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<String> ciphers,
+ Set<String> 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 class SecurityUtility {
* @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 class SecurityUtility {
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<String> ciphers,
+ Set<String> 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<String> ciphers,
+ Set<String> 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<String> ciphers,
+ Set<String> 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<String> ciphers, Set<String> protocols,
- boolean requireTrustedClientCertOnConnect)
+ public static SslContext createNettySslContextForServer(SslProvider sslProvider, boolean allowInsecureConnection,
+ String trustCertsFilePath,
+ String certFilePath, String keyFilePath,
+ Set<String> ciphers, Set<String> 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 00000000000..0fbd2521ae0
--- /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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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 00000000000..2b8ea64347d
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 00000000000..166a2e00fb3
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 00000000000..b6189b75c8a
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 00000000000..b09cc030a71
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 00000000000..3d5a80e2347
--- /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 00000000000..adcae3393ad
--- /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 00000000000..5b08b151c80
--- /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 00000000000..df5f69298e2
--- /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 00000000000..a3f3a36b73c
--- /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 0231251e3f7..a29158f3902 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 a033a87912d..12abf871b50 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 @@ package org.apache.pulsar.proxy.server;
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 class ServiceChannelInitializer extends ChannelInitializer<SocketChannel>
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 class ServiceChannelInitializer extends ChannelInitializer<SocketChannel>
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;