diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/WebService.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/WebService.java index 7e6b1636a5c442..e711c6c1d8d349 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/WebService.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/web/WebService.java @@ -30,7 +30,7 @@ import org.apache.pulsar.broker.PulsarServerException; import org.apache.pulsar.broker.PulsarService; import org.apache.pulsar.broker.ServiceConfiguration; -import org.apache.pulsar.common.util.SecurityUtility; +import org.apache.pulsar.common.util.jetty.JettySslContextFactory; import org.apache.pulsar.common.util.keystoretls.KeyStoreSSLContext; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; @@ -109,17 +109,23 @@ public WebService(PulsarService pulsar) throws PulsarServerException { config.getTlsTrustStore(), config.getTlsTrustStorePassword(), config.isTlsRequireTrustedClientCertOnConnect(), - config.getWebServiceTlsCiphers(), - config.getWebServiceTlsProtocols(), + config.getWebServiceTlsCiphers() != null ? config.getWebServiceTlsCiphers() : + config.getTlsCiphers(), + config.getWebServiceTlsProtocols() != null ? config.getWebServiceTlsProtocols() : + config.getTlsCiphers(), config.getTlsCertRefreshCheckDurationSec() ); } else { - sslCtxFactory = SecurityUtility.createSslContextFactory( + sslCtxFactory = JettySslContextFactory.createServerSslContext( config.isTlsAllowInsecureConnection(), config.getTlsTrustCertsFilePath(), config.getTlsCertificateFilePath(), config.getTlsKeyFilePath(), - config.isTlsRequireTrustedClientCertOnConnect(), true, + config.isTlsRequireTrustedClientCertOnConnect(), + config.getWebServiceTlsCiphers() != null ? config.getWebServiceTlsCiphers() : + config.getTlsCiphers(), + config.getWebServiceTlsProtocols() != null ? config.getWebServiceTlsProtocols() : + config.getTlsCiphers(), config.getTlsCertRefreshCheckDurationSec()); } httpsConnector = new PulsarServerConnector(server, 1, 1, sslCtxFactory); 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 a1f4350b1d1552..b6c647b31e690c 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 @@ -517,52 +517,4 @@ private static void setupClientAuthentication(SslContextBuilder builder, builder.clientAuth(ClientAuth.OPTIONAL); } } - - public static SslContextFactory createSslContextFactory(boolean tlsAllowInsecureConnection, - String tlsTrustCertsFilePath, String tlsCertificateFilePath, String tlsKeyFilePath, - boolean tlsRequireTrustedClientCertOnConnect, boolean autoRefresh, long certRefreshInSec) - throws GeneralSecurityException, SSLException, FileNotFoundException, IOException { - SslContextFactory sslCtxFactory = null; - if (autoRefresh) { - sslCtxFactory = new SslContextFactoryWithAutoRefresh(tlsAllowInsecureConnection, tlsTrustCertsFilePath, - tlsCertificateFilePath, tlsKeyFilePath, tlsRequireTrustedClientCertOnConnect, 0); - } else { - sslCtxFactory = new SslContextFactory(); - SSLContext sslCtx = createSslContext(tlsAllowInsecureConnection, tlsTrustCertsFilePath, - tlsCertificateFilePath, tlsKeyFilePath); - sslCtxFactory.setSslContext(sslCtx); - } - if (tlsRequireTrustedClientCertOnConnect) { - sslCtxFactory.setNeedClientAuth(true); - } else { - sslCtxFactory.setWantClientAuth(true); - } - sslCtxFactory.setTrustAll(true); - return sslCtxFactory; - } - - /** - * {@link SslContextFactory} that auto-refresh SSLContext. - */ - static class SslContextFactoryWithAutoRefresh extends SslContextFactory { - - private final DefaultSslContextBuilder sslCtxRefresher; - - public SslContextFactoryWithAutoRefresh(boolean tlsAllowInsecureConnection, String tlsTrustCertsFilePath, - String tlsCertificateFilePath, String tlsKeyFilePath, boolean tlsRequireTrustedClientCertOnConnect, - long certRefreshInSec) - throws SSLException, FileNotFoundException, GeneralSecurityException, IOException { - super(); - sslCtxRefresher = new DefaultSslContextBuilder(tlsAllowInsecureConnection, tlsTrustCertsFilePath, - tlsCertificateFilePath, tlsKeyFilePath, tlsRequireTrustedClientCertOnConnect, certRefreshInSec); - if (CONSCRYPT_PROVIDER != null) { - setProvider(CONSCRYPT_PROVIDER.getName()); - } - } - - @Override - public SSLContext getSslContext() { - return sslCtxRefresher.get(); - } - } } diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/jetty/JettySslContextFactory.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/jetty/JettySslContextFactory.java new file mode 100644 index 00000000000000..88b92ab3ea5c4b --- /dev/null +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/jetty/JettySslContextFactory.java @@ -0,0 +1,112 @@ +/** + * 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.jetty; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Set; +import javax.net.ssl.SSLContext; +import org.apache.pulsar.common.util.DefaultSslContextBuilder; +import org.apache.pulsar.common.util.SecurityUtility; +import org.apache.pulsar.common.util.SslContextAutoRefreshBuilder; +import org.apache.pulsar.common.util.keystoretls.NetSslContextBuilder; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public class JettySslContextFactory { + public static SslContextFactory.Server createServerSslContextWithKeystore(String sslProviderString, + String keyStoreTypeString, + String keyStore, + String keyStorePassword, + boolean allowInsecureConnection, + String trustStoreTypeString, + String trustStore, + String trustStorePassword, + boolean requireTrustedClientCertOnConnect, + Set ciphers, + Set protocols, + long certRefreshInSec){ + NetSslContextBuilder sslCtxRefresher = new NetSslContextBuilder( + sslProviderString, + keyStoreTypeString, + keyStore, + keyStorePassword, + allowInsecureConnection, + trustStoreTypeString, + trustStore, + trustStorePassword, + requireTrustedClientCertOnConnect, + certRefreshInSec); + + return new Server(sslProviderString, sslCtxRefresher, requireTrustedClientCertOnConnect, ciphers, protocols); + } + + public static SslContextFactory createServerSslContext(boolean tlsAllowInsecureConnection, + String tlsTrustCertsFilePath, + String tlsCertificateFilePath, + String tlsKeyFilePath, + boolean tlsRequireTrustedClientCertOnConnect, + Set ciphers, + Set protocols, + long certRefreshInSec) + throws GeneralSecurityException, IOException { + DefaultSslContextBuilder sslCtxRefresher = + new DefaultSslContextBuilder(tlsAllowInsecureConnection, tlsTrustCertsFilePath, + tlsCertificateFilePath, tlsKeyFilePath, tlsRequireTrustedClientCertOnConnect, certRefreshInSec); + + return new Server(null, sslCtxRefresher, tlsRequireTrustedClientCertOnConnect, ciphers, protocols); + } + + private static class Server extends SslContextFactory.Server { + private final SslContextAutoRefreshBuilder sslCtxRefresher; + + public Server(String sslProviderString, SslContextAutoRefreshBuilder sslCtxRefresher, + boolean requireTrustedClientCertOnConnect, Set ciphers, Set protocols) { + super(); + this.sslCtxRefresher = sslCtxRefresher; + + if (ciphers != null && ciphers.size() > 0) { + this.setIncludeCipherSuites(ciphers.toArray(new String[0])); + } + + if (protocols != null && protocols.size() > 0) { + this.setIncludeProtocols(protocols.toArray(new String[0])); + } + + if (sslProviderString != null && !sslProviderString.equals("")) { + setProvider(sslProviderString); + } else { + if (SecurityUtility.CONSCRYPT_PROVIDER != null) { + setProvider(SecurityUtility.CONSCRYPT_PROVIDER.getName()); + } + } + + if (requireTrustedClientCertOnConnect) { + this.setNeedClientAuth(true); + } else { + this.setWantClientAuth(true); + } + this.setTrustAll(true); + } + + @Override + public SSLContext getSslContext() { + return sslCtxRefresher.get(); + } + } +} diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/keystoretls/KeyStoreSSLContext.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/keystoretls/KeyStoreSSLContext.java index 1ed310946f2b53..8f836cdd166fb2 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/keystoretls/KeyStoreSSLContext.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/keystoretls/KeyStoreSSLContext.java @@ -38,6 +38,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.pulsar.common.util.SecurityUtility; +import org.apache.pulsar.common.util.jetty.JettySslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory; /** @@ -352,16 +353,7 @@ public static SslContextFactory.Server createSslContextFactory(String sslProvide Set ciphers, Set protocols, long certRefreshInSec) { - SslContextFactory.Server sslCtxFactory; - - if (sslProviderString == null) { - Provider provider = SecurityUtility.CONSCRYPT_PROVIDER; - if (provider != null) { - sslProviderString = provider.getName(); - } - } - - sslCtxFactory = new JettySslContextFactoryWithAutoRefresh( + return JettySslContextFactory.createServerSslContextWithKeystore( sslProviderString, keyStoreTypeString, keyStore, @@ -373,16 +365,8 @@ public static SslContextFactory.Server createSslContextFactory(String sslProvide requireTrustedClientCertOnConnect, ciphers, protocols, - certRefreshInSec); - - if (requireTrustedClientCertOnConnect) { - sslCtxFactory.setNeedClientAuth(true); - } else { - sslCtxFactory.setWantClientAuth(true); - } - sslCtxFactory.setTrustAll(true); - - return sslCtxFactory; + certRefreshInSec + ); } } diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/WorkerServer.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/WorkerServer.java index e5310844424664..ac45a087466703 100644 --- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/WorkerServer.java +++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/WorkerServer.java @@ -19,13 +19,18 @@ package org.apache.pulsar.functions.worker.rest; import io.prometheus.client.jetty.JettyStatisticsCollector; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Optional; +import javax.servlet.DispatcherType; import lombok.extern.slf4j.Slf4j; import org.apache.pulsar.broker.authentication.AuthenticationService; import org.apache.pulsar.broker.web.AuthenticationFilter; -import org.apache.pulsar.broker.web.RateLimitingFilter; import org.apache.pulsar.broker.web.JettyRequestLogFactory; +import org.apache.pulsar.broker.web.RateLimitingFilter; import org.apache.pulsar.broker.web.WebExecutorThreadPool; -import org.apache.pulsar.common.util.SecurityUtility; +import org.apache.pulsar.common.util.jetty.JettySslContextFactory; import org.apache.pulsar.functions.worker.WorkerConfig; import org.apache.pulsar.functions.worker.WorkerService; import org.apache.pulsar.functions.worker.rest.api.v2.WorkerApiV2Resource; @@ -45,13 +50,6 @@ import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.servlet.ServletContainer; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Optional; - -import javax.servlet.DispatcherType; - @Slf4j public class WorkerServer { @@ -122,11 +120,11 @@ private void init() { if (this.workerConfig.getTlsEnabled()) { try { - SslContextFactory sslCtxFactory = SecurityUtility.createSslContextFactory( + SslContextFactory sslCtxFactory = JettySslContextFactory.createServerSslContext( this.workerConfig.isTlsAllowInsecureConnection(), this.workerConfig.getTlsTrustCertsFilePath(), this.workerConfig.getTlsCertificateFilePath(), this.workerConfig.getTlsKeyFilePath(), this.workerConfig.isTlsRequireTrustedClientCertOnConnect(), - true, + null, null, this.workerConfig.getTlsCertRefreshCheckDurationSec()); httpsConnector = new ServerConnector(server, 1, 1, sslCtxFactory); httpsConnector.setPort(this.workerConfig.getWorkerPortTls()); diff --git a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/WebServer.java b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/WebServer.java index 84b1153b386293..e58214a2faae7d 100644 --- a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/WebServer.java +++ b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/WebServer.java @@ -35,7 +35,7 @@ import org.apache.pulsar.broker.web.JsonMapperProvider; import org.apache.pulsar.broker.web.RateLimitingFilter; import org.apache.pulsar.broker.web.WebExecutorThreadPool; -import org.apache.pulsar.common.util.SecurityUtility; +import org.apache.pulsar.common.util.jetty.JettySslContextFactory; import org.apache.pulsar.common.util.keystoretls.KeyStoreSSLContext; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; @@ -108,18 +108,23 @@ public WebServer(ProxyConfiguration config, AuthenticationService authentication config.getTlsTrustStore(), config.getTlsTrustStorePassword(), config.isTlsRequireTrustedClientCertOnConnect(), - config.getWebServiceTlsCiphers(), - config.getWebServiceTlsProtocols(), + config.getWebServiceTlsCiphers() != null ? config.getWebServiceTlsCiphers() : + config.getTlsCiphers(), + config.getWebServiceTlsProtocols() != null ? config.getWebServiceTlsProtocols() : + config.getTlsCiphers(), config.getTlsCertRefreshCheckDurationSec() ); } else { - sslCtxFactory = SecurityUtility.createSslContextFactory( + sslCtxFactory = JettySslContextFactory.createServerSslContext( config.isTlsAllowInsecureConnection(), config.getTlsTrustCertsFilePath(), config.getTlsCertificateFilePath(), config.getTlsKeyFilePath(), config.isTlsRequireTrustedClientCertOnConnect(), - true, + config.getWebServiceTlsCiphers() != null ? config.getWebServiceTlsCiphers() : + config.getTlsCiphers(), + config.getWebServiceTlsProtocols() != null ? config.getWebServiceTlsProtocols() : + config.getTlsCiphers(), config.getTlsCertRefreshCheckDurationSec()); } connectorTls = new ServerConnector(server, 1, 1, sslCtxFactory); diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/ProxyServer.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/ProxyServer.java index 1d4df854f42124..679d981024591e 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/ProxyServer.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/ProxyServer.java @@ -23,18 +23,16 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; - import java.util.stream.Collectors; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.websocket.DeploymentException; - import org.apache.pulsar.broker.PulsarServerException; -import org.apache.pulsar.broker.web.JsonMapperProvider; import org.apache.pulsar.broker.web.JettyRequestLogFactory; +import org.apache.pulsar.broker.web.JsonMapperProvider; import org.apache.pulsar.broker.web.WebExecutorThreadPool; import org.apache.pulsar.client.api.PulsarClientException; -import org.apache.pulsar.common.util.SecurityUtility; +import org.apache.pulsar.common.util.jetty.JettySslContextFactory; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -74,13 +72,14 @@ public ProxyServer(WebSocketProxyConfiguration config) // TLS enabled connector if (config.getWebServicePortTls().isPresent()) { try { - SslContextFactory sslCtxFactory = SecurityUtility.createSslContextFactory( + SslContextFactory sslCtxFactory = JettySslContextFactory.createServerSslContext( config.isTlsAllowInsecureConnection(), config.getTlsTrustCertsFilePath(), config.getTlsCertificateFilePath(), config.getTlsKeyFilePath(), config.isTlsRequireTrustedClientCertOnConnect(), - true, + null, + null, config.getTlsCertRefreshCheckDurationSec()); connectorTls = new ServerConnector(server, -1, -1, sslCtxFactory); connectorTls.setPort(config.getWebServicePortTls().get());