QPIDJMS-303: updates to round out GSSAPI/Kerberos authentication handling -Consolidate around login module config file, simplify options handling. -Updates to support for passing credentials via URI/ConnectionFactory. -Only allow the mechanism to be selected if configured to enable it. -Improve handling of init-failure due to e.g config issues. -Tests rework, e.g. reuse mini-kdc etc for efficiency, move temp state to ensure cleanup, drop unused dep, additional handling in testpeer.
Project: http://git-wip-us.apache.org/repos/asf/qpid-jms/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-jms/commit/ce833c7b Tree: http://git-wip-us.apache.org/repos/asf/qpid-jms/tree/ce833c7b Diff: http://git-wip-us.apache.org/repos/asf/qpid-jms/diff/ce833c7b Branch: refs/heads/master Commit: ce833c7b6d72fcff3a5517ede0a22094c86d726a Parents: 6dff7ac Author: Robert Gemmell <rob...@apache.org> Authored: Mon Jul 31 18:22:17 2017 +0100 Committer: Robert Gemmell <rob...@apache.org> Committed: Mon Jul 31 18:22:17 2017 +0100 ---------------------------------------------------------------------- pom.xml | 7 - qpid-jms-client/pom.xml | 6 - .../qpid/jms/provider/amqp/AmqpProvider.java | 20 ++- .../provider/amqp/AmqpSaslAuthenticator.java | 2 +- .../apache/qpid/jms/sasl/AbstractMechanism.java | 11 ++ .../apache/qpid/jms/sasl/GssapiMechanism.java | 86 +++++----- .../org/apache/qpid/jms/sasl/Mechanism.java | 16 ++ .../qpid/jms/sasl/SaslMechanismFinder.java | 10 +- .../integration/SaslGssApiIntegrationTest.java | 161 ++++++++++++------- .../qpid/jms/sasl/AbstractMechanismTest.java | 5 + .../qpid/jms/sasl/AnonymousMechanismTest.java | 7 + .../qpid/jms/sasl/CramMD5MechanismTest.java | 7 + .../qpid/jms/sasl/ExternalMechanismTest.java | 7 + .../qpid/jms/sasl/GssapiMechanismTest.java | 39 +++++ .../qpid/jms/sasl/PlainMechanismTest.java | 7 + .../qpid/jms/sasl/ScramSHA1MechanismTest.java | 11 ++ .../qpid/jms/sasl/ScramSHA256MechanismTest.java | 11 ++ .../qpid/jms/test/testpeer/TestAmqpPeer.java | 85 ++++++---- .../jms/test/testpeer/TestAmqpPeerRunner.java | 2 +- .../SaslGssApiIntegrationTest-login.config | 21 ++- 20 files changed, 356 insertions(+), 165 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index bace1ac..c912587 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,6 @@ <mockito-version>1.10.19</mockito-version> <hamcrest-version>1.3</hamcrest-version> <hadoop-minikdc-version>2.8.1</hadoop-minikdc-version> - <directory-jdbm2-version>2.0.0-M3</directory-jdbm2-version> <!-- Maven Plugin Versions for this Project --> <maven-javacc-plugin-version>2.6</maven-javacc-plugin-version> @@ -188,12 +187,6 @@ <version>${hadoop-minikdc-version}</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> </dependencyManagement> http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/pom.xml ---------------------------------------------------------------------- diff --git a/qpid-jms-client/pom.xml b/qpid-jms-client/pom.xml index 7e6e971..b825bb9 100644 --- a/qpid-jms-client/pom.xml +++ b/qpid-jms-client/pom.xml @@ -98,12 +98,6 @@ <artifactId>hadoop-minikdc</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>org.apache.directory.jdbm</groupId> - <artifactId>apacheds-jdbm2</artifactId> - <scope>test</scope> - </dependency> - </dependencies> <build> http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpProvider.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpProvider.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpProvider.java index abedabc..16a82a0 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpProvider.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpProvider.java @@ -19,6 +19,7 @@ package org.apache.qpid.jms.provider.amqp; import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -1383,18 +1384,15 @@ public class AmqpProvider implements Provider, TransportListener , AmqpResourceP mechanism.setUsername(connectionInfo.getUsername()); mechanism.setPassword(connectionInfo.getPassword()); - if (GssapiMechanism.NAME.equals(mechanism.getName())) { - try { - Map<String, String> props = - PropertyUtil.filterProperties(PropertyUtil.parseQuery(getRemoteURI()), "sasl."); - if (!props.containsKey("serverName")) { - props.put("serverName", remoteURI.getHost()); - } - PropertyUtil.setProperties(mechanism, props); - PropertyUtil.setProperty(mechanism, "options", props); - } catch (Exception badConfig) { - throw new RuntimeException("Failed to apply sasl url params to mechanism: " + mechanism.getName() + ", reason: " + badConfig.toString(), badConfig); + try { + Map<String, String> saslOptions = PropertyUtil.filterProperties(PropertyUtil.parseQuery(getRemoteURI()), "sasl.options."); + if (!saslOptions.containsKey("serverName")) { + saslOptions.put("serverName", remoteURI.getHost()); } + + mechanism.init(Collections.unmodifiableMap(saslOptions)); + } catch (Exception ex) { + throw new RuntimeException("Failed to apply sasl options to mechanism: " + mechanism.getName() + ", reason: " + ex.toString(), ex); } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpSaslAuthenticator.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpSaslAuthenticator.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpSaslAuthenticator.java index bac8e3e..584dc6d 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpSaslAuthenticator.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/AmqpSaslAuthenticator.java @@ -99,11 +99,11 @@ public class AmqpSaslAuthenticator { if (remoteMechanisms != null && remoteMechanisms.length != 0) { mechanism = mechanismFinder.apply(remoteMechanisms); if (mechanism != null) { - sasl.setMechanisms(mechanism.getName()); byte[] response = mechanism.getInitialResponse(); if (response != null) { sasl.send(response, 0, response.length); } + sasl.setMechanisms(mechanism.getName()); } else { recordFailure("Could not find a suitable SASL mechanism for the remote peer using the available credentials.", null); } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/AbstractMechanism.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/AbstractMechanism.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/AbstractMechanism.java index 783029c..098f3e5 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/AbstractMechanism.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/AbstractMechanism.java @@ -16,6 +16,8 @@ */ package org.apache.qpid.jms.sasl; +import java.util.Map; + import javax.security.sasl.SaslException; /** @@ -30,6 +32,10 @@ public abstract class AbstractMechanism implements Mechanism { private String password; @Override + public void init(Map<String, String> options) { + } + + @Override public void verifyCompletion() throws SaslException { } @@ -68,4 +74,9 @@ public abstract class AbstractMechanism implements Mechanism { public String toString() { return "SASL-" + getName(); } + + @Override + public boolean isEnabledByDefault() { + return true; + } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/GssapiMechanism.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/GssapiMechanism.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/GssapiMechanism.java index e2644f8..86627fe 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/GssapiMechanism.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/GssapiMechanism.java @@ -19,16 +19,20 @@ package org.apache.qpid.jms.sasl; import org.apache.qpid.jms.util.PropertyUtil; import javax.security.auth.Subject; -import javax.security.auth.login.AppConfigurationEntry; -import javax.security.auth.login.Configuration; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; + +import java.io.IOException; import java.security.Principal; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.util.HashMap; import java.util.Map; /** @@ -37,12 +41,12 @@ import java.util.Map; public class GssapiMechanism extends AbstractMechanism { public static final String NAME = "GSSAPI"; + private Subject subject; private SaslClient saslClient; private String protocol = "amqp"; private String serverName = null; - private String configScope = null; - private Map<String, String> options = new HashMap<String, String>(); + private String configScope = "amqp-jms-client"; // a gss/sasl service name, x@y, morphs to a krbPrincipal a/y@REALM @@ -57,16 +61,22 @@ public class GssapiMechanism extends AbstractMechanism { } @Override + public boolean isEnabledByDefault() { + // Only enable if given explicit configuration to do so, as we can't discern here + // whether the external configuration is appropriately set to actually allow its use. + return false; + } + + @Override + public void init(Map<String, String> saslOptions) { + PropertyUtil.setProperties(this, saslOptions); + } + + @Override public byte[] getInitialResponse() throws SaslException { try { - LoginContext loginContext = null; - if (configScope != null) { - loginContext = new LoginContext(configScope); - } else { - // inline keytab config using user as principal - loginContext = new LoginContext("", null, null, - kerb5InlineConfig(getUsername(), options)); - } + LoginContext loginContext = new LoginContext(configScope, new CredentialCallbackHandler());; + loginContext.login(); subject = loginContext.getSubject(); @@ -109,39 +119,11 @@ public class GssapiMechanism extends AbstractMechanism { } } - @Override public boolean isApplicable(String username, String password, Principal localPrincipal) { return true; } - public static Configuration kerb5InlineConfig(String principal, final Map<String, String> userOptions) { - final Map<String, String> options = new HashMap<>(); - options.put("principal", principal); - options.put("useKeyTab", "true"); - options.put("storeKey", "true"); - String ticketCache = System.getenv("KRB5CCNAME"); - if (ticketCache != null) { - options.put("ticketCache", ticketCache); - } - options.putAll(PropertyUtil.filterProperties(userOptions, "krb5.")); - return new Configuration() { - @Override - public AppConfigurationEntry[] getAppConfigurationEntry(String name) { - return new AppConfigurationEntry[]{ - new AppConfigurationEntry(getKrb5LoginModuleName(), - AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, - options)}; - } - }; - } - - private static final boolean IBM_JAVA = System.getProperty("java.vendor").contains("IBM"); - private static String getKrb5LoginModuleName() { - return IBM_JAVA ? "com.ibm.security.auth.module.Krb5LoginModule" - : "com.sun.security.auth.module.Krb5LoginModule"; - } - public String getProtocol() { return protocol; } @@ -166,11 +148,23 @@ public class GssapiMechanism extends AbstractMechanism { this.configScope = configScope; } - public Map<String, String> getOptions() { - return options; - } + private class CredentialCallbackHandler implements CallbackHandler { - public void setOptions(Map<String, String> options) { - this.options = options; + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + Callback cb = callbacks[i]; + if (cb instanceof NameCallback) { + ((NameCallback) cb).setName(getUsername()); + } else if (cb instanceof PasswordCallback) { + String pass = getPassword(); + if (pass != null) { + ((PasswordCallback) cb).setPassword(pass.toCharArray()); + } + } else { + throw new UnsupportedCallbackException(cb); + } + } + } } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/Mechanism.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/Mechanism.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/Mechanism.java index ca8225d..53e71f2 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/Mechanism.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/Mechanism.java @@ -17,6 +17,7 @@ package org.apache.qpid.jms.sasl; import java.security.Principal; +import java.util.Map; import javax.security.sasl.SaslException; @@ -62,6 +63,14 @@ public interface Mechanism extends Comparable<Mechanism> { String getName(); /** + * Perform any configuration initiation required by the mechanism. + * + * @param options + * An immutable map of sasl options. Will always be non-null. + */ + void init(Map<String, String> options); + + /** * Create an initial response based on selected mechanism. * * May be null if there is no initial response. @@ -139,4 +148,11 @@ public interface Mechanism extends Comparable<Mechanism> { */ boolean isApplicable(String username, String password, Principal localPrincipal); + /** + * Allows the mechanism to indicate if it is enabled by default, or only when explicitly enabled + * through configuring the permitted sasl mechanisms. + * + * @return true if this Mechanism is enabled by default. + */ + boolean isEnabledByDefault(); } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/SaslMechanismFinder.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/SaslMechanismFinder.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/SaslMechanismFinder.java index 6ca6b9b..ce09489 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/SaslMechanismFinder.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/sasl/SaslMechanismFinder.java @@ -73,10 +73,16 @@ public class SaslMechanismFinder { MechanismFactory factory = findMechanismFactory(remoteMechanism); if (factory != null) { Mechanism mech = factory.createMechanism(); - if(mechRestrictions != null && !mechRestrictions.contains(remoteMechanism)) { + + boolean mechConfigured = mechRestrictions != null && mechRestrictions.contains(remoteMechanism); + if(mechRestrictions != null && !mechConfigured) { LOG.debug("Skipping {} mechanism because it is not in the configured mechanisms restriction set", remoteMechanism); } else if(mech.isApplicable(username, password, localPrincipal)) { - found.add(mech); + if(mech.isEnabledByDefault() || mechConfigured) { + found.add(mech); + } else { + LOG.debug("Skipping {} mechanism as it must be explicitly enabled in the configured sasl mechanisms", mech); + } } else { LOG.debug("Skipping {} mechanism because the available credentials are not sufficient", mech); } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SaslGssApiIntegrationTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SaslGssApiIntegrationTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SaslGssApiIntegrationTest.java index 60f8c73..bcbb060 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SaslGssApiIntegrationTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/SaslGssApiIntegrationTest.java @@ -27,9 +27,10 @@ import org.apache.qpid.jms.JmsConnectionFactory; import org.apache.qpid.jms.test.QpidJmsTestCase; import org.apache.qpid.jms.test.testpeer.TestAmqpPeer; import org.apache.qpid.proton.amqp.Symbol; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Assume; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +39,7 @@ import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSSecurityException; import java.io.File; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; @@ -49,34 +51,40 @@ public class SaslGssApiIntegrationTest extends QpidJmsTestCase { private static final Logger LOG = LoggerFactory.getLogger(SaslGssApiIntegrationTest.class); - private static final Symbol GSSAPI = Symbol.valueOf("GSSAPI"); - private static final String serviceName = "amqp/localhost"; - - private MiniKdc kdc; - private final boolean debug = false; - - @Before - public void setUpKerberos() throws Exception { - - // login.config or url overrides necessary for the IBM krb5 login module - Assume.assumeFalse(System.getProperty("java.vendor").contains("IBM")); - - Path tempDirectory = Files.createTempDirectory("junit.SaslGssApiIntegrationTest."); + private static final String LOGIN_CONFIG = "SaslGssApiIntegrationTest-login.config"; + private static final String GSSAPI = "GSSAPI"; + private static final Symbol ANONYMOUS = Symbol.valueOf("ANONYMOUS"); + private static final Symbol PLAIN = Symbol.valueOf("PLAIN"); + private static final String KRB5_KEYTAB = "target/SaslGssApiIntegrationTest.krb5.keytab"; + private static final String SERVICE_PRINCIPAL = "amqp/localhost"; + private static final String CLIENT_PRINCIPAL_LOGIN_CONFIG = "clientprincipal"; + private static final String CLIENT_PRINCIPAL_FACTORY_USERNAME = "factoryusername"; + private static final String CLIENT_PRINCIPAL_URI_USERNAME = "uriusername"; + private static final String CLIENT_PRINCIPAL_DEFAULT_CONFIG_SCOPE = "defaultscopeprincipal"; + + private static MiniKdc kdc; + private static final boolean DEBUG = false; + + @BeforeClass + public static void setUpKerberos() throws Exception { + Path targetDir = FileSystems.getDefault().getPath("target"); + Path tempDirectory = Files.createTempDirectory(targetDir, "junit.SaslGssApiIntegrationTest."); File root = tempDirectory.toFile(); - root.deleteOnExit(); + kdc = new MiniKdc(MiniKdc.createConf(), new File(root, "kdc")); kdc.start(); // hard coded match, default_keytab_name in minikdc-krb5.conf template - File userKeyTab = new File("target/SaslGssApiIntegrationTest.krb5.keytab"); - kdc.createPrincipal(userKeyTab, "client", serviceName); + File userKeyTab = new File(KRB5_KEYTAB); + kdc.createPrincipal(userKeyTab, CLIENT_PRINCIPAL_LOGIN_CONFIG, CLIENT_PRINCIPAL_FACTORY_USERNAME, + CLIENT_PRINCIPAL_URI_USERNAME, CLIENT_PRINCIPAL_DEFAULT_CONFIG_SCOPE, SERVICE_PRINCIPAL); Keytab kt = Keytab.read(userKeyTab); for (KeytabEntry entry : kt.getEntries()) { LOG.info("KeyTab Kerb PrincipalNames:" + entry.getPrincipalName()); } - if (debug) { + if (DEBUG) { java.util.logging.Logger logger = java.util.logging.Logger.getLogger("javax.security.sasl"); logger.setLevel(java.util.logging.Level.FINEST); logger.addHandler(new java.util.logging.ConsoleHandler()); @@ -86,50 +94,51 @@ public class SaslGssApiIntegrationTest extends QpidJmsTestCase { } } - @After - public void stopKDC() throws Exception { + @AfterClass + public static void cleanUpKerberos() { if (kdc != null) { kdc.stop(); } } - @Test(timeout = 20000) - public void testSaslGssApiKrbConnection() throws Exception { - try (TestAmqpPeer testPeer = new TestAmqpPeer();) { - - testPeer.expectSaslGSSAPI(serviceName); - testPeer.expectOpen(); - - // Each connection creates a session for managing temporary destinations etc - testPeer.expectBegin(); + @Before + @Override + public void setUp() throws Exception { + super.setUp(); - String uriOptions = "?amqp.saslMechanisms=" + GSSAPI.toString(); - ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + testPeer.getServerPort() + uriOptions); - Connection connection = factory.createConnection("client", null); - // Set a clientID to provoke the actual AMQP connection process to occur. - connection.setClientID("clientName"); + Assume.assumeFalse(System.getProperty("java.vendor").contains("IBM")); - testPeer.waitForAllHandlersToComplete(1000); - assertNull(testPeer.getThrowable()); + // NOTE: we may need to isolate this test later if we use login.config in others + setTestSystemProperty("java.security.auth.login.config", + SaslGssApiIntegrationTest.class.getClassLoader().getResource(LOGIN_CONFIG).getPath()); + } - testPeer.expectClose(); - connection.close(); - } + @Test(timeout = 20000) + public void testSaslGssApiKrbConnection() throws Exception { + doSaslGssApiKrbConnectionTestImpl("KRB5-CLIENT", CLIENT_PRINCIPAL_LOGIN_CONFIG + "@EXAMPLE.COM"); } @Test(timeout = 20000) - public void testSaslGssApiKrbConnectionJmsUser() throws Exception { + public void testSaslGssApiKrbConnectionWithDefaultScope() throws Exception { + doSaslGssApiKrbConnectionTestImpl(null, CLIENT_PRINCIPAL_DEFAULT_CONFIG_SCOPE + "@EXAMPLE.COM"); + } + + private void doSaslGssApiKrbConnectionTestImpl(String configScope, String clientAuthIdAtServer) throws Exception { try (TestAmqpPeer testPeer = new TestAmqpPeer();) { - testPeer.expectSaslGSSAPI(serviceName); + testPeer.expectSaslGSSAPI(SERVICE_PRINCIPAL, KRB5_KEYTAB, clientAuthIdAtServer); testPeer.expectOpen(); // Each connection creates a session for managing temporary destinations etc testPeer.expectBegin(); - String uriOptions = "?jms.username=client&amqp.saslMechanisms=" + GSSAPI.toString(); + String uriOptions = "?amqp.saslMechanisms=" + GSSAPI; + if(configScope != null) { + uriOptions += "&sasl.options.configScope=" + configScope; + } + ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + testPeer.getServerPort() + uriOptions); - Connection connection = factory.createConnection(); + Connection connection = factory.createConnection("ignoredusername", null); // Set a clientID to provoke the actual AMQP connection process to occur. connection.setClientID("clientName"); @@ -142,18 +151,22 @@ public class SaslGssApiIntegrationTest extends QpidJmsTestCase { } @Test(timeout = 20000) - public void testSaslGssApiKrb5ConfigOptionOverridePrincipal() throws Exception { + public void testSaslGssApiKrbConnectionWithPrincipalViaJmsUsernameUri() throws Exception { try (TestAmqpPeer testPeer = new TestAmqpPeer();) { - testPeer.expectSaslGSSAPI(serviceName); + testPeer.expectSaslGSSAPI(SERVICE_PRINCIPAL, KRB5_KEYTAB, CLIENT_PRINCIPAL_URI_USERNAME + "@EXAMPLE.COM"); testPeer.expectOpen(); // Each connection creates a session for managing temporary destinations etc testPeer.expectBegin(); - String uriOptions = "?jms.username=getsOverridden&sasl.krb5.principal=client&amqp.saslMechanisms=" + GSSAPI.toString(); + // No password, not needed as using keyTab. + String uriOptions = "?sasl.options.configScope=KRB5-CLIENT-URI-USERNAME-CALLBACK&jms.username=" + + CLIENT_PRINCIPAL_URI_USERNAME +"&amqp.saslMechanisms=" + GSSAPI; ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + testPeer.getServerPort() + uriOptions); + Connection connection = factory.createConnection(); + // Set a clientID to provoke the actual AMQP connection process to occur. connection.setClientID("clientName"); @@ -165,23 +178,22 @@ public class SaslGssApiIntegrationTest extends QpidJmsTestCase { } } - - @Test(timeout = 20000) - public void testSaslGssApiKrbConfigConnection() throws Exception { - setTestSystemProperty("java.security.auth.login.config", - SaslGssApiIntegrationTest.class.getClassLoader().getResource("SaslGssApiIntegrationTest-login.config").getPath()); + public void testSaslGssApiKrbConnectionWithPrincipalViaJmsUsernameConnFactory() throws Exception { try (TestAmqpPeer testPeer = new TestAmqpPeer();) { - testPeer.expectSaslGSSAPI(serviceName); + testPeer.expectSaslGSSAPI(SERVICE_PRINCIPAL, KRB5_KEYTAB, CLIENT_PRINCIPAL_FACTORY_USERNAME + "@EXAMPLE.COM"); testPeer.expectOpen(); // Each connection creates a session for managing temporary destinations etc testPeer.expectBegin(); - String uriOptions = "?sasl.configScope=KRB5-CLIENT&sasl.protocol=amqp&sasl.server=localhost&amqp.saslMechanisms=" + GSSAPI.toString(); + String uriOptions = "?sasl.options.configScope=KRB5-CLIENT-FACTORY-USERNAME-CALLBACK" + "&amqp.saslMechanisms=" + GSSAPI; ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + testPeer.getServerPort() + uriOptions); - Connection connection = factory.createConnection(); + + // No password, not needed as using keyTab. + Connection connection = factory.createConnection(CLIENT_PRINCIPAL_FACTORY_USERNAME, null); + // Set a clientID to provoke the actual AMQP connection process to occur. connection.setClientID("clientName"); @@ -196,22 +208,49 @@ public class SaslGssApiIntegrationTest extends QpidJmsTestCase { @Test(timeout = 20000) public void testSaslGssApiKrbConfigError() throws Exception { final String loginConfigScope = "KRB5-CLIENT-DOES-NOT-EXIST"; - try (TestAmqpPeer testPeer = new TestAmqpPeer();) { + try (TestAmqpPeer testPeer = new TestAmqpPeer();) { testPeer.expectSaslGSSAPIFail(); - String uriOptions = "?sasl.configScope=" + loginConfigScope + "&sasl.protocol=amqp&sasl.server=localhost&amqp.saslMechanisms=" + GSSAPI.toString(); + String uriOptions = "?sasl.options.configScope=" + loginConfigScope + "&amqp.saslMechanisms=" + GSSAPI; ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + testPeer.getServerPort() + uriOptions); - Connection connection = factory.createConnection(); - // Set a clientID to provoke the actual AMQP connection process to occur. - connection.setClientID("clientName"); + factory.createConnection(); - testPeer.expectClose(); - connection.close(); fail("Expect exception on no login config"); } catch (JMSSecurityException expected) { assertTrue(expected.getMessage().contains(loginConfigScope)); } } + @Test(timeout = 20000) + public void testGssapiOnlySelectedWhenPresentIfExplicitlyEnabled() throws Exception { + doMechanismSelectedTestImpl("username", "password", PLAIN, new Symbol[] {Symbol.valueOf(GSSAPI), PLAIN, ANONYMOUS}, false); + doMechanismSelectedTestImpl("username", "password", Symbol.valueOf(GSSAPI), new Symbol[] {Symbol.valueOf(GSSAPI), PLAIN, ANONYMOUS}, true); + } + + private void doMechanismSelectedTestImpl(String username, String password, Symbol clientSelectedMech, Symbol[] serverMechs, boolean enableGssapiExplicitly) throws Exception { + try (TestAmqpPeer testPeer = new TestAmqpPeer();) { + + testPeer.expectFailingSaslAuthentication(serverMechs, clientSelectedMech); + + String uriOptions = "?jms.clientID=myclientid"; + if(enableGssapiExplicitly) { + uriOptions += "&amqp.saslMechanisms=PLAIN," + GSSAPI; + } + ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + testPeer.getServerPort() + uriOptions); + + try { + factory.createConnection(username, password); + fail("Excepted exception to be thrown"); + }catch (JMSSecurityException jmsse) { + // Expected, we deliberately failed the SASL process, + // we only wanted to verify the correct mechanism + // was selected, other tests verify the remainder. + + LOG.info("Caught expected security exception: {}", jmsse.getMessage()); + } + + testPeer.waitForAllHandlersToComplete(1000); + } + } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AbstractMechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AbstractMechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AbstractMechanismTest.java index 768cc74..bbacf02 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AbstractMechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AbstractMechanismTest.java @@ -68,5 +68,10 @@ public class AbstractMechanismTest { public boolean isApplicable(String username, String password, Principal localPrincipal) { return false; } + + @Override + public boolean isEnabledByDefault() { + return false; + } } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AnonymousMechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AnonymousMechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AnonymousMechanismTest.java index 82b686f..9c9da7c 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AnonymousMechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/AnonymousMechanismTest.java @@ -103,4 +103,11 @@ public class AnonymousMechanismTest { } })); } + + @Test + public void testIsEnabledByDefault() { + AnonymousMechanism mech = new AnonymousMechanism(); + + assertTrue("Should be enabled by default", mech.isEnabledByDefault()); + } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/CramMD5MechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/CramMD5MechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/CramMD5MechanismTest.java index 1a6149f..3110147 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/CramMD5MechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/CramMD5MechanismTest.java @@ -85,4 +85,11 @@ public class CramMD5MechanismTest { } })); } + + @Test + public void testIsEnabledByDefault() { + CramMD5Mechanism mech = new CramMD5Mechanism(); + + assertTrue("Should be enabled by default", mech.isEnabledByDefault()); + } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ExternalMechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ExternalMechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ExternalMechanismTest.java index ab613b9..bb9142f 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ExternalMechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ExternalMechanismTest.java @@ -74,4 +74,11 @@ public class ExternalMechanismTest { } })); } + + @Test + public void testIsEnabledByDefault() { + ExternalMechanism mech = new ExternalMechanism(); + + assertTrue("Should be enabled by default", mech.isEnabledByDefault()); + } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/GssapiMechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/GssapiMechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/GssapiMechanismTest.java new file mode 100644 index 0000000..713ebd4 --- /dev/null +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/GssapiMechanismTest.java @@ -0,0 +1,39 @@ +/* + * 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.qpid.jms.sasl; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class GssapiMechanismTest { + + @Test + public void testIsApplicableWithoutCredentials() { + GssapiMechanism mech = new GssapiMechanism(); + + assertTrue("Should be applicable without credentials", mech.isApplicable(null, null, null)); + } + + @Test + public void testIsNotEnabledByDefault() { + GssapiMechanism mech = new GssapiMechanism(); + + assertFalse("Should not be enabled by default", mech.isEnabledByDefault()); + } +} http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/PlainMechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/PlainMechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/PlainMechanismTest.java index ac03286..808c7df 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/PlainMechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/PlainMechanismTest.java @@ -104,4 +104,11 @@ public class PlainMechanismTest { } })); } + + @Test + public void testIsEnabledByDefault() { + PlainMechanism mech = new PlainMechanism(); + + assertTrue("Should be enabled by default", mech.isEnabledByDefault()); + } } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA1MechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA1MechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA1MechanismTest.java index 094e78b..0011fb8 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA1MechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA1MechanismTest.java @@ -16,6 +16,10 @@ */ package org.apache.qpid.jms.sasl; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + /** * The known good used by these tests is taken from the example in RFC 5802 section 5. */ @@ -46,4 +50,11 @@ public class ScramSHA1MechanismTest extends AbstractScramSHAMechanismTestBase { mech.setPassword(PASSWORD); return mech; } + + @Test + public void testIsEnabledByDefault() { + ScramSHA1Mechanism mech = new ScramSHA1Mechanism(); + + assertTrue("Should be enabled by default", mech.isEnabledByDefault()); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA256MechanismTest.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA256MechanismTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA256MechanismTest.java index e917e58..945fcd7 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA256MechanismTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/sasl/ScramSHA256MechanismTest.java @@ -16,6 +16,10 @@ */ package org.apache.qpid.jms.sasl; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + /** * The known good used by these tests is taken from the example in RFC 7677 section 3. */ @@ -46,4 +50,11 @@ public class ScramSHA256MechanismTest extends AbstractScramSHAMechanismTestBase mech.setPassword(PASSWORD); return mech; } + + @Test + public void testIsEnabledByDefault() { + ScramSHA256Mechanism mech = new ScramSHA256Mechanism(); + + assertTrue("Should be enabled by default", mech.isEnabledByDefault()); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java index da1e69a..ffbafa7 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeer.java @@ -21,7 +21,6 @@ package org.apache.qpid.jms.test.testpeer; import static org.apache.qpid.jms.provider.amqp.AmqpSupport.DYNAMIC_NODE_LIFETIME_POLICY; import static org.apache.qpid.jms.provider.amqp.AmqpSupport.GLOBAL; import static org.apache.qpid.jms.provider.amqp.AmqpSupport.SHARED; -import static org.apache.qpid.jms.sasl.GssapiMechanism.kerb5InlineConfig; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.equalTo; @@ -49,6 +48,8 @@ import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.sasl.AuthorizeCallback; import javax.security.sasl.Sasl; @@ -520,12 +521,9 @@ public class TestAmqpPeer implements AutoCloseable new FrameSender( this, FrameType.SASL, 0, saslMechanismsFrame, null))); - - addHandler(new SaslInitMatcher().withMechanism(equalTo(GSSAPI))); - } - public void expectSaslGSSAPI(String serviceName) throws Exception { + public void expectSaslGSSAPI(String serviceName, String keyTab, String clientAuthId) throws Exception { SaslMechanismsFrame saslMechanismsFrame = new SaslMechanismsFrame().setSaslServerMechanisms(GSSAPI); @@ -534,18 +532,30 @@ public class TestAmqpPeer implements AutoCloseable this, FrameType.SASL, 0, saslMechanismsFrame, null))); + // setup server gss context final Map<String, String> options = new HashMap<>(); + options.put("principal", serviceName); + options.put("useKeyTab", "true"); + options.put("keyTab", keyTab); + options.put("storeKey", "true"); options.put("isInitiator", "false"); + Configuration loginCconfiguration = new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + return new AppConfigurationEntry[]{ + new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, + options)}; + } + }; - // setup server gss context - LoginContext loginContext = new LoginContext("", null, null, - kerb5InlineConfig(serviceName, options)); + LoginContext loginContext = new LoginContext("", null, null, loginCconfiguration); loginContext.login(); final Subject serverSubject =loginContext.getSubject(); LOGGER.info("saslServer subject:" + serverSubject.getPrivateCredentials()); - Map<String, ?> config = new HashMap(); + Map<String, ?> config = new HashMap<>(); final CallbackHandler handler = new CallbackHandler() { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { @@ -613,9 +623,8 @@ public class TestAmqpPeer implements AutoCloseable } }); - AtomicBoolean response = new AtomicBoolean(false); - SaslResponseMatcher challengeMatcher = new SaslResponseMatcher().withResponse(new BaseMatcher<Binary>() { - + AtomicBoolean succeeded = new AtomicBoolean(false); + SaslResponseMatcher responseMatcher = new SaslResponseMatcher().withResponse(new BaseMatcher<Binary>() { @Override public void describeTo(Description description) {} @@ -623,8 +632,10 @@ public class TestAmqpPeer implements AutoCloseable public boolean matches(Object o) { final Binary binary = (Binary) o; // validate via sasl + + byte[] additionalData = null; try { - Subject.doAs(serverSubject, new PrivilegedExceptionAction<byte[]>() { + additionalData = Subject.doAs(serverSubject, new PrivilegedExceptionAction<byte[]>() { @Override public byte[] run() throws Exception { LOGGER.info("Evaluate response.. size:" + binary.getLength()); @@ -635,32 +646,48 @@ public class TestAmqpPeer implements AutoCloseable e.printStackTrace(); throw new RuntimeException("failed to evaluate challenge response", e); } - LOGGER.info("Complete:" + saslServer.isComplete()); - return saslServer.isComplete(); + + boolean complete = saslServer.isComplete(); + boolean expectedAuthId = false; + if(complete) { + expectedAuthId = clientAuthId.equals(saslServer.getAuthorizationID()); + LOGGER.info("Authorized ID: " + saslServer.getAuthorizationID()); + } + + LOGGER.info("Complete:" + complete + ", expectedAuthID:" + expectedAuthId +", additionalData:" + additionalData); + + if(complete && expectedAuthId && additionalData == null) { + succeeded.set(true); + return true; + } else { + return false; + } } }).onCompletion(new AmqpPeerRunnable() { @Override public void run() { + SaslOutcomeFrame saslOutcome = new SaslOutcomeFrame(); + if (saslServer.isComplete() && succeeded.get()) { + saslOutcome.setCode(SASL_OK); + } else { + saslOutcome.setCode(SASL_FAIL_AUTH); + } - if (saslServer.isComplete()) { - LOGGER.info("Authorized ID: " + saslServer.getAuthorizationID()); - LOGGER.info("Send Outcome"); - TestAmqpPeer.this.sendFrame( - FrameType.SASL, 0, - new SaslOutcomeFrame().setCode(SASL_OK), - null, - false, 0); + LOGGER.info("Send Outcome"); + TestAmqpPeer.this.sendFrame( + FrameType.SASL, 0, + saslOutcome, + null, + false, 0); - // Now that we processed the SASL layer AMQP header, reset the - // peer to expect the non-SASL AMQP header. - _driverRunnable.expectHeader(); - } + // Now that we processed the SASL layer AMQP header, reset the + // peer to expect the non-SASL AMQP header. + _driverRunnable.expectHeader(); } }); addHandler(saslInitMatcher); - addHandler(challengeMatcher); - + addHandler(responseMatcher); addHandler(new HeaderHandlerImpl(AmqpHeader.HEADER, AmqpHeader.HEADER)); } http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java index 7b3f24f..393e70a 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/test/testpeer/TestAmqpPeerRunner.java @@ -117,7 +117,7 @@ class TestAmqpPeerRunner implements Runnable { ByteBuffer networkInputByteBuffer = ByteBuffer.wrap(networkInputBytes, 0, bytesRead); - LOGGER.debug("Read: {}", new Binary(networkInputBytes, 0, bytesRead)); + LOGGER.debug("Read: {} ({} bytes)", new Binary(networkInputBytes, 0, bytesRead), bytesRead); try { _testFrameParser.input(networkInputByteBuffer); http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/ce833c7b/qpid-jms-client/src/test/resources/SaslGssApiIntegrationTest-login.config ---------------------------------------------------------------------- diff --git a/qpid-jms-client/src/test/resources/SaslGssApiIntegrationTest-login.config b/qpid-jms-client/src/test/resources/SaslGssApiIntegrationTest-login.config index 6aa4123..edd7fc1 100644 --- a/qpid-jms-client/src/test/resources/SaslGssApiIntegrationTest-login.config +++ b/qpid-jms-client/src/test/resources/SaslGssApiIntegrationTest-login.config @@ -17,7 +17,26 @@ KRB5-CLIENT { com.sun.security.auth.module.Krb5LoginModule required + principal="clientprincipal" + useKeyTab=true + keytab="target/SaslGssApiIntegrationTest.krb5.keytab"; +}; + +KRB5-CLIENT-URI-USERNAME-CALLBACK { + com.sun.security.auth.module.Krb5LoginModule required + useKeyTab=true + keytab="target/SaslGssApiIntegrationTest.krb5.keytab"; +}; + +KRB5-CLIENT-FACTORY-USERNAME-CALLBACK { + com.sun.security.auth.module.Krb5LoginModule required + useKeyTab=true + keytab="target/SaslGssApiIntegrationTest.krb5.keytab"; +}; + +amqp-jms-client { + com.sun.security.auth.module.Krb5LoginModule required + principal="defaultscopeprincipal" useKeyTab=true - principal="client" keytab="target/SaslGssApiIntegrationTest.krb5.keytab"; }; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org