ARTEMIS-656 support host verification for SSL cert
This commit is contained in:
parent
113c2a3477
commit
cfbe06f3bc
|
@ -18,6 +18,7 @@ package org.apache.activemq.artemis.core.remoting.impl.netty;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
|
import javax.net.ssl.SSLParameters;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
|
@ -197,6 +198,8 @@ public class NettyConnector extends AbstractConnector {
|
||||||
|
|
||||||
private String enabledProtocols;
|
private String enabledProtocols;
|
||||||
|
|
||||||
|
private boolean verifyHost;
|
||||||
|
|
||||||
private boolean tcpNoDelay;
|
private boolean tcpNoDelay;
|
||||||
|
|
||||||
private int tcpSendBufferSize;
|
private int tcpSendBufferSize;
|
||||||
|
@ -306,6 +309,8 @@ public class NettyConnector extends AbstractConnector {
|
||||||
enabledCipherSuites = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES, configuration);
|
enabledCipherSuites = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES, configuration);
|
||||||
|
|
||||||
enabledProtocols = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.DEFAULT_ENABLED_PROTOCOLS, configuration);
|
enabledProtocols = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.DEFAULT_ENABLED_PROTOCOLS, configuration);
|
||||||
|
|
||||||
|
verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
|
keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
|
||||||
|
@ -316,6 +321,7 @@ public class NettyConnector extends AbstractConnector {
|
||||||
trustStorePassword = TransportConstants.DEFAULT_TRUSTSTORE_PASSWORD;
|
trustStorePassword = TransportConstants.DEFAULT_TRUSTSTORE_PASSWORD;
|
||||||
enabledCipherSuites = TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES;
|
enabledCipherSuites = TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES;
|
||||||
enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS;
|
enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS;
|
||||||
|
verifyHost = TransportConstants.DEFAULT_VERIFY_HOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration);
|
tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration);
|
||||||
|
@ -462,7 +468,13 @@ public class NettyConnector extends AbstractConnector {
|
||||||
public void initChannel(Channel channel) throws Exception {
|
public void initChannel(Channel channel) throws Exception {
|
||||||
final ChannelPipeline pipeline = channel.pipeline();
|
final ChannelPipeline pipeline = channel.pipeline();
|
||||||
if (sslEnabled && !useServlet) {
|
if (sslEnabled && !useServlet) {
|
||||||
SSLEngine engine = context.createSSLEngine();
|
SSLEngine engine;
|
||||||
|
if (verifyHost) {
|
||||||
|
engine = context.createSSLEngine(host, port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
engine = context.createSSLEngine();
|
||||||
|
}
|
||||||
|
|
||||||
engine.setUseClientMode(true);
|
engine.setUseClientMode(true);
|
||||||
|
|
||||||
|
@ -496,6 +508,12 @@ public class NettyConnector extends AbstractConnector {
|
||||||
engine.setEnabledProtocols(originalProtocols);
|
engine.setEnabledProtocols(originalProtocols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verifyHost) {
|
||||||
|
SSLParameters sslParameters = engine.getSSLParameters();
|
||||||
|
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
|
||||||
|
engine.setSSLParameters(sslParameters);
|
||||||
|
}
|
||||||
|
|
||||||
SslHandler handler = new SslHandler(engine);
|
SslHandler handler = new SslHandler(engine);
|
||||||
|
|
||||||
pipeline.addLast(handler);
|
pipeline.addLast(handler);
|
||||||
|
|
|
@ -87,6 +87,8 @@ public class TransportConstants {
|
||||||
|
|
||||||
public static final String NEED_CLIENT_AUTH_PROP_NAME = "needClientAuth";
|
public static final String NEED_CLIENT_AUTH_PROP_NAME = "needClientAuth";
|
||||||
|
|
||||||
|
public static final String VERIFY_HOST_PROP_NAME = "verifyHost";
|
||||||
|
|
||||||
public static final String BACKLOG_PROP_NAME = "backlog";
|
public static final String BACKLOG_PROP_NAME = "backlog";
|
||||||
|
|
||||||
public static final String NETTY_VERSION;
|
public static final String NETTY_VERSION;
|
||||||
|
@ -155,6 +157,8 @@ public class TransportConstants {
|
||||||
|
|
||||||
public static final boolean DEFAULT_NEED_CLIENT_AUTH = false;
|
public static final boolean DEFAULT_NEED_CLIENT_AUTH = false;
|
||||||
|
|
||||||
|
public static final boolean DEFAULT_VERIFY_HOST = false;
|
||||||
|
|
||||||
public static final boolean DEFAULT_TCP_NODELAY = true;
|
public static final boolean DEFAULT_TCP_NODELAY = true;
|
||||||
|
|
||||||
public static final int DEFAULT_TCP_SENDBUFFER_SIZE = 32768;
|
public static final int DEFAULT_TCP_SENDBUFFER_SIZE = 32768;
|
||||||
|
@ -226,6 +230,7 @@ public class TransportConstants {
|
||||||
allowableAcceptorKeys.add(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME);
|
allowableAcceptorKeys.add(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME);
|
||||||
allowableAcceptorKeys.add(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME);
|
allowableAcceptorKeys.add(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME);
|
||||||
allowableAcceptorKeys.add(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME);
|
allowableAcceptorKeys.add(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME);
|
||||||
|
allowableAcceptorKeys.add(TransportConstants.VERIFY_HOST_PROP_NAME);
|
||||||
allowableAcceptorKeys.add(TransportConstants.TCP_NODELAY_PROPNAME);
|
allowableAcceptorKeys.add(TransportConstants.TCP_NODELAY_PROPNAME);
|
||||||
allowableAcceptorKeys.add(TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME);
|
allowableAcceptorKeys.add(TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME);
|
||||||
allowableAcceptorKeys.add(TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME);
|
allowableAcceptorKeys.add(TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME);
|
||||||
|
@ -270,6 +275,7 @@ public class TransportConstants {
|
||||||
allowableConnectorKeys.add(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME);
|
allowableConnectorKeys.add(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME);
|
||||||
allowableConnectorKeys.add(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME);
|
allowableConnectorKeys.add(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME);
|
||||||
allowableConnectorKeys.add(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME);
|
allowableConnectorKeys.add(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME);
|
||||||
|
allowableConnectorKeys.add(TransportConstants.VERIFY_HOST_PROP_NAME);
|
||||||
allowableConnectorKeys.add(TransportConstants.TCP_NODELAY_PROPNAME);
|
allowableConnectorKeys.add(TransportConstants.TCP_NODELAY_PROPNAME);
|
||||||
allowableConnectorKeys.add(TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME);
|
allowableConnectorKeys.add(TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME);
|
||||||
allowableConnectorKeys.add(TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME);
|
allowableConnectorKeys.add(TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME);
|
||||||
|
|
|
@ -19,12 +19,15 @@ package org.apache.activemq.artemis.core.remoting.impl.netty;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
import javax.net.ssl.SSLParameters;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -138,6 +141,8 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
|
|
||||||
private final boolean needClientAuth;
|
private final boolean needClientAuth;
|
||||||
|
|
||||||
|
private final boolean verifyHost;
|
||||||
|
|
||||||
private final boolean tcpNoDelay;
|
private final boolean tcpNoDelay;
|
||||||
|
|
||||||
private final int backlog;
|
private final int backlog;
|
||||||
|
@ -224,6 +229,8 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
enabledProtocols = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.DEFAULT_ENABLED_PROTOCOLS, configuration);
|
enabledProtocols = ConfigurationHelper.getStringProperty(TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.DEFAULT_ENABLED_PROTOCOLS, configuration);
|
||||||
|
|
||||||
needClientAuth = ConfigurationHelper.getBooleanProperty(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, TransportConstants.DEFAULT_NEED_CLIENT_AUTH, configuration);
|
needClientAuth = ConfigurationHelper.getBooleanProperty(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, TransportConstants.DEFAULT_NEED_CLIENT_AUTH, configuration);
|
||||||
|
|
||||||
|
verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
|
keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
|
||||||
|
@ -235,6 +242,7 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
enabledCipherSuites = TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES;
|
enabledCipherSuites = TransportConstants.DEFAULT_ENABLED_CIPHER_SUITES;
|
||||||
enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS;
|
enabledProtocols = TransportConstants.DEFAULT_ENABLED_PROTOCOLS;
|
||||||
needClientAuth = TransportConstants.DEFAULT_NEED_CLIENT_AUTH;
|
needClientAuth = TransportConstants.DEFAULT_NEED_CLIENT_AUTH;
|
||||||
|
verifyHost = TransportConstants.DEFAULT_VERIFY_HOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration);
|
tcpNoDelay = ConfigurationHelper.getBooleanProperty(TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.DEFAULT_TCP_NODELAY, configuration);
|
||||||
|
@ -391,7 +399,13 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
ise.initCause(e);
|
ise.initCause(e);
|
||||||
throw ise;
|
throw ise;
|
||||||
}
|
}
|
||||||
SSLEngine engine = context.createSSLEngine();
|
SSLEngine engine;
|
||||||
|
if (verifyHost) {
|
||||||
|
engine = context.createSSLEngine(host, port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
engine = context.createSSLEngine();
|
||||||
|
}
|
||||||
|
|
||||||
engine.setUseClientMode(false);
|
engine.setUseClientMode(false);
|
||||||
|
|
||||||
|
@ -439,6 +453,13 @@ public class NettyAcceptor extends AbstractAcceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.setEnabledProtocols(set.toArray(new String[set.size()]));
|
engine.setEnabledProtocols(set.toArray(new String[set.size()]));
|
||||||
|
|
||||||
|
if (verifyHost) {
|
||||||
|
SSLParameters sslParameters = engine.getSSLParameters();
|
||||||
|
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
|
||||||
|
engine.setSSLParameters(sslParameters);
|
||||||
|
}
|
||||||
|
|
||||||
return new SslHandler(engine);
|
return new SslHandler(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -395,6 +395,18 @@ following additional properties:
|
||||||
connecting to this acceptor that 2-way SSL is required. Valid values
|
connecting to this acceptor that 2-way SSL is required. Valid values
|
||||||
are `true` or `false`. Default is `false`.
|
are `true` or `false`. Default is `false`.
|
||||||
|
|
||||||
|
- `verifyHost`
|
||||||
|
|
||||||
|
When used on an `acceptor` the `CN` of the connecting client's SSL certificate
|
||||||
|
will be compared to its hostname to verify they match. This is useful
|
||||||
|
only for 2-way SSL.
|
||||||
|
|
||||||
|
When used on a `connector` the `CN` of the server's SSL certificate will be
|
||||||
|
compared to its hostname to verify they match. This is useful for both 1-way
|
||||||
|
and 2-way SSL.
|
||||||
|
|
||||||
|
Valid values are `true` or `false`. Default is `false`.
|
||||||
|
|
||||||
## 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
|
||||||
|
|
|
@ -55,7 +55,10 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "storeType={0}")
|
@Parameterized.Parameters(name = "storeType={0}")
|
||||||
public static Collection getParameters() {
|
public static Collection getParameters() {
|
||||||
return Arrays.asList(new Object[][]{{"JCEKS"}, {"JKS"}});
|
return Arrays.asList(new Object[][]{
|
||||||
|
{"JCEKS"},
|
||||||
|
{"JKS"}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoreClientOverOneWaySSLTest(String storeType) {
|
public CoreClientOverOneWaySSLTest(String storeType) {
|
||||||
|
@ -78,6 +81,10 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
|
||||||
* keytool -export -keystore other-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample
|
* keytool -export -keystore other-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample
|
||||||
* keytool -import -keystore other-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt
|
* keytool -import -keystore other-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
*
|
*
|
||||||
|
* keytool -genkey -keystore verified-server-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
|
||||||
|
* keytool -export -keystore verified-server-side-keystore.jks -file activemq-jks.cer -storepass secureexample
|
||||||
|
* keytool -import -keystore verified-client-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
|
*
|
||||||
* Commands to create the JCEKS artifacts:
|
* Commands to create the JCEKS artifacts:
|
||||||
* keytool -genkey -keystore server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ"
|
* keytool -genkey -keystore server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ"
|
||||||
* keytool -export -keystore server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
* keytool -export -keystore server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
||||||
|
@ -86,6 +93,10 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
|
||||||
* keytool -genkey -keystore other-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=Other ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ"
|
* keytool -genkey -keystore other-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=Other ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ"
|
||||||
* keytool -export -keystore other-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
* keytool -export -keystore other-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
||||||
* keytool -import -keystore other-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt
|
* keytool -import -keystore other-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
|
*
|
||||||
|
* keytool -genkey -keystore verified-server-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ"
|
||||||
|
* keytool -export -keystore verified-server-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
||||||
|
* keytool -import -keystore verified-client-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
*/
|
*/
|
||||||
private String storeType;
|
private String storeType;
|
||||||
private String SERVER_SIDE_KEYSTORE;
|
private String SERVER_SIDE_KEYSTORE;
|
||||||
|
@ -123,6 +134,56 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
|
||||||
Assert.assertEquals(text, m.getBodyBuffer().readString());
|
Assert.assertEquals(text, m.getBodyBuffer().readString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneWaySSLVerifyHost() throws Exception {
|
||||||
|
createCustomSslServer(null, null, true);
|
||||||
|
String text = RandomUtil.randomString();
|
||||||
|
|
||||||
|
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "verified-" + CLIENT_SIDE_TRUSTSTORE);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
tc.getParams().put(TransportConstants.VERIFY_HOST_PROP_NAME, true);
|
||||||
|
|
||||||
|
ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
|
||||||
|
ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));
|
||||||
|
ClientSession session = addClientSession(sf.createSession(false, true, true));
|
||||||
|
session.createQueue(CoreClientOverOneWaySSLTest.QUEUE, CoreClientOverOneWaySSLTest.QUEUE, false);
|
||||||
|
ClientProducer producer = addClientProducer(session.createProducer(CoreClientOverOneWaySSLTest.QUEUE));
|
||||||
|
|
||||||
|
ClientMessage message = createTextMessage(session, text);
|
||||||
|
producer.send(message);
|
||||||
|
|
||||||
|
ClientConsumer consumer = addClientConsumer(session.createConsumer(CoreClientOverOneWaySSLTest.QUEUE));
|
||||||
|
session.start();
|
||||||
|
|
||||||
|
Message m = consumer.receive(1000);
|
||||||
|
Assert.assertNotNull(m);
|
||||||
|
Assert.assertEquals(text, m.getBodyBuffer().readString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneWaySSLVerifyHostNegative() throws Exception {
|
||||||
|
createCustomSslServer(null, null, false);
|
||||||
|
String text = RandomUtil.randomString();
|
||||||
|
|
||||||
|
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
tc.getParams().put(TransportConstants.VERIFY_HOST_PROP_NAME, true);
|
||||||
|
|
||||||
|
ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
|
||||||
|
|
||||||
|
try {
|
||||||
|
ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));
|
||||||
|
fail("Creating a session here should fail due to a certificate with a CN that doesn't match the host name.");
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneWaySSLReloaded() throws Exception {
|
public void testOneWaySSLReloaded() throws Exception {
|
||||||
createCustomSslServer();
|
createCustomSslServer();
|
||||||
|
@ -589,11 +650,22 @@ public class CoreClientOverOneWaySSLTest extends ActiveMQTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createCustomSslServer(String cipherSuites, String protocols) throws Exception {
|
private void createCustomSslServer(String cipherSuites, String protocols) throws Exception {
|
||||||
|
createCustomSslServer(cipherSuites, protocols, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCustomSslServer(String cipherSuites, String protocols, boolean useVerifiedKeystore) throws Exception {
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||||
params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
|
params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE);
|
|
||||||
|
if (useVerifiedKeystore) {
|
||||||
|
params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_KEYSTORE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE);
|
||||||
|
}
|
||||||
params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
params.put(TransportConstants.HOST_PROP_NAME, "localhost");
|
||||||
|
|
||||||
if (cipherSuites != null) {
|
if (cipherSuites != null) {
|
||||||
params.put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, cipherSuites);
|
params.put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, cipherSuites);
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.activemq.artemis.api.core.client.ClientSession;
|
||||||
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
|
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
|
||||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||||
import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
||||||
|
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor;
|
||||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||||
import org.apache.activemq.artemis.utils.RandomUtil;
|
import org.apache.activemq.artemis.utils.RandomUtil;
|
||||||
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
||||||
|
@ -56,7 +57,9 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "storeType={0}")
|
@Parameterized.Parameters(name = "storeType={0}")
|
||||||
public static Collection getParameters() {
|
public static Collection getParameters() {
|
||||||
return Arrays.asList(new Object[][]{{"JCEKS"}, {"JKS"}});
|
return Arrays.asList(new Object[][]{
|
||||||
|
{"JCEKS"},
|
||||||
|
{"JKS"}});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoreClientOverTwoWaySSLTest(String storeType) {
|
public CoreClientOverTwoWaySSLTest(String storeType) {
|
||||||
|
@ -77,10 +80,18 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase {
|
||||||
* keytool -export -keystore client-side-keystore.jks -file activemq-jks.cer -storepass secureexample
|
* keytool -export -keystore client-side-keystore.jks -file activemq-jks.cer -storepass secureexample
|
||||||
* keytool -import -keystore server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt
|
* keytool -import -keystore server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
*
|
*
|
||||||
|
* keytool -genkey -keystore verified-client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
|
||||||
|
* keytool -export -keystore verified-client-side-keystore.jks -file activemq-jks.cer -storepass secureexample
|
||||||
|
* keytool -import -keystore verified-server-side-truststore.jks -file activemq-jks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
|
*
|
||||||
* Commands to create the JCEKS artifacts:
|
* Commands to create the JCEKS artifacts:
|
||||||
* keytool -genkey -keystore client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
|
* keytool -genkey -keystore client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
|
||||||
* keytool -export -keystore client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
* keytool -export -keystore client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
||||||
* keytool -import -keystore server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt
|
* keytool -import -keystore server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
|
*
|
||||||
|
* keytool -genkey -keystore verified-client-side-keystore.jceks -storetype JCEKS -storepass secureexample -keypass secureexample -dname "CN=localhost, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
|
||||||
|
* keytool -export -keystore verified-client-side-keystore.jceks -file activemq-jceks.cer -storetype jceks -storepass secureexample
|
||||||
|
* keytool -import -keystore verified-server-side-truststore.jceks -storetype JCEKS -file activemq-jceks.cer -storepass secureexample -keypass secureexample -noprompt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private String storeType;
|
private String storeType;
|
||||||
|
@ -148,6 +159,72 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase {
|
||||||
Assert.assertEquals(text, m.getBodyBuffer().readString());
|
Assert.assertEquals(text, m.getBodyBuffer().readString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoWaySSLVerifyClientHost() throws Exception {
|
||||||
|
NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL");
|
||||||
|
acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true);
|
||||||
|
acceptor.getConfiguration().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "verified-" + SERVER_SIDE_TRUSTSTORE);
|
||||||
|
server.getRemotingService().stop(false);
|
||||||
|
server.getRemotingService().start();
|
||||||
|
server.getRemotingService().startAcceptors();
|
||||||
|
|
||||||
|
String text = RandomUtil.randomString();
|
||||||
|
|
||||||
|
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
|
tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "verified-" + CLIENT_SIDE_KEYSTORE);
|
||||||
|
tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
|
||||||
|
server.getRemotingService().addIncomingInterceptor(new MyInterceptor());
|
||||||
|
|
||||||
|
ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
|
||||||
|
ClientSessionFactory sf = createSessionFactory(locator);
|
||||||
|
ClientSession session = sf.createSession(false, true, true);
|
||||||
|
session.createQueue(CoreClientOverTwoWaySSLTest.QUEUE, CoreClientOverTwoWaySSLTest.QUEUE, false);
|
||||||
|
ClientProducer producer = session.createProducer(CoreClientOverTwoWaySSLTest.QUEUE);
|
||||||
|
|
||||||
|
ClientMessage message = createTextMessage(session, text);
|
||||||
|
producer.send(message);
|
||||||
|
|
||||||
|
ClientConsumer consumer = session.createConsumer(CoreClientOverTwoWaySSLTest.QUEUE);
|
||||||
|
session.start();
|
||||||
|
|
||||||
|
Message m = consumer.receive(1000);
|
||||||
|
Assert.assertNotNull(m);
|
||||||
|
Assert.assertEquals(text, m.getBodyBuffer().readString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoWaySSLVerifyClientHostNegative() throws Exception {
|
||||||
|
NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL");
|
||||||
|
acceptor.getConfiguration().put(TransportConstants.VERIFY_HOST_PROP_NAME, true);
|
||||||
|
server.getRemotingService().stop(false);
|
||||||
|
server.getRemotingService().start();
|
||||||
|
server.getRemotingService().startAcceptors();
|
||||||
|
|
||||||
|
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
|
tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, CLIENT_SIDE_TRUSTSTORE);
|
||||||
|
tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, CLIENT_SIDE_KEYSTORE);
|
||||||
|
tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD);
|
||||||
|
|
||||||
|
server.getRemotingService().addIncomingInterceptor(new MyInterceptor());
|
||||||
|
|
||||||
|
ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
|
||||||
|
try {
|
||||||
|
ClientSessionFactory sf = createSessionFactory(locator);
|
||||||
|
fail("Creating a session here should fail due to a certificate with a CN that doesn't match the host name.");
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTwoWaySSLWithoutClientKeyStore() throws Exception {
|
public void testTwoWaySSLWithoutClientKeyStore() throws Exception {
|
||||||
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||||
|
@ -183,7 +260,7 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase {
|
||||||
params.put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType);
|
params.put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
|
params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
|
||||||
params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true);
|
params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true);
|
||||||
ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params));
|
ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params, "nettySSL"));
|
||||||
server = createServer(false, config);
|
server = createServer(false, config);
|
||||||
server.start();
|
server.start();
|
||||||
waitForServerToStart(server);
|
waitForServerToStart(server);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue