ARTEMIS-1469 - Add support for trusting any client certificate

Added a new trustAll flag which will support trusting any client
keystore when doing testing against a broker.  This setting should not
be used in production and is strictly for testing.
This commit is contained in:
Christopher L. Shannon (cshannon) 2017-10-18 10:07:23 -04:00 committed by Justin Bertram
parent ff68b1641a
commit b386c7c5ae
6 changed files with 92 additions and 4 deletions

View File

@ -212,6 +212,8 @@ public class NettyConnector extends AbstractConnector {
private boolean verifyHost; private boolean verifyHost;
private boolean trustAll;
private String sniHost; private String sniHost;
private String kerb5Config; private String kerb5Config;
@ -342,6 +344,8 @@ public class NettyConnector extends AbstractConnector {
verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration); verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, configuration);
trustAll = ConfigurationHelper.getBooleanProperty(TransportConstants.TRUST_ALL_PROP_NAME, TransportConstants.DEFAULT_TRUST_ALL, configuration);
sniHost = ConfigurationHelper.getStringProperty(TransportConstants.SNIHOST_PROP_NAME, TransportConstants.DEFAULT_SNIHOST_CONFIG, configuration); sniHost = ConfigurationHelper.getStringProperty(TransportConstants.SNIHOST_PROP_NAME, TransportConstants.DEFAULT_SNIHOST_CONFIG, configuration);
kerb5Config = ConfigurationHelper.getStringProperty(TransportConstants.SSL_KRB5_CONFIG_PROP_NAME, TransportConstants.DEFAULT_SSL_KRB5_CONFIG, configuration); kerb5Config = ConfigurationHelper.getStringProperty(TransportConstants.SSL_KRB5_CONFIG_PROP_NAME, TransportConstants.DEFAULT_SSL_KRB5_CONFIG, configuration);
@ -357,6 +361,7 @@ public class NettyConnector extends AbstractConnector {
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; verifyHost = TransportConstants.DEFAULT_VERIFY_HOST;
trustAll = TransportConstants.DEFAULT_TRUST_ALL;
useDefaultSslContext = TransportConstants.DEFAULT_USE_DEFAULT_SSL_CONTEXT; useDefaultSslContext = TransportConstants.DEFAULT_USE_DEFAULT_SSL_CONTEXT;
} }
@ -514,7 +519,7 @@ public class NettyConnector extends AbstractConnector {
if (System.getProperty(ACTIVEMQ_TRUSTSTORE_PASSWORD_PROP_NAME) != null) { if (System.getProperty(ACTIVEMQ_TRUSTSTORE_PASSWORD_PROP_NAME) != null) {
realTrustStorePassword = System.getProperty(ACTIVEMQ_TRUSTSTORE_PASSWORD_PROP_NAME); realTrustStorePassword = System.getProperty(ACTIVEMQ_TRUSTSTORE_PASSWORD_PROP_NAME);
} }
context = SSLSupport.createContext(realKeyStoreProvider, realKeyStorePath, realKeyStorePassword, realTrustStoreProvider, realTrustStorePath, realTrustStorePassword); context = SSLSupport.createContext(realKeyStoreProvider, realKeyStorePath, realKeyStorePassword, realTrustStoreProvider, realTrustStorePath, realTrustStorePassword, trustAll);
} }
} catch (Exception e) { } catch (Exception e) {
close(); close();

View File

@ -103,6 +103,8 @@ public class TransportConstants {
public static final String VERIFY_HOST_PROP_NAME = "verifyHost"; public static final String VERIFY_HOST_PROP_NAME = "verifyHost";
public static final String TRUST_ALL_PROP_NAME = "trustAll";
public static final String SNIHOST_PROP_NAME = "sniHost"; public static final String SNIHOST_PROP_NAME = "sniHost";
public static final String BACKLOG_PROP_NAME = "backlog"; public static final String BACKLOG_PROP_NAME = "backlog";
@ -195,6 +197,8 @@ public class TransportConstants {
public static final boolean DEFAULT_VERIFY_HOST = false; public static final boolean DEFAULT_VERIFY_HOST = false;
public static final boolean DEFAULT_TRUST_ALL = false;
public static final boolean DEFAULT_USE_DEFAULT_SSL_CONTEXT = false; public static final boolean DEFAULT_USE_DEFAULT_SSL_CONTEXT = false;
public static final boolean DEFAULT_TCP_NODELAY = true; public static final boolean DEFAULT_TCP_NODELAY = true;

View File

@ -33,6 +33,8 @@ import java.security.SecureRandom;
import org.apache.activemq.artemis.utils.ClassloadingUtil; import org.apache.activemq.artemis.utils.ClassloadingUtil;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
/** /**
* Please note, this class supports PKCS#11 keystores, but there are no specific tests in the ActiveMQ Artemis test-suite to * Please note, this class supports PKCS#11 keystores, but there are no specific tests in the ActiveMQ Artemis test-suite to
* validate/verify this works because this requires a functioning PKCS#11 provider which is not available by default * validate/verify this works because this requires a functioning PKCS#11 provider which is not available by default
@ -48,9 +50,20 @@ public class SSLSupport {
final String trustStoreProvider, final String trustStoreProvider,
final String trustStorePath, final String trustStorePath,
final String trustStorePassword) throws Exception { final String trustStorePassword) throws Exception {
return SSLSupport.createContext(keystoreProvider, keystorePath, keystorePassword, trustStoreProvider, trustStorePath, trustStorePassword, false);
}
public static SSLContext createContext(final String keystoreProvider,
final String keystorePath,
final String keystorePassword,
final String trustStoreProvider,
final String trustStorePath,
final String trustStorePassword,
final boolean trustAll) throws Exception {
SSLContext context = SSLContext.getInstance("TLS"); SSLContext context = SSLContext.getInstance("TLS");
KeyManager[] keyManagers = SSLSupport.loadKeyManagers(keystoreProvider, keystorePath, keystorePassword); KeyManager[] keyManagers = SSLSupport.loadKeyManagers(keystoreProvider, keystorePath, keystorePassword);
TrustManager[] trustManagers = SSLSupport.loadTrustManager(trustStoreProvider, trustStorePath, trustStorePassword); TrustManager[] trustManagers = SSLSupport.loadTrustManager(trustStoreProvider, trustStorePath, trustStorePassword, trustAll);
context.init(keyManagers, trustManagers, new SecureRandom()); context.init(keyManagers, trustManagers, new SecureRandom());
return context; return context;
} }
@ -79,8 +92,12 @@ public class SSLSupport {
private static TrustManager[] loadTrustManager(final String trustStoreProvider, private static TrustManager[] loadTrustManager(final String trustStoreProvider,
final String trustStorePath, final String trustStorePath,
final String trustStorePassword) throws Exception { final String trustStorePassword,
if (trustStorePath == null && (trustStoreProvider == null || !"PKCS11".equals(trustStoreProvider.toUpperCase()))) { final boolean trustAll) throws Exception {
if (trustAll) {
//This is useful for testing but not should be used outside of that purpose
return InsecureTrustManagerFactory.INSTANCE.getTrustManagers();
} else if (trustStorePath == null && (trustStoreProvider == null || !"PKCS11".equals(trustStoreProvider.toUpperCase()))) {
return null; return null;
} else { } else {
TrustManagerFactory trustMgrFactory; TrustManagerFactory trustMgrFactory;

View File

@ -407,6 +407,14 @@ following additional properties:
Valid values are `true` or `false`. Default is `false`. Valid values are `true` or `false`. Default is `false`.
- `trustAll`
When used on a `connector` the client will trust the provided server certificate
implicitly, regardless of any configured trust store. **Warning:** This setting is
primarily for testing purposes only and should not be used in production.
Valid values are `true` or `false`. Default is `false`.
- `useDefaultSslContext` - `useDefaultSslContext`
Only valid on a `connector`. Allows the `connector` to use the "default" SSL Only valid on a `connector`. Allows the `connector` to use the "default" SSL

View File

@ -220,6 +220,53 @@ public class CoreClientOverTwoWaySSLTest extends ActiveMQTestBase {
} }
} }
@Test
public void testTwoWaySSLVerifyClientTrustAllTrue() throws Exception {
NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL");
acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true);
server.getRemotingService().stop(false);
server.getRemotingService().start();
server.getRemotingService().startAcceptors();
//Set trust all so this should work even with no trust store set
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
tc.getParams().put(TransportConstants.TRUST_ALL_PROP_NAME, true);
tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
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));
ClientSessionFactory sf = createSessionFactory(locator);
sf.close();
}
@Test
public void testTwoWaySSLVerifyClientTrustAllFalse() throws Exception {
NettyAcceptor acceptor = (NettyAcceptor) server.getRemotingService().getAcceptor("nettySSL");
acceptor.getConfiguration().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true);
server.getRemotingService().stop(false);
server.getRemotingService().start();
server.getRemotingService().startAcceptors();
//Trust all defaults to false so this should fail with no trust store set
tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
tc.getParams().put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, storeType);
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 no trust store being set");
} 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);

View File

@ -161,4 +161,11 @@ public class SSLSupportTest extends ActiveMQTestBase {
} catch (Exception e) { } catch (Exception e) {
} }
} }
@Test
public void testContextWithTrustAll() throws Exception {
//This is using a bad password but should not fail because the trust store should be ignored with
//the trustAll flag set to true
SSLSupport.createContext(storeType, keyStorePath, keyStorePassword, storeType, trustStorePath, "bad passord", true);
}
} }