You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2017/07/06 15:30:32 UTC

[1/2] activemq-artemis git commit: This closes #1379

Repository: activemq-artemis
Updated Branches:
  refs/heads/master faae59e6d -> f3cc555ab


This closes #1379


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/f3cc555a
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/f3cc555a
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/f3cc555a

Branch: refs/heads/master
Commit: f3cc555ab0d55b07b028bc0def76347de6e5ee7d
Parents: faae59e cda1e01
Author: Clebert Suconic <cl...@apache.org>
Authored: Thu Jul 6 11:30:25 2017 -0400
Committer: Clebert Suconic <cl...@apache.org>
Committed: Thu Jul 6 11:30:25 2017 -0400

----------------------------------------------------------------------
 .../impl/TransportConfigurationUtil.java        |  28 ++++
 .../remoting/impl/netty/NettyConnection.java    |  14 ++
 .../remoting/impl/netty/NettyConnector.java     |  45 ++++-
 .../remoting/impl/netty/TransportConstants.java |   8 +
 artemis-server/pom.xml                          |  15 +-
 .../core/remoting/impl/netty/NettyAcceptor.java |  39 ++++-
 pom.xml                                         |   4 +-
 tests/integration-tests/pom.xml                 |  22 ++-
 .../ssl/CoreClientOverOneWaySSLKerb5Test.java   | 163 +++++++++++++++++++
 .../src/test/resources/minikdc-krb5.conf        |  26 +++
 10 files changed, 339 insertions(+), 25 deletions(-)
----------------------------------------------------------------------



[2/2] activemq-artemis git commit: ARTEMIS-1264 Foundation work for authentication with Kerberos using KRB_ cypher suites.

Posted by cl...@apache.org.
ARTEMIS-1264 Foundation work for authentication with Kerberos using KRB_ cypher suites.

Core client with netty connector and acceptor doing kerberos
jaas.doAs around sslengine init such that the SSL handshake can do kerberos ticket
generaton and validation.
The kerberos authenticated user is then validated with the security manager before
being populated into the message userId.
The feature is enabled with the kerb5Config property. When lowercase it is the
principal. With a leading uppercase char it is the login.config entry to use.


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/cda1e018
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/cda1e018
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/cda1e018

Branch: refs/heads/master
Commit: cda1e018e1bd7ccd85d6ffd2333fc910b67febf5
Parents: faae59e
Author: gtully <ga...@gmail.com>
Authored: Fri Jun 30 13:56:24 2017 +0100
Committer: Clebert Suconic <cl...@apache.org>
Committed: Thu Jul 6 11:30:25 2017 -0400

----------------------------------------------------------------------
 .../impl/TransportConfigurationUtil.java        |  28 ++++
 .../remoting/impl/netty/NettyConnection.java    |  14 ++
 .../remoting/impl/netty/NettyConnector.java     |  45 ++++-
 .../remoting/impl/netty/TransportConstants.java |   8 +
 artemis-server/pom.xml                          |  15 +-
 .../core/remoting/impl/netty/NettyAcceptor.java |  39 ++++-
 pom.xml                                         |   4 +-
 tests/integration-tests/pom.xml                 |  22 ++-
 .../ssl/CoreClientOverOneWaySSLKerb5Test.java   | 163 +++++++++++++++++++
 .../src/test/resources/minikdc-krb5.conf        |  26 +++
 10 files changed, 339 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
index fe4cb3d..97a4bd2 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/TransportConfigurationUtil.java
@@ -27,6 +27,9 @@ import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactor
 import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
 import org.apache.activemq.artemis.utils.ClassloadingUtil;
 
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
 /**
  * Stores static mappings of class names to ConnectorFactory instances to act as a central repo for ConnectorFactory
  * objects.
@@ -95,4 +98,29 @@ public class TransportConfigurationUtil {
       }
       return false;
    }
+
+   public static Configuration kerb5Config(String principal, boolean initiator) {
+      final Map<String, String> krb5LoginModuleOptions = new HashMap<>();
+      krb5LoginModuleOptions.put("isInitiator", String.valueOf(initiator));
+      krb5LoginModuleOptions.put("principal", principal);
+      krb5LoginModuleOptions.put("useKeyTab", "true");
+      krb5LoginModuleOptions.put("storeKey", "true");
+      krb5LoginModuleOptions.put("doNotPrompt", "true");
+      krb5LoginModuleOptions.put("renewTGT", "true");
+      krb5LoginModuleOptions.put("refreshKrb5Config", "true");
+      krb5LoginModuleOptions.put("useTicketCache", "true");
+      String ticketCache = System.getenv("KRB5CCNAME");
+      if (ticketCache != null) {
+         krb5LoginModuleOptions.put("ticketCache", ticketCache);
+      }
+      return new Configuration() {
+         @Override
+         public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+            return new AppConfigurationEntry[]{
+               new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
+                       AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+                       krb5LoginModuleOptions)};
+         }
+      };
+   }
 }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnection.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnection.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnection.java
index 0316b15..3ce40c9 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnection.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnection.java
@@ -28,6 +28,7 @@ import io.netty.buffer.ByteBuf;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelPromise;
 import io.netty.channel.EventLoop;
 import io.netty.handler.ssl.SslHandler;
@@ -45,6 +46,8 @@ import org.apache.activemq.artemis.utils.Env;
 import org.apache.activemq.artemis.utils.IPV6Util;
 import org.jboss.logging.Logger;
 
+import javax.net.ssl.SSLPeerUnverifiedException;
+
 public class NettyConnection implements Connection {
 
    private static final Logger logger = Logger.getLogger(NettyConnection.class);
@@ -487,6 +490,17 @@ public class NettyConnection implements Connection {
    //never allow this
    @Override
    public final ActiveMQPrincipal getDefaultActiveMQPrincipal() {
+      ChannelHandler channelHandler = channel.pipeline().get("ssl");
+      if (channelHandler != null && channelHandler instanceof SslHandler) {
+         SslHandler sslHandler = (SslHandler) channelHandler;
+         try {
+            return new ActiveMQPrincipal(sslHandler.engine().getSession().getPeerPrincipal().getName(), "");
+         } catch (SSLPeerUnverifiedException ignored) {
+            if (logger.isTraceEnabled()) {
+               logger.trace(ignored.getMessage(), ignored);
+            }
+         }
+      }
       return null;
    }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java
index f5b5e56..20431f0 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyConnector.java
@@ -28,6 +28,7 @@ import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -43,6 +44,8 @@ import java.util.concurrent.TimeUnit;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLParameters;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
 
 import io.netty.bootstrap.Bootstrap;
 import io.netty.buffer.ByteBuf;
@@ -95,6 +98,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQException;
 import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
 import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
 import org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQClientProtocolManager;
+import org.apache.activemq.artemis.core.remoting.impl.TransportConfigurationUtil;
 import org.apache.activemq.artemis.core.remoting.impl.ssl.SSLSupport;
 import org.apache.activemq.artemis.core.server.ActiveMQComponent;
 import org.apache.activemq.artemis.spi.core.remoting.AbstractConnector;
@@ -205,6 +209,10 @@ public class NettyConnector extends AbstractConnector {
 
    private boolean verifyHost;
 
+   private String sniHost;
+
+   private String kerb5Config;
+
    private boolean useDefaultSslContext;
 
    private boolean tcpNoDelay;
@@ -328,6 +336,10 @@ public class NettyConnector extends AbstractConnector {
 
          verifyHost = ConfigurationHelper.getBooleanProperty(TransportConstants.VERIFY_HOST_PROP_NAME, TransportConstants.DEFAULT_VERIFY_HOST, 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);
+
          useDefaultSslContext = ConfigurationHelper.getBooleanProperty(TransportConstants.USE_DEFAULT_SSL_CONTEXT_PROP_NAME, TransportConstants.DEFAULT_USE_DEFAULT_SSL_CONTEXT, configuration);
       } else {
          keyStoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
@@ -509,13 +521,36 @@ public class NettyConnector extends AbstractConnector {
          public void initChannel(Channel channel) throws Exception {
             final ChannelPipeline pipeline = channel.pipeline();
             if (sslEnabled && !useServlet) {
-               SSLEngine engine;
-               if (verifyHost) {
-                  engine = context.createSSLEngine(host, port);
-               } else {
-                  engine = context.createSSLEngine();
+
+               Subject subject = null;
+               if (kerb5Config != null && kerb5Config.length() > 0) {
+
+                  LoginContext loginContext = null;
+                  if (Character.isUpperCase(kerb5Config.charAt(0))) {
+                     // use as login.config scope
+                     loginContext = new LoginContext(kerb5Config);
+                  } else {
+                     // inline keytab config using kerb5Config as principal
+                     loginContext = new LoginContext("", null, null,
+                             TransportConfigurationUtil.kerb5Config(kerb5Config, true));
+                  }
+
+                  loginContext.login();
+                  subject = loginContext.getSubject();
+                  verifyHost = true;
                }
 
+               SSLEngine engine = Subject.doAs(subject, new PrivilegedExceptionAction<SSLEngine>() {
+                  @Override
+                  public SSLEngine run() {
+                     if (verifyHost) {
+                        return context.createSSLEngine(sniHost != null ? sniHost : host, port);
+                     } else {
+                        return context.createSSLEngine();
+                     }
+                  }
+               });
+
                engine.setUseClientMode(true);
 
                engine.setWantClientAuth(true);

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java
index 428a3a0..30342ac 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/TransportConstants.java
@@ -27,6 +27,8 @@ public class TransportConstants {
 
    public static final String SSL_ENABLED_PROP_NAME = "sslEnabled";
 
+   public static final String SSL_KRB5_CONFIG_PROP_NAME = "sslKrb5Config";
+
    public static final String HTTP_ENABLED_PROP_NAME = "httpEnabled";
 
    public static final String HTTP_CLIENT_IDLE_PROP_NAME = "httpClientIdleTime";
@@ -99,6 +101,8 @@ public class TransportConstants {
 
    public static final String VERIFY_HOST_PROP_NAME = "verifyHost";
 
+   public static final String SNIHOST_PROP_NAME = "sniHost";
+
    public static final String BACKLOG_PROP_NAME = "backlog";
 
    public static final String USE_DEFAULT_SSL_CONTEXT_PROP_NAME = "useDefaultSslContext";
@@ -145,6 +149,10 @@ public class TransportConstants {
 
    public static final boolean DEFAULT_SSL_ENABLED = false;
 
+   public static final String DEFAULT_SSL_KRB5_CONFIG = null;
+
+   public static final String DEFAULT_SNIHOST_CONFIG = null;
+
    public static final boolean DEFAULT_USE_GLOBAL_WORKER_POOL = true;
 
    public static final boolean DEFAULT_USE_EPOLL = true;

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/artemis-server/pom.xml
----------------------------------------------------------------------
diff --git a/artemis-server/pom.xml b/artemis-server/pom.xml
index d5f058b..8e1ecd6 100644
--- a/artemis-server/pom.xml
+++ b/artemis-server/pom.xml
@@ -94,7 +94,7 @@
       </dependency>
       <dependency>
          <groupId>org.apache.directory.server</groupId>
-         <artifactId>apacheds-server-integ</artifactId>
+         <artifactId>apacheds-test-framework</artifactId>
          <version>${directory-version}</version>
          <scope>test</scope>
          <exclusions>
@@ -105,18 +105,11 @@
          </exclusions>
       </dependency>
       <dependency>
-         <groupId>org.apache.directory.server</groupId>
-         <artifactId>apacheds-core-integ</artifactId>
-         <version>${directory-version}</version>
+         <groupId>org.apache.directory.jdbm</groupId>
+         <artifactId>apacheds-jdbm2</artifactId>
+         <version>${directory-jdbm2-version}</version>
          <scope>test</scope>
-         <exclusions>
-            <exclusion>
-               <groupId>bouncycastle</groupId>
-               <artifactId>bcprov-jdk15</artifactId>
-            </exclusion>
-         </exclusions>
       </dependency>
-
       <dependency>
          <groupId>org.apache.activemq</groupId>
          <artifactId>artemis-commons</artifactId>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
index 1fde73f..bc26776 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/remoting/impl/netty/NettyAcceptor.java
@@ -20,10 +20,13 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLParameters;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -68,6 +71,7 @@ import org.apache.activemq.artemis.api.core.management.CoreNotificationType;
 import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl;
 import org.apache.activemq.artemis.core.protocol.ProtocolHandler;
 import org.apache.activemq.artemis.core.remoting.impl.AbstractAcceptor;
+import org.apache.activemq.artemis.core.remoting.impl.TransportConfigurationUtil;
 import org.apache.activemq.artemis.core.remoting.impl.ssl.SSLSupport;
 import org.apache.activemq.artemis.core.security.ActiveMQPrincipal;
 import org.apache.activemq.artemis.core.server.ActiveMQComponent;
@@ -154,6 +158,8 @@ public class NettyAcceptor extends AbstractAcceptor {
 
    private final boolean verifyHost;
 
+   private final String kerb5Config;
+
    private final boolean tcpNoDelay;
 
    private final int backlog;
@@ -217,6 +223,8 @@ public class NettyAcceptor extends AbstractAcceptor {
 
       sslEnabled = ConfigurationHelper.getBooleanProperty(TransportConstants.SSL_ENABLED_PROP_NAME, TransportConstants.DEFAULT_SSL_ENABLED, configuration);
 
+      kerb5Config = ConfigurationHelper.getStringProperty(TransportConstants.SSL_KRB5_CONFIG_PROP_NAME, TransportConstants.DEFAULT_SSL_KRB5_CONFIG, configuration);
+
       remotingThreads = ConfigurationHelper.getIntProperty(TransportConstants.NIO_REMOTING_THREADS_PROPNAME, -1, configuration);
       remotingThreads = ConfigurationHelper.getIntProperty(TransportConstants.REMOTING_THREADS_PROPNAME, remotingThreads, configuration);
 
@@ -423,7 +431,7 @@ public class NettyAcceptor extends AbstractAcceptor {
    public synchronized SslHandler getSslHandler() throws Exception {
       final SSLContext context;
       try {
-         if (keyStorePath == null && TransportConstants.DEFAULT_TRUSTSTORE_PROVIDER.equals(keyStoreProvider))
+         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.");
@@ -433,13 +441,32 @@ public class NettyAcceptor extends AbstractAcceptor {
          ise.initCause(e);
          throw ise;
       }
-      SSLEngine engine;
-      if (verifyHost) {
-         engine = context.createSSLEngine(host, port);
-      } else {
-         engine = context.createSSLEngine();
+      Subject subject = null;
+      if (kerb5Config != null && kerb5Config.length() > 0) {
+         LoginContext loginContext = null;
+         if (Character.isUpperCase(kerb5Config.charAt(0))) {
+            // use as login.config scope
+            loginContext = new LoginContext(kerb5Config);
+         } else {
+            loginContext = new LoginContext("", null, null,
+                    TransportConfigurationUtil.kerb5Config(kerb5Config, false));
+         }
+         loginContext.login();
+
+         subject = loginContext.getSubject();
       }
 
+      SSLEngine engine = Subject.doAs(subject, new PrivilegedExceptionAction<SSLEngine>() {
+         @Override
+         public SSLEngine run() {
+            if (verifyHost) {
+               return context.createSSLEngine(host, port);
+            } else {
+               return context.createSSLEngine();
+            }
+         }
+      });
+
       engine.setUseClientMode(false);
 
       if (needClientAuth)

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 840dda1..ae4bc22 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,7 +164,9 @@
 
       <javac-compiler-id>javac-with-errorprone</javac-compiler-id>
 
-      <directory-version>1.5.7</directory-version>
+      <directory-version>2.0.0-M15</directory-version>
+      <directory-jdbm2-version>2.0.0-M1</directory-jdbm2-version>
+
       <cdi-api.version>1.2</cdi-api.version>
       <geronimo-annotation_1.2_spec.version>1.0</geronimo-annotation_1.2_spec.version>
    </properties>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/tests/integration-tests/pom.xml
----------------------------------------------------------------------
diff --git a/tests/integration-tests/pom.xml b/tests/integration-tests/pom.xml
index 36f1db4..56a4bc8 100644
--- a/tests/integration-tests/pom.xml
+++ b/tests/integration-tests/pom.xml
@@ -249,13 +249,19 @@
       </dependency>
       <dependency>
          <groupId>org.apache.directory.server</groupId>
-         <artifactId>apacheds-server-integ</artifactId>
+         <artifactId>apacheds-test-framework</artifactId>
          <version>${directory-version}</version>
          <scope>test</scope>
+         <exclusions>
+            <exclusion>
+               <groupId>org.apache.directory.api</groupId>
+               <artifactId>api-ldap-schema-data</artifactId>
+            </exclusion>
+         </exclusions>
       </dependency>
       <dependency>
          <groupId>org.apache.directory.server</groupId>
-         <artifactId>apacheds-core-integ</artifactId>
+         <artifactId>apacheds-server-annotations</artifactId>
          <version>${directory-version}</version>
          <scope>test</scope>
          <exclusions>
@@ -328,6 +334,18 @@
             </exclusion>
          </exclusions>
       </dependency>
+      <dependency>
+         <groupId>org.apache.hadoop</groupId>
+         <artifactId>hadoop-minikdc</artifactId>
+         <version>2.8.1</version>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.apache.directory.jdbm</groupId>
+         <artifactId>apacheds-jdbm2</artifactId>
+         <version>${directory-jdbm2-version}</version>
+         <scope>test</scope>
+      </dependency>
    </dependencies>
 
    <build>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLKerb5Test.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLKerb5Test.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLKerb5Test.java
new file mode 100644
index 0000000..6c26667
--- /dev/null
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/ssl/CoreClientOverOneWaySSLKerb5Test.java
@@ -0,0 +1,163 @@
+/*
+ * 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.activemq.artemis.tests.integration.ssl;
+
+import org.apache.activemq.artemis.api.core.RoutingType;
+import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.api.core.TransportConfiguration;
+import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
+import org.apache.activemq.artemis.api.core.client.ClientConsumer;
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientProducer;
+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.ServerLocator;
+import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
+import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
+import org.apache.activemq.artemis.core.security.Role;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
+import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
+import org.apache.activemq.artemis.utils.RandomUtil;
+import org.apache.hadoop.minikdc.MiniKdc;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class CoreClientOverOneWaySSLKerb5Test extends ActiveMQTestBase {
+
+   public static final SimpleString QUEUE = new SimpleString("QueueOverKrb5SSL");
+   public static final String CLIENT_PRINCIPAL = "client";
+   public static final String SNI_HOST = "sni.host";
+   public static final String SERVICE_PRINCIPAL = "host/" + SNI_HOST;
+
+   private MiniKdc kdc;
+   private ActiveMQServer server;
+
+   private TransportConfiguration tc;
+
+   @Test
+   public void testOneWaySSLWithGoodClientCipherSuite() throws Exception {
+
+      // hard coded match, default_keytab_name in minikdc-krb5.conf template
+      File userKeyTab = new File("target/test.krb5.keytab");
+      kdc.createPrincipal(userKeyTab, CLIENT_PRINCIPAL, SERVICE_PRINCIPAL);
+
+      createCustomSslServer();
+
+      tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
+      tc.getParams().put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, getSuitableCipherSuite());
+      tc.getParams().put(TransportConstants.SNIHOST_PROP_NAME, SNI_HOST); // static service name rather than dynamic machine name
+      tc.getParams().put(TransportConstants.SSL_KRB5_CONFIG_PROP_NAME, "client"); // lower case used as principal with default keytab
+      final ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
+
+      ClientSessionFactory sf = null;
+      try {
+         sf = createSessionFactory(locator);
+         ClientSession session = sf.createSession(false, true, true);
+         session.createQueue(CoreClientOverOneWaySSLKerb5Test.QUEUE, RoutingType.ANYCAST, CoreClientOverOneWaySSLKerb5Test.QUEUE);
+         ClientProducer producer = session.createProducer(CoreClientOverOneWaySSLKerb5Test.QUEUE);
+
+         final String text = RandomUtil.randomString();
+         ClientMessage message = createTextMessage(session, text);
+         producer.send(message);
+
+         ClientConsumer consumer = session.createConsumer(CoreClientOverOneWaySSLKerb5Test.QUEUE);
+         session.start();
+
+         ClientMessage m = consumer.receive(1000);
+         Assert.assertNotNull(m);
+         Assert.assertEquals(text, m.getReadOnlyBodyBuffer().readString());
+         System.err.println("m:" + m + ", user:" + m.getValidatedUserID());
+         Assert.assertNotNull("got validated user", m.getValidatedUserID());
+         Assert.assertTrue("krb id in validated user", m.getValidatedUserID().contains(CLIENT_PRINCIPAL));
+
+      } catch (Exception e) {
+         e.printStackTrace();
+         Assert.fail();
+      } finally {
+         if (sf != null) {
+            sf.close();
+         }
+         locator.close();
+      }
+   }
+
+
+   public String getSuitableCipherSuite() throws Exception {
+      return "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
+   }
+
+
+   // Package protected ---------------------------------------------
+
+   @Override
+   @Before
+   public void setUp() throws Exception {
+      super.setUp();
+      kdc = new MiniKdc(MiniKdc.createConf(), temporaryFolder.newFolder("kdc"));
+      kdc.start();
+   }
+
+   @Override
+   @After
+   public void tearDown() throws Exception {
+      try {
+         kdc.stop();
+      } finally {
+         super.tearDown();
+      }
+   }
+
+   private void createCustomSslServer() throws Exception {
+      Map<String, Object> params = new HashMap<>();
+
+      params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
+      params.put(TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, getSuitableCipherSuite());
+      params.put(TransportConstants.SSL_KRB5_CONFIG_PROP_NAME, SERVICE_PRINCIPAL);
+
+      ConfigurationImpl config = createBasicConfig().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params, "nettySSL"));
+      config.setPopulateValidatedUser(true); // so we can verify the kerb5 id is present
+      config.setSecurityEnabled(true);
+
+      server = createServer(false, config);
+      server.start();
+      waitForServerToStart(server);
+
+      final String roleName = "ALLOW_ALL";
+      Role role = new Role(roleName, true, true, true, true, true, true, true, true, true, true);
+      Set<Role> roles = new HashSet<>();
+      roles.add(role);
+      HierarchicalRepository<Set<Role>> securityRepository = server.getSecurityRepository();
+      securityRepository.addMatch(QUEUE.toString(), roles);
+      ActiveMQJAASSecurityManager securityManager = (ActiveMQJAASSecurityManager) server.getSecurityManager();
+
+      final String user = CLIENT_PRINCIPAL + "@" + kdc.getRealm();
+      securityManager.getConfiguration().addUser(user, "");
+      securityManager.getConfiguration().addRole(user, roleName);
+
+      tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY);
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/cda1e018/tests/integration-tests/src/test/resources/minikdc-krb5.conf
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/resources/minikdc-krb5.conf b/tests/integration-tests/src/test/resources/minikdc-krb5.conf
new file mode 100644
index 0000000..0f068ca
--- /dev/null
+++ b/tests/integration-tests/src/test/resources/minikdc-krb5.conf
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+[libdefaults]
+    default_realm = {0}
+    udp_preference_limit = 1
+    default_keytab_name = FILE:target/test.krb5.keytab
+
+[realms]
+    {0} = '{'
+        kdc = {1}:{2}
+    '}'
\ No newline at end of file