[ARTEMIS-2704]: Provide a SPI to manage and cache SSLContext.
* Adding a new SPI to allow for SSLContext reuse accross the broker. * Providing a default behaviour similar to the existing one. [ARTEMIS-2718]: Take advantage of ARTEMIS-2704 to cache SSLContexts. * Adding a cache for SSLContexts and reusing them accross acceptors and connectors. Issue: https://issues.apache.org/jira/browse/ARTEMIS-2704 Issue: https://issues.apache.org/jira/browse/ARTEMIS-2718
This commit is contained in:
parent
79fef2f20b
commit
a88815d9b3
|
@ -103,7 +103,6 @@ import io.netty.util.ResourceLeakDetector;
|
||||||
import io.netty.util.ResourceLeakDetector.Level;
|
import io.netty.util.ResourceLeakDetector.Level;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||||
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
|
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
||||||
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
|
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
|
||||||
import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
|
import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
|
||||||
|
@ -123,6 +122,9 @@ import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import static org.apache.activemq.artemis.utils.Base64.encodeBytes;
|
import static org.apache.activemq.artemis.utils.Base64.encodeBytes;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
|
||||||
|
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactoryProvider;
|
||||||
|
|
||||||
public class NettyConnector extends AbstractConnector {
|
public class NettyConnector extends AbstractConnector {
|
||||||
|
|
||||||
public static String NIO_CONNECTOR_TYPE = "NIO";
|
public static String NIO_CONNECTOR_TYPE = "NIO";
|
||||||
|
@ -674,22 +676,10 @@ public class NettyConnector extends AbstractConnector {
|
||||||
String truststoreProvider,
|
String truststoreProvider,
|
||||||
String truststorePath,
|
String truststorePath,
|
||||||
String truststorePassword) throws Exception {
|
String truststorePassword) throws Exception {
|
||||||
SSLContext context;
|
SSLContext context = SSLContextFactoryProvider.getSSLContextFactory().getSSLContext(configuration,
|
||||||
if (useDefaultSslContext) {
|
keystoreProvider, keystorePath, keystorePassword,
|
||||||
context = SSLContext.getDefault();
|
truststoreProvider, truststorePath, truststorePassword,
|
||||||
} else {
|
crlPath, trustManagerFactoryPlugin, trustAll);
|
||||||
context = new SSLSupport()
|
|
||||||
.setKeystoreProvider(keystoreProvider)
|
|
||||||
.setKeystorePath(keystorePath)
|
|
||||||
.setKeystorePassword(keystorePassword)
|
|
||||||
.setTruststoreProvider(truststoreProvider)
|
|
||||||
.setTruststorePath(truststorePath)
|
|
||||||
.setTruststorePassword(truststorePassword)
|
|
||||||
.setTrustAll(trustAll)
|
|
||||||
.setCrlPath(crlPath)
|
|
||||||
.setTrustManagerFactoryPlugin(trustManagerFactoryPlugin)
|
|
||||||
.createContext();
|
|
||||||
}
|
|
||||||
Subject subject = null;
|
Subject subject = null;
|
||||||
if (kerb5Config != null) {
|
if (kerb5Config != null) {
|
||||||
LoginContext loginContext = new LoginContext(kerb5Config);
|
LoginContext loginContext = new LoginContext(kerb5Config);
|
||||||
|
|
|
@ -29,6 +29,8 @@ public class TransportConstants {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TransportConstants.class);
|
private static final Logger logger = Logger.getLogger(TransportConstants.class);
|
||||||
|
|
||||||
|
public static final String SSL_CONTEXT_PROP_NAME = "sslContext";
|
||||||
|
|
||||||
public static final String SSL_ENABLED_PROP_NAME = "sslEnabled";
|
public static final String SSL_ENABLED_PROP_NAME = "sslEnabled";
|
||||||
|
|
||||||
public static final String SSL_KRB5_CONFIG_PROP_NAME = "sslKrb5Config";
|
public static final String SSL_KRB5_CONFIG_PROP_NAME = "sslKrb5Config";
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.activemq.artemis.core.remoting.impl.ssl;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||||
|
import org.apache.activemq.artemis.utils.ConfigurationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSLContextFactory providing a cache of SSLContext.
|
||||||
|
* Since SSLContext should be reused instead of recreated and are thread safe.
|
||||||
|
* To activate it uou need to allow this Service to be discovered by having a
|
||||||
|
* <code>META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory</code>
|
||||||
|
* file with <code> org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory</code>
|
||||||
|
* as value.
|
||||||
|
*/
|
||||||
|
public class CachingSSLContextFactory extends DefaultSSLContextFactory {
|
||||||
|
|
||||||
|
private static final Map<String, SSLContext> SSL_CONTEXTS = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearSSLContexts() {
|
||||||
|
SSL_CONTEXTS.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SSLContext getSSLContext(Map<String, Object> configuration,
|
||||||
|
String keystoreProvider, String keystorePath, String keystorePassword,
|
||||||
|
String truststoreProvider, String truststorePath, String truststorePassword,
|
||||||
|
String crlPath, String trustManagerFactoryPlugin, boolean trustAll) throws Exception {
|
||||||
|
String sslContextName = getSSLContextName(configuration, keystorePath, keystoreProvider, truststorePath, truststoreProvider);
|
||||||
|
if (!SSL_CONTEXTS.containsKey(sslContextName)) {
|
||||||
|
SSL_CONTEXTS.put(sslContextName, createSSLContext(configuration,
|
||||||
|
keystoreProvider, keystorePath, keystorePassword,
|
||||||
|
truststoreProvider, truststorePath, truststorePassword,
|
||||||
|
crlPath, trustManagerFactoryPlugin, trustAll));
|
||||||
|
}
|
||||||
|
return SSL_CONTEXTS.get(sslContextName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the sslContextName :
|
||||||
|
* - if available the 'sslContext' from the configuration
|
||||||
|
* - otherwise if available the keyStorePath + '_' + keystoreProvider
|
||||||
|
* - otherwise the truststorePath + '_' + truststoreProvider.
|
||||||
|
* @param configuration
|
||||||
|
* @param keyStorePath
|
||||||
|
* @param keystoreProvider
|
||||||
|
* @param truststorePath
|
||||||
|
* @param truststoreProvider
|
||||||
|
* @return the ley associated to the SSLContext.
|
||||||
|
*/
|
||||||
|
protected String getSSLContextName(Map<String, Object> configuration, String keyStorePath, String keystoreProvider, String truststorePath, String truststoreProvider) {
|
||||||
|
String sslContextName = ConfigurationHelper.getStringProperty(TransportConstants.SSL_CONTEXT_PROP_NAME, null, configuration);
|
||||||
|
if (sslContextName == null) {
|
||||||
|
if (keyStorePath != null) {
|
||||||
|
return keyStorePath + '_' + keystoreProvider;
|
||||||
|
}
|
||||||
|
return truststorePath + '_' + truststoreProvider;
|
||||||
|
}
|
||||||
|
return sslContextName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.activemq.artemis.core.remoting.impl.ssl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||||
|
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory;
|
||||||
|
import org.apache.activemq.artemis.utils.ConfigurationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple SSLContextFactory for use in NettyConnector and NettyAcceptor.
|
||||||
|
*/
|
||||||
|
public class DefaultSSLContextFactory implements SSLContextFactory {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SSLContext getSSLContext(Map<String, Object> configuration,
|
||||||
|
String keystoreProvider, String keystorePath, String keystorePassword,
|
||||||
|
String truststoreProvider, String truststorePath, String truststorePassword,
|
||||||
|
String crlPath, String trustManagerFactoryPlugin, boolean trustAll) throws Exception {
|
||||||
|
return createSSLContext(configuration,
|
||||||
|
keystoreProvider, keystorePath, keystorePassword,
|
||||||
|
truststoreProvider, truststorePath, truststorePassword,
|
||||||
|
crlPath, trustManagerFactoryPlugin, trustAll);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SSLContext createSSLContext(Map<String, Object> configuration,
|
||||||
|
String keystoreProvider, String keystorePath, String keystorePassword,
|
||||||
|
String truststoreProvider, String truststorePath, String truststorePassword,
|
||||||
|
String crlPath, String trustManagerFactoryPlugin, boolean trustAll) throws Exception {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
configuration.forEach((k, v) -> builder.append("\r\n").append(k).append("=").append(v));
|
||||||
|
log.debugf("Creating SSL context with configuration %s", builder.toString());
|
||||||
|
}
|
||||||
|
boolean useDefaultSslContext = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_DEFAULT_SSL_CONTEXT_PROP_NAME, TransportConstants.DEFAULT_USE_DEFAULT_SSL_CONTEXT, configuration);
|
||||||
|
if (useDefaultSslContext) {
|
||||||
|
return SSLContext.getDefault();
|
||||||
|
}
|
||||||
|
return new SSLSupport()
|
||||||
|
.setKeystoreProvider(keystoreProvider)
|
||||||
|
.setKeystorePath(keystorePath)
|
||||||
|
.setKeystorePassword(keystorePassword)
|
||||||
|
.setTruststoreProvider(truststoreProvider)
|
||||||
|
.setTruststorePath(truststorePath)
|
||||||
|
.setTruststorePassword(truststorePassword)
|
||||||
|
.setTrustAll(trustAll)
|
||||||
|
.setCrlPath(crlPath)
|
||||||
|
.setTrustManagerFactoryPlugin(trustManagerFactoryPlugin)
|
||||||
|
.createContext();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.activemq.artemis.spi.core.remoting.ssl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service interface to create a SSLContext for a configuration.
|
||||||
|
* This is NOT used by OpenSSL.
|
||||||
|
* To create and use your own implementation you need to create a file
|
||||||
|
* <code>META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory</code>
|
||||||
|
* in your jar and fill it with the full qualified name of your implementation.
|
||||||
|
*/
|
||||||
|
public interface SSLContextFactory extends Comparable<SSLContextFactory> {
|
||||||
|
Logger log = Logger.getLogger(SSLContextFactory.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a SSLContext from the configuration.
|
||||||
|
* @param configuration
|
||||||
|
* @param keystoreProvider
|
||||||
|
* @param keystorePath
|
||||||
|
* @param keystorePassword
|
||||||
|
* @param truststoreProvider
|
||||||
|
* @param truststorePath
|
||||||
|
* @param truststorePassword
|
||||||
|
* @param crlPath
|
||||||
|
* @param trustManagerFactoryPlugin
|
||||||
|
* @param trustAll
|
||||||
|
* @return a SSLContext instance.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
SSLContext getSSLContext(Map<String, Object> configuration,
|
||||||
|
String keystoreProvider, String keystorePath, String keystorePassword,
|
||||||
|
String truststoreProvider, String truststorePath, String truststorePassword,
|
||||||
|
String crlPath, String trustManagerFactoryPlugin, boolean trustAll) throws Exception;
|
||||||
|
|
||||||
|
default void clearSSLContexts() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The priority for the SSLContextFactory when resolving the service to get the implementation.
|
||||||
|
* This is used when selecting the implementation when several implementations are loaded.
|
||||||
|
* The highest priority implementation will be used.
|
||||||
|
* @return the priority.
|
||||||
|
*/
|
||||||
|
int getPriority();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int compareTo(SSLContextFactory other) {
|
||||||
|
return this.getPriority() - other.getPriority();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed 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.activemq.artemis.spi.core.remoting.ssl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider that loads the SSLContextFactory services and return the one with the highest priority.
|
||||||
|
* This is only used to provide SSLContext, so it doesn't support OpenSSL.
|
||||||
|
*/
|
||||||
|
public class SSLContextFactoryProvider {
|
||||||
|
private static final SSLContextFactory factory;
|
||||||
|
static {
|
||||||
|
ServiceLoader<SSLContextFactory> loader = ServiceLoader.load(SSLContextFactory.class, Thread.currentThread().getContextClassLoader());
|
||||||
|
final List<SSLContextFactory> factories = new ArrayList<>();
|
||||||
|
loader.forEach(factories::add);
|
||||||
|
Collections.sort(factories);
|
||||||
|
factory = factories.get(factories.size() - 1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the SSLContextFactory with the higher priority.
|
||||||
|
*/
|
||||||
|
public static SSLContextFactory getSSLContextFactory() {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultSSLContextFactory
|
|
@ -92,6 +92,7 @@ import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
|
||||||
import org.apache.activemq.artemis.spi.core.remoting.BufferHandler;
|
import org.apache.activemq.artemis.spi.core.remoting.BufferHandler;
|
||||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||||
import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleListener;
|
import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleListener;
|
||||||
|
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactoryProvider;
|
||||||
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
|
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
|
||||||
import org.apache.activemq.artemis.utils.ConfigurationHelper;
|
import org.apache.activemq.artemis.utils.ConfigurationHelper;
|
||||||
import org.apache.activemq.artemis.utils.collections.TypedProperties;
|
import org.apache.activemq.artemis.utils.collections.TypedProperties;
|
||||||
|
@ -489,6 +490,7 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
// only for testing purposes
|
// only for testing purposes
|
||||||
public void setKeyStorePath(String keyStorePath) {
|
public void setKeyStorePath(String keyStorePath) {
|
||||||
this.keyStorePath = keyStorePath;
|
this.keyStorePath = keyStorePath;
|
||||||
|
this.configuration.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, keyStorePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -519,7 +521,7 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
|
|
||||||
public synchronized SslHandler getSslHandler(ByteBufAllocator alloc, String peerHost, int peerPort) throws Exception {
|
public synchronized SslHandler getSslHandler(ByteBufAllocator alloc, String peerHost, int peerPort) throws Exception {
|
||||||
SSLEngine engine;
|
SSLEngine engine;
|
||||||
if (sslProvider.equals(TransportConstants.OPENSSL_PROVIDER)) {
|
if (TransportConstants.OPENSSL_PROVIDER.equals(sslProvider)) {
|
||||||
engine = loadOpenSslEngine(alloc, peerHost, peerPort);
|
engine = loadOpenSslEngine(alloc, peerHost, peerPort);
|
||||||
} else {
|
} else {
|
||||||
engine = loadJdkSslEngine(peerHost, peerPort);
|
engine = loadJdkSslEngine(peerHost, peerPort);
|
||||||
|
@ -594,21 +596,13 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
private SSLEngine loadJdkSslEngine(String peerHost, int peerPort) throws Exception {
|
private SSLEngine loadJdkSslEngine(String peerHost, int peerPort) throws Exception {
|
||||||
final SSLContext context;
|
final SSLContext context;
|
||||||
try {
|
try {
|
||||||
if (kerb5Config == null && keyStorePath == null && TransportConstants.DEFAULT_TRUSTSTORE_PROVIDER.equals(keyStoreProvider))
|
checkSSLConfiguration();
|
||||||
throw new IllegalArgumentException("If \"" + TransportConstants.SSL_ENABLED_PROP_NAME + "\" is true then \"" + TransportConstants.KEYSTORE_PATH_PROP_NAME + "\" must be non-null " + "unless an alternative \"" + TransportConstants.KEYSTORE_PROVIDER_PROP_NAME + "\" has been specified.");
|
context = SSLContextFactoryProvider.getSSLContextFactory().getSSLContext(configuration,
|
||||||
context = new SSLSupport()
|
keyStoreProvider, keyStorePath, keyStorePassword,
|
||||||
.setKeystoreProvider(keyStoreProvider)
|
trustStoreProvider, trustStorePath, trustStorePassword,
|
||||||
.setKeystorePath(keyStorePath)
|
crlPath, trustManagerFactoryPlugin, TransportConstants.DEFAULT_TRUST_ALL);
|
||||||
.setKeystorePassword(keyStorePassword)
|
|
||||||
.setTruststoreProvider(trustStoreProvider)
|
|
||||||
.setTruststorePath(trustStorePath)
|
|
||||||
.setTruststorePassword(trustStorePassword)
|
|
||||||
.setCrlPath(crlPath)
|
|
||||||
.setTrustManagerFactoryPlugin(trustManagerFactoryPlugin)
|
|
||||||
.createContext();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
IllegalStateException ise = new IllegalStateException("Unable to create NettyAcceptor for " + host + ":" + port);
|
IllegalStateException ise = new IllegalStateException("Unable to create NettyAcceptor for " + host + ":" + port, e);
|
||||||
ise.initCause(e);
|
|
||||||
throw ise;
|
throw ise;
|
||||||
}
|
}
|
||||||
Subject subject = null;
|
Subject subject = null;
|
||||||
|
@ -631,11 +625,19 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkSSLConfiguration() throws IllegalArgumentException {
|
||||||
|
if (configuration.containsKey(TransportConstants.SSL_CONTEXT_PROP_NAME)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (kerb5Config == null && keyStorePath == null && TransportConstants.DEFAULT_TRUSTSTORE_PROVIDER.equals(keyStoreProvider)) {
|
||||||
|
throw new IllegalArgumentException("If \"" + TransportConstants.SSL_ENABLED_PROP_NAME + "\" is true then \"" + TransportConstants.KEYSTORE_PATH_PROP_NAME + "\" must be non-null " + "unless an alternative \"" + TransportConstants.KEYSTORE_PROVIDER_PROP_NAME + "\" has been specified.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private SSLEngine loadOpenSslEngine(ByteBufAllocator alloc, String peerHost, int peerPort) throws Exception {
|
private SSLEngine loadOpenSslEngine(ByteBufAllocator alloc, String peerHost, int peerPort) throws Exception {
|
||||||
final SslContext context;
|
final SslContext context;
|
||||||
try {
|
try {
|
||||||
if (kerb5Config == null && keyStorePath == null && TransportConstants.DEFAULT_TRUSTSTORE_PROVIDER.equals(keyStoreProvider))
|
checkSSLConfiguration();
|
||||||
throw new IllegalArgumentException("If \"" + TransportConstants.SSL_ENABLED_PROP_NAME + "\" is true then \"" + TransportConstants.KEYSTORE_PATH_PROP_NAME + "\" must be non-null " + "unless an alternative \"" + TransportConstants.KEYSTORE_PROVIDER_PROP_NAME + "\" has been specified.");
|
|
||||||
context = new SSLSupport()
|
context = new SSLSupport()
|
||||||
.setKeystoreProvider(keyStoreProvider)
|
.setKeystoreProvider(keyStoreProvider)
|
||||||
.setKeystorePath(keyStorePath)
|
.setKeystorePath(keyStorePath)
|
||||||
|
@ -647,8 +649,7 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
.setTrustManagerFactoryPlugin(trustManagerFactoryPlugin)
|
.setTrustManagerFactoryPlugin(trustManagerFactoryPlugin)
|
||||||
.createNettyContext();
|
.createNettyContext();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
IllegalStateException ise = new IllegalStateException("Unable to create NettyAcceptor for " + host + ":" + port);
|
IllegalStateException ise = new IllegalStateException("Unable to create NettyAcceptor for " + host + ":" + port, e);
|
||||||
ise.initCause(e);
|
|
||||||
throw ise;
|
throw ise;
|
||||||
}
|
}
|
||||||
Subject subject = null;
|
Subject subject = null;
|
||||||
|
|
|
@ -70,6 +70,7 @@ import org.apache.activemq.artemis.spi.core.remoting.AcceptorFactory;
|
||||||
import org.apache.activemq.artemis.spi.core.remoting.BufferHandler;
|
import org.apache.activemq.artemis.spi.core.remoting.BufferHandler;
|
||||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||||
import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleListener;
|
import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleListener;
|
||||||
|
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactoryProvider;
|
||||||
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
|
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
|
||||||
import org.apache.activemq.artemis.utils.ConfigurationHelper;
|
import org.apache.activemq.artemis.utils.ConfigurationHelper;
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch;
|
import org.apache.activemq.artemis.utils.ReusableLatch;
|
||||||
|
@ -380,6 +381,7 @@ public class RemotingServiceImpl implements RemotingService, ServerConnectionLif
|
||||||
if (!started) {
|
if (!started) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SSLContextFactoryProvider.getSSLContextFactory().clearSSLContexts();
|
||||||
|
|
||||||
failureCheckAndFlushThread.close(criticalError);
|
failureCheckAndFlushThread.close(criticalError);
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,12 @@ Please see the examples for a full working example of using Netty SSL.
|
||||||
Netty SSL uses all the same properties as Netty TCP but adds the following
|
Netty SSL uses all the same properties as Netty TCP but adds the following
|
||||||
additional properties:
|
additional properties:
|
||||||
|
|
||||||
|
- `sslContext`
|
||||||
|
|
||||||
|
A key that can be used in conjunction with `org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory`
|
||||||
|
to cache created SSLContext and avoid recreating. Look [Configuring a SSLContextFactory](#Configuring a SSLContextFactory)
|
||||||
|
for more details.
|
||||||
|
|
||||||
- `sslEnabled`
|
- `sslEnabled`
|
||||||
|
|
||||||
Must be `true` to enable SSL. Default is `false`.
|
Must be `true` to enable SSL. Default is `false`.
|
||||||
|
@ -490,6 +496,24 @@ additional properties:
|
||||||
[broker's classpath](using-server.md#adding-runtime-dependencies).
|
[broker's classpath](using-server.md#adding-runtime-dependencies).
|
||||||
|
|
||||||
|
|
||||||
|
#### Configuring a SSLContextFactory
|
||||||
|
|
||||||
|
If you have a `JDK` provider you can configure which SSLContextFactory to use.
|
||||||
|
Currently we provide two implementations:
|
||||||
|
- `org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultSSLContextFactory`
|
||||||
|
- `org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory`
|
||||||
|
but you can also add your own implementation of `org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory`.
|
||||||
|
|
||||||
|
The implementations are loaded by a ServiceLoader, thus you need to declare your implementation in
|
||||||
|
a `META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory` file.
|
||||||
|
If several implementations are available, the one with the highest `priority` will be selected.
|
||||||
|
So for example, if you want to use `org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory`
|
||||||
|
you need to add a `META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory` file
|
||||||
|
to your classpath with the content `org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory`.
|
||||||
|
|
||||||
|
**Note:** This mechanism doesn't work if you have selected `OPENSSL` as provider.
|
||||||
|
|
||||||
|
|
||||||
### Configuring Netty HTTP
|
### Configuring Netty HTTP
|
||||||
|
|
||||||
Netty HTTP tunnels packets over the HTTP protocol. It can be useful in
|
Netty HTTP tunnels packets over the HTTP protocol. It can be useful in
|
||||||
|
|
Loading…
Reference in New Issue