You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2020/05/05 16:58:04 UTC

[qpid-broker-j] branch master updated: QPID-8426: [Broker-J] Make Kerberos tests passing on IBM JDK

This is an automated email from the ASF dual-hosted git repository.

orudyy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git


The following commit(s) were added to refs/heads/master by this push:
     new e9a23e3  QPID-8426: [Broker-J] Make Kerberos tests passing on IBM JDK
e9a23e3 is described below

commit e9a23e36d81ca0fb16ef5b4fcfff387fe7534b5c
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Tue May 5 16:53:08 2020 +0100

    QPID-8426: [Broker-J] Make Kerberos tests passing on IBM JDK
---
 .../manager/KerberosAuthenticationManagerTest.java |  49 +++----
 .../SimpleLDAPAuthenticationManagerTest.java       |  14 +-
 .../auth/manager/SpnegoAuthenticatorTest.java      |  53 +++-----
 .../qpid/server/test/EmbeddedKdcResource.java      |  28 +---
 .../apache/qpid/server/test/KerberosUtilities.java | 151 ++++++++++++++++++---
 broker-core/src/test/resources/login.ibm.config    |  51 +++++++
 .../java/org/apache/qpid/test/utils/JvmVendor.java |  25 +++-
 .../org/apache/qpid/test/utils/UnitTestBase.java   |  18 +--
 8 files changed, 253 insertions(+), 136 deletions(-)

diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java
index 4e2c922..9211710 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java
@@ -19,20 +19,22 @@
 
 package org.apache.qpid.server.security.auth.manager;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager.GSSAPI_MECHANISM;
-import static org.hamcrest.Matchers.not;
+import static org.apache.qpid.server.test.KerberosUtilities.ACCEPT_SCOPE;
+import static org.apache.qpid.server.test.KerberosUtilities.CLIENT_PRINCIPAL_FULL_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.CLIENT_PRINCIPAL_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.HOST_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.LOGIN_CONFIG;
+import static org.apache.qpid.server.test.KerberosUtilities.REALM;
+import static org.apache.qpid.server.test.KerberosUtilities.SERVER_PROTOCOL;
+import static org.apache.qpid.server.test.KerberosUtilities.SERVICE_PRINCIPAL_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.File;
-import java.net.InetAddress;
-import java.net.URLDecoder;
-import java.nio.file.Path;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Base64;
@@ -46,7 +48,6 @@ import javax.security.auth.login.LoginContext;
 import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslClient;
 
-import org.ietf.jgss.GSSException;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -62,25 +63,19 @@ import org.apache.qpid.server.security.auth.sasl.SaslSettings;
 import org.apache.qpid.server.test.EmbeddedKdcResource;
 import org.apache.qpid.server.test.KerberosUtilities;
 import org.apache.qpid.server.util.StringUtil;
-import org.apache.qpid.test.utils.JvmVendor;
 import org.apache.qpid.test.utils.SystemPropertySetter;
 import org.apache.qpid.test.utils.UnitTestBase;
 
 public class KerberosAuthenticationManagerTest extends UnitTestBase
 {
-    private static final String LOGIN_CONFIG = "login.config";
-    private static final String REALM = "QPID.ORG";
-    private static final String HOST_NAME = InetAddress.getLoopbackAddress().getCanonicalHostName();
-    private static final String SERVER_PROTOCOL = "AMQP";
-    private static final String SERVICE_PRINCIPAL_NAME = SERVER_PROTOCOL + "/" + HOST_NAME;
-    private static final String SERVER_PRINCIPAL_FULL_NAME = SERVICE_PRINCIPAL_NAME + "@" + REALM;
-    private static final String CLIENT_PRINCIPAL_NAME = "client";
-    private static final String CLIENT_PRINCIPAL_FULL_NAME = CLIENT_PRINCIPAL_NAME + "@" + REALM;
 
     private static final KerberosUtilities UTILS = new KerberosUtilities();
 
     @ClassRule
-    public static final EmbeddedKdcResource KDC = new EmbeddedKdcResource(HOST_NAME, 0, "QpidTestKerberosServer", REALM);
+    public static final EmbeddedKdcResource KDC = new EmbeddedKdcResource(HOST_NAME,
+                                                                          0,
+                                                                          "QpidTestKerberosServer",
+                                                                          REALM);
 
     @ClassRule
     public static final SystemPropertySetter SYSTEM_PROPERTY_SETTER = new SystemPropertySetter();
@@ -93,20 +88,15 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
     @BeforeClass
     public static void createKeyTabs() throws Exception
     {
-        assumeThat(getJvmVendor(), not(JvmVendor.IBM));
-        KDC.createPrincipal("broker.keytab", SERVER_PRINCIPAL_FULL_NAME);
-        _clientKeyTabFile = KDC.createPrincipal("client.keytab", CLIENT_PRINCIPAL_FULL_NAME);
-        final Path loginConfig = UTILS.transformLoginConfig(LOGIN_CONFIG, HOST_NAME);
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config",
-                                                 URLDecoder.decode(loginConfig.toFile().getAbsolutePath(), UTF_8.name()));
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("javax.security.auth.useSubjectCredsOnly", "false");
+        UTILS.prepareConfiguration(HOST_NAME, SYSTEM_PROPERTY_SETTER);
+        _clientKeyTabFile = UTILS.prepareKeyTabs(KDC);
     }
 
     @Before
     public void setUp() throws Exception
     {
         Map<String, String> context = Collections.singletonMap(KerberosAuthenticationManager.GSSAPI_SPNEGO_CONFIG,
-                                                               "com.sun.security.jgss.accept");
+                                                               ACCEPT_SCOPE);
         final Map<String, Object> attributes = new HashMap<>();
         attributes.put(AuthenticationProvider.NAME, getTestName());
         attributes.put(AuthenticationProvider.CONTEXT, context);
@@ -161,7 +151,7 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
     public void testCreateKerberosAuthenticationProvidersWithNonExistingJaasLoginModule()
     {
         when(_broker.getChildren(AuthenticationProvider.class)).thenReturn(Collections.emptySet());
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config",
+        SYSTEM_PROPERTY_SETTER.setSystemProperty(LOGIN_CONFIG,
                                                  "config.module." + System.nanoTime());
         final Map<String, Object> attributes = Collections.singletonMap(AuthenticationProvider.NAME, getTestName());
         final KerberosAuthenticationManager kerberosAuthenticationProvider =
@@ -178,10 +168,11 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
     }
 
     @Test
-    public void testAuthenticateUsingNegotiationToken() throws GSSException
+    public void testAuthenticateUsingNegotiationToken() throws Exception
     {
-        final String token =
-                Base64.getEncoder().encodeToString(UTILS.buildToken(CLIENT_PRINCIPAL_NAME, SERVICE_PRINCIPAL_NAME));
+        byte[] negotiationTokenBytes =
+                UTILS.buildToken(CLIENT_PRINCIPAL_NAME, _clientKeyTabFile, SERVICE_PRINCIPAL_NAME);
+        final String token = Base64.getEncoder().encodeToString(negotiationTokenBytes);
         final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
 
         final AuthenticationResult result = _kerberosAuthenticationProvider.authenticate(authenticationHeader);
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
index ddbb5c6..b27d601 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
@@ -20,19 +20,15 @@ package org.apache.qpid.server.security.auth.manager;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.qpid.server.security.auth.manager.CachingAuthenticationProvider.AUTHENTICATION_CACHE_MAX_SIZE;
-import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.net.URLDecoder;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.security.Principal;
@@ -89,7 +85,6 @@ import org.apache.qpid.server.security.auth.AuthenticationResult;
 import org.apache.qpid.server.security.auth.SocketConnectionPrincipal;
 import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
 import org.apache.qpid.server.security.auth.sasl.SaslSettings;
-import org.apache.qpid.test.utils.JvmVendor;
 import org.apache.qpid.server.test.KerberosUtilities;
 import org.apache.qpid.test.utils.SystemPropertySetter;
 import org.apache.qpid.test.utils.TestFileUtils;
@@ -147,7 +142,6 @@ public class SimpleLDAPAuthenticationManagerTest extends UnitTestBase
     private static final String HOSTNAME = "localhost";
     private static final String BROKER_PRINCIPAL = "service/" + HOSTNAME;
     private static final String LINE_SEPARATOR = System.lineSeparator();
-    private static final String LOGIN_CONFIG = "login.config";
     private static final String LOGIN_SCOPE = "ldap-gssapi-bind";
     private static final AtomicBoolean KERBEROS_SETUP = new AtomicBoolean();
     private static final KerberosUtilities UTILS = new KerberosUtilities();
@@ -367,7 +361,6 @@ public class SimpleLDAPAuthenticationManagerTest extends UnitTestBase
 
     private void setUpKerberosAndJaas() throws Exception
     {
-        assumeThat(getJvmVendor(), not(JvmVendor.IBM));
         if (KERBEROS_SETUP.compareAndSet(false, true))
         {
             setUpKerberos();
@@ -401,14 +394,11 @@ public class SimpleLDAPAuthenticationManagerTest extends UnitTestBase
         createPrincipal("Service", "LDAP Service", "ldap", UUID.randomUUID().toString(), servicePrincipalName);
     }
 
-    private void setUpJaas() throws LdapException, IOException
+    private void setUpJaas() throws Exception
     {
         createKeyTab(BROKER_PRINCIPAL);
 
-        final Path loginConfig = UTILS.transformLoginConfig(LOGIN_CONFIG, InetAddress.getLoopbackAddress().getCanonicalHostName());
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config",
-                                                 URLDecoder.decode(loginConfig.toFile().getAbsolutePath(), UTF_8.name()));
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("sun.security.krb5.debug", "true");
+        UTILS.prepareConfiguration(KerberosUtilities.HOST_NAME, SYSTEM_PROPERTY_SETTER);
     }
 
     private String createKrb5Conf(final int port) throws IOException
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java
index 28c87e5..bbd65a4 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java
@@ -19,23 +19,21 @@
 
 package org.apache.qpid.server.security.auth.manager;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.hamcrest.Matchers.not;
+import static org.apache.qpid.server.test.KerberosUtilities.ACCEPT_SCOPE;
+import static org.apache.qpid.server.test.KerberosUtilities.HOST_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.REALM;
+import static org.apache.qpid.server.test.KerberosUtilities.SERVICE_PRINCIPAL_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import java.net.InetAddress;
-import java.net.URLDecoder;
-import java.nio.file.Path;
+import java.io.File;
 import java.security.Principal;
 import java.util.Base64;
 import java.util.Map;
 
-import org.ietf.jgss.GSSException;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -45,18 +43,13 @@ import org.apache.qpid.server.security.TokenCarryingPrincipal;
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 import org.apache.qpid.server.test.EmbeddedKdcResource;
 import org.apache.qpid.server.test.KerberosUtilities;
-import org.apache.qpid.test.utils.JvmVendor;
 import org.apache.qpid.test.utils.SystemPropertySetter;
 import org.apache.qpid.test.utils.UnitTestBase;
 
 public class SpnegoAuthenticatorTest extends UnitTestBase
 {
-    private static final String CLIENT_NAME = "client";
-    private static final String HOST_NAME = InetAddress.getLoopbackAddress().getCanonicalHostName();
-    private static final String SERVER_NAME = "AMQP/" + HOST_NAME;
     private static final String ANOTHER_SERVICE = "foo/" + HOST_NAME;
-    private static final String REALM = "QPID.ORG";
-    private static final String LOGIN_CONFIG = "login.config";
+    private static final String ANOTHER_SERVICE_FULL_NAME = ANOTHER_SERVICE + "@" + REALM;
     private static final KerberosUtilities UTILS = new KerberosUtilities();
 
     @ClassRule
@@ -64,6 +57,7 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
 
     @ClassRule
     public static final SystemPropertySetter SYSTEM_PROPERTY_SETTER = new SystemPropertySetter();
+    private static File _clientKeyTab;
 
     private SpnegoAuthenticator _spnegoAuthenticator;
     private KerberosAuthenticationManager _kerberosAuthenticationManager;
@@ -71,30 +65,25 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
     @BeforeClass
     public static void createKeyTabs() throws Exception
     {
-        assumeThat(getJvmVendor(), not(JvmVendor.IBM));
-        KDC.createPrincipal("broker.keytab", SERVER_NAME + "@" + REALM);
-        KDC.createPrincipal("client.keytab", CLIENT_NAME + "@" + REALM);
-        KDC.createPrincipal("another.keytab", ANOTHER_SERVICE + "@" + REALM);
-        final Path loginConfig = UTILS.transformLoginConfig(LOGIN_CONFIG, HOST_NAME);
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config",
-                                                 URLDecoder.decode(loginConfig.toFile().getAbsolutePath(), UTF_8.name()));
-        SYSTEM_PROPERTY_SETTER.setSystemProperty("javax.security.auth.useSubjectCredsOnly", "false");
+        KDC.createPrincipal("another.keytab", ANOTHER_SERVICE_FULL_NAME);
+        UTILS.prepareConfiguration(HOST_NAME, SYSTEM_PROPERTY_SETTER);
+        _clientKeyTab = UTILS.prepareKeyTabs(KDC);
     }
 
     @Before
     public void setUp()
     {
         _kerberosAuthenticationManager = mock(KerberosAuthenticationManager.class);
-        when(_kerberosAuthenticationManager.getSpnegoLoginConfigScope()).thenReturn("com.sun.security.jgss.accept");
+        when(_kerberosAuthenticationManager.getSpnegoLoginConfigScope()).thenReturn(ACCEPT_SCOPE);
         when(_kerberosAuthenticationManager.isStripRealmFromPrincipalName()).thenReturn(true);
 
         _spnegoAuthenticator = new SpnegoAuthenticator(_kerberosAuthenticationManager);
     }
 
     @Test
-    public void testAuthenticate() throws GSSException
+    public void testAuthenticate() throws Exception
     {
-        final String token = Base64.getEncoder().encodeToString(buildToken(SERVER_NAME));
+        final String token = Base64.getEncoder().encodeToString(buildToken(SERVICE_PRINCIPAL_NAME));
         final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
 
         final AuthenticationResult result = _spnegoAuthenticator.authenticate(authenticationHeader);
@@ -103,7 +92,7 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
         assertEquals(AuthenticationResult.AuthenticationStatus.SUCCESS, result.getStatus());
         final Principal principal = result.getMainPrincipal();
         assertTrue(principal instanceof TokenCarryingPrincipal);
-        assertEquals(CLIENT_NAME, principal.getName());
+        assertEquals(KerberosUtilities.CLIENT_PRINCIPAL_NAME, principal.getName());
 
         final Map<String, String> tokens = ((TokenCarryingPrincipal)principal).getTokens();
         assertNotNull(tokens);
@@ -119,9 +108,9 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
     }
 
     @Test
-    public void testAuthenticateNoNegotiatePrefix() throws GSSException
+    public void testAuthenticateNoNegotiatePrefix() throws Exception
     {
-        final String token = Base64.getEncoder().encodeToString(buildToken(SERVER_NAME));
+        final String token = Base64.getEncoder().encodeToString(buildToken(SERVICE_PRINCIPAL_NAME));
         final AuthenticationResult result = _spnegoAuthenticator.authenticate(token);
         assertNotNull(result);
         assertEquals(AuthenticationResult.AuthenticationStatus.ERROR, result.getStatus());
@@ -146,10 +135,10 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
     }
 
     @Test
-    public void testAuthenticateWrongConfigName() throws GSSException
+    public void testAuthenticateWrongConfigName() throws Exception
     {
         when(_kerberosAuthenticationManager.getSpnegoLoginConfigScope()).thenReturn("foo");
-        final String token = Base64.getEncoder().encodeToString(buildToken(SERVER_NAME));
+        final String token = Base64.getEncoder().encodeToString(buildToken(SERVICE_PRINCIPAL_NAME));
         final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
 
         final AuthenticationResult result = _spnegoAuthenticator.authenticate(authenticationHeader);
@@ -158,7 +147,7 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
     }
 
     @Test
-    public void testAuthenticateWrongServer() throws GSSException
+    public void testAuthenticateWrongServer() throws Exception
     {
         final String token = Base64.getEncoder().encodeToString(buildToken(ANOTHER_SERVICE));
         final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
@@ -168,8 +157,8 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
         assertEquals(AuthenticationResult.AuthenticationStatus.ERROR, result.getStatus());
     }
 
-    private byte[] buildToken(final String anotherService) throws GSSException
+    private byte[] buildToken(final String anotherService) throws Exception
     {
-        return UTILS.buildToken(CLIENT_NAME, anotherService);
+        return UTILS.buildToken(KerberosUtilities.CLIENT_PRINCIPAL_NAME, _clientKeyTab, anotherService);
     }
 }
diff --git a/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java b/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java
index 07e20b3..8224189 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java
@@ -21,11 +21,11 @@ package org.apache.qpid.server.test;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.nio.file.FileSystems;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
@@ -46,11 +46,6 @@ public class EmbeddedKdcResource extends ExternalResource
     private final List<File> _createdFiles = new ArrayList<>();
     private volatile File _kdcDirectory;
 
-    public EmbeddedKdcResource(final String realm)
-    {
-        this(InetAddress.getLoopbackAddress().getCanonicalHostName(), 0, "QpidTestKerberosServer", realm);
-    }
-
     public EmbeddedKdcResource(final String host, final int port, final String serviceName, final String realm)
     {
         _realm = realm;
@@ -150,7 +145,8 @@ public class EmbeddedKdcResource extends ExternalResource
     public File createPrincipal(String keyTabFileName, String... principals)
             throws Exception
     {
-        final File ketTabFile = createFile(keyTabFileName);
+        final Path ketTabPath = Paths.get("target", keyTabFileName);
+        final File ketTabFile = ketTabPath.toFile();
         _createdFiles.add(ketTabFile);
         createPrincipal(ketTabFile, principals);
         return ketTabFile;
@@ -176,22 +172,4 @@ public class EmbeddedKdcResource extends ExternalResource
         }
     }
 
-    private static File createFile(final String keyTabFile) throws IOException
-    {
-        final File target = FileSystems.getDefault().getPath("target").toFile();
-        final File file = new File(target, keyTabFile);
-        if (file.exists())
-        {
-            if (!file.delete())
-            {
-                throw new IOException(String.format("Cannot delete existing file '%s'", keyTabFile));
-            }
-        }
-        if (!file.createNewFile())
-        {
-            throw new IOException(String.format("Cannot create file '%s'", keyTabFile));
-        }
-        return file;
-    }
-
 }
diff --git a/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java b/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java
index 8bfd077..903551d 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java
@@ -25,11 +25,16 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
 import java.net.URL;
+import java.net.URLDecoder;
 import java.nio.file.Files;
+import java.nio.file.LinkOption;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
+import java.security.PrivilegedExceptionAction;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -56,15 +61,90 @@ import org.ietf.jgss.Oid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.qpid.test.utils.JvmVendor;
+import org.apache.qpid.test.utils.SystemPropertySetter;
+
 public class KerberosUtilities
 {
+    public static final String REALM = "QPID.ORG";
+    public static final String HOST_NAME = InetAddress.getLoopbackAddress().getCanonicalHostName();
+    public static final String CLIENT_PRINCIPAL_NAME = "client";
+    public static final String CLIENT_PRINCIPAL_FULL_NAME = CLIENT_PRINCIPAL_NAME + "@" + REALM;
+    public static final String SERVER_PROTOCOL = "AMQP";
+    public static final String SERVICE_PRINCIPAL_NAME = SERVER_PROTOCOL + "/" + HOST_NAME;
+    private static final String SUN_ACCEPT_SCOPE = "com.sun.security.jgss.accept";
+    private static final String IBM_ACCEPT_SCOPE = "com.ibm.security.jgss.krb5.accept";
+    public static final String ACCEPT_SCOPE = isIBM() ? IBM_ACCEPT_SCOPE : SUN_ACCEPT_SCOPE;
+    private static final String USE_SUBJECT_CREDS_ONLY = "javax.security.auth.useSubjectCredsOnly";
+    public static final String LOGIN_CONFIG = "java.security.auth.login.config";
+
     private static final Logger LOGGER = LoggerFactory.getLogger(KerberosUtilities.class);
     private static final String IBM_LOGIN_MODULE_CLASS = "com.ibm.security.auth.module.Krb5LoginModule";
     private static final String SUN_LOGIN_MODULE_CLASS = "com.sun.security.auth.module.Krb5LoginModule";
-    private static final String KERBEROS_LOGIN_MODULE_CLASS =
-            System.getProperty("java.vendor").contains("IBM") ? IBM_LOGIN_MODULE_CLASS : SUN_LOGIN_MODULE_CLASS;
+    private static final String KERBEROS_LOGIN_MODULE_CLASS = isIBM() ? IBM_LOGIN_MODULE_CLASS : SUN_LOGIN_MODULE_CLASS;
+    private static final String LOGIN_CONFIG_RESOURCE = "login.config";
+    private static final String LOGIN_IBM_CONFIG_RESOURCE = "login.ibm.config";
+    private static final String SERVICE_PRINCIPAL_FULL_NAME = SERVICE_PRINCIPAL_NAME + "@" + REALM;
+    private static final String BROKER_KEYTAB = "broker.keytab";
+    private static final String CLIENT_KEYTAB = "client.keytab";
+
+
+    public File prepareKeyTabs(final EmbeddedKdcResource kdc) throws Exception
+    {
+        final File clientKeyTabFile;
+        kdc.createPrincipal(BROKER_KEYTAB, SERVICE_PRINCIPAL_FULL_NAME);
+        clientKeyTabFile = kdc.createPrincipal(CLIENT_KEYTAB, CLIENT_PRINCIPAL_FULL_NAME);
+        return clientKeyTabFile;
+    }
+
+    public void prepareConfiguration(final String hostName, final SystemPropertySetter systemPropertySetter)
+            throws IOException
+    {
+        final Path loginConfig = transformLoginConfig(hostName);
+        systemPropertySetter.setSystemProperty(LOGIN_CONFIG,
+                                               URLDecoder.decode(loginConfig.toFile().getAbsolutePath(), UTF_8.name()));
+        systemPropertySetter.setSystemProperty(USE_SUBJECT_CREDS_ONLY, "false");
+    }
+
+    public byte[] buildToken(String clientPrincipalName, File clientKeyTabFile, String targetServerPrincipalName)
+            throws Exception
+    {
+        final LoginContext lc = createKerberosKeyTabLoginContext("test",
+                                                                 clientPrincipalName,
+                                                                 clientKeyTabFile);
+
+        Subject clientSubject = null;
+        String useSubjectCredsOnly = System.getProperty(USE_SUBJECT_CREDS_ONLY);
+        try
+        {
+            lc.login();
+            clientSubject = lc.getSubject();
+            debug("LoginContext subject {}", clientSubject);
+            System.setProperty(USE_SUBJECT_CREDS_ONLY, "true");
+            return Subject.doAs(clientSubject,
+                                (PrivilegedExceptionAction<byte[]>) () -> buildTokenWithinSubjectWithKerberosTicket(
+                                        clientPrincipalName,
+                                        targetServerPrincipalName));
+        }
+        finally
+        {
+            if (useSubjectCredsOnly == null)
+            {
+                System.clearProperty(USE_SUBJECT_CREDS_ONLY);
+            }
+            else
+            {
+                System.setProperty(USE_SUBJECT_CREDS_ONLY, useSubjectCredsOnly);
+            }
+            if (clientSubject != null)
+            {
+                lc.logout();
+            }
+        }
+    }
 
-    public byte[] buildToken(String clientPrincipalName, String targetServerPrincipalName) throws GSSException
+    private byte[] buildTokenWithinSubjectWithKerberosTicket(String clientPrincipalName,
+                                                             String targetServerPrincipalName) throws GSSException
     {
         debug("Building token for client principal '{}' and server principal '{}'",
               clientPrincipalName,
@@ -72,10 +152,19 @@ public class KerberosUtilities
 
         final GSSManager manager = GSSManager.getInstance();
         final GSSName clientName = manager.createName(clientPrincipalName, GSSName.NT_USER_NAME);
-        final GSSCredential credential = manager.createCredential(clientName,
-                                                                  GSSCredential.DEFAULT_LIFETIME,
-                                                                  new Oid("1.2.840.113554.1.2.2"),
-                                                                  GSSCredential.INITIATE_ONLY);
+        final GSSCredential credential;
+        try
+        {
+            credential = manager.createCredential(clientName,
+                                                  GSSCredential.DEFAULT_LIFETIME,
+                                                  new Oid("1.2.840.113554.1.2.2"),
+                                                  GSSCredential.INITIATE_ONLY);
+        }
+        catch (GSSException e)
+        {
+            debug("Failure to create credential for {}", clientName, e);
+            throw e;
+        }
 
         debug("Client credential '{}'", credential);
 
@@ -190,10 +279,19 @@ public class KerberosUtilities
         {
             final Map<String, String> options = new HashMap<>();
             options.put("principal", principalName);
-            options.put("useKeyTab", TRUE.toString());
-            options.put("keyTab", keyTabFile.getAbsolutePath());
-            options.put("refreshKrb5Config", TRUE.toString());
-            options.put("doNotPrompt", TRUE.toString());
+
+            if (isIBM())
+            {
+                options.put("useKeytab", keyTabFile.getAbsolutePath());
+                options.put("credsType", "both");
+            }
+            else
+            {
+                options.put("keyTab", keyTabFile.getAbsolutePath());
+                options.put("useKeyTab", TRUE.toString());
+                options.put("doNotPrompt", TRUE.toString());
+                options.put("refreshKrb5Config", TRUE.toString());
+            }
             _entry = new AppConfigurationEntry(KERBEROS_LOGIN_MODULE_CLASS,
                                                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                                                options);
@@ -220,15 +318,16 @@ public class KerberosUtilities
         }
     }
 
-    public Path transformLoginConfig(String resourceName, String hostName) throws IOException
+    private Path transformLoginConfig(String hostName) throws IOException
     {
+        final String resourceName = isIBM() ? LOGIN_IBM_CONFIG_RESOURCE : LOGIN_CONFIG_RESOURCE;
         final URL resource = KerberosUtilities.class.getClassLoader().getResource(resourceName);
         if (resource == null)
         {
             throw new IllegalArgumentException(String.format("Unknown resource '%s'", resourceName));
         }
         final String config;
-        try(InputStream is = resource.openStream())
+        try (InputStream is = resource.openStream())
         {
             config = new String(ByteStreams.toByteArray(is), UTF_8);
         }
@@ -236,18 +335,30 @@ public class KerberosUtilities
         {
             throw new IOException(String.format("Failed to load resource '%s'", resource.toExternalForm()), e);
         }
-        String newConfig = config.replace("AMQP/localhost", "AMQP/" + hostName);
-        if (IBM_LOGIN_MODULE_CLASS.equals(KERBEROS_LOGIN_MODULE_CLASS))
-        {
-            newConfig = newConfig.replace(SUN_LOGIN_MODULE_CLASS, IBM_LOGIN_MODULE_CLASS);
-        }
-        final Path file = Paths.get("target", resourceName);
+        final String newConfig = config.replace("AMQP/localhost", "AMQP/" + hostName)
+                                       .replace("target/" + BROKER_KEYTAB, toAbsolutePath(BROKER_KEYTAB))
+                                       .replace("target/" + CLIENT_KEYTAB, toAbsolutePath(CLIENT_KEYTAB));
+
+        final Path file = Paths.get("target", LOGIN_CONFIG_RESOURCE);
         Files.write(file,
                     newConfig.getBytes(UTF_8),
                     StandardOpenOption.WRITE,
                     StandardOpenOption.CREATE,
                     StandardOpenOption.TRUNCATE_EXISTING);
-        return file;
+        return file.toRealPath(LinkOption.NOFOLLOW_LINKS);
+    }
+
+    private String toAbsolutePath(String fileName)
+    {
+        final Path path = Paths.get("target", fileName)
+                               .toAbsolutePath()
+                               .normalize();
+        return path.toUri().getPath();
+    }
+
+    private static boolean isIBM()
+    {
+        return JvmVendor.getJvmVendor() == JvmVendor.IBM;
     }
 
 }
diff --git a/broker-core/src/test/resources/login.ibm.config b/broker-core/src/test/resources/login.ibm.config
new file mode 100644
index 0000000..6e85f6e
--- /dev/null
+++ b/broker-core/src/test/resources/login.ibm.config
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+ldap-gssapi-bind {
+    com.ibm.security.auth.module.Krb5LoginModule required
+    credsType="both"
+    principal="service/localhost@QPID.ORG"
+    useKeytab="target/kerberos.keytab";
+};
+
+ldap-gssapi-bind-broken {
+    com.ibm.security.auth.module.Krb5LoginModule required
+    credsType="both"
+    principal="service/localhost@QPID.ORG"
+    useKeytab="target/kerberos-non-existing.keytab";
+};
+
+qpid-broker-j {
+    com.ibm.security.auth.module.Krb5LoginModule required
+    credsType="both"
+    principal="service/localhost@QPID.ORG"
+    useKeytab="target/kerberos.keytab";
+};
+
+com.ibm.security.jgss.krb5.accept {
+    com.ibm.security.auth.module.Krb5LoginModule required
+    credsType="acceptor"
+    principal="AMQP/localhost@QPID.ORG"
+    useKeytab="target/broker.keytab";
+};
+
+com.ibm.security.jgss.krb5.initiate {
+    com.ibm.security.auth.module.Krb5LoginModule required
+    credsType="both"
+    principal="client@QPID.ORG"
+    useKeytab="target/client.keytab";
+};
diff --git a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java
index bd176d7..9ed7c28 100644
--- a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java
+++ b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java
@@ -20,10 +20,33 @@
 
 package org.apache.qpid.test.utils;
 
+import com.google.common.base.StandardSystemProperty;
+
 public enum JvmVendor
 {
     ORACLE,
     IBM,
     OPENJDK,
-    UNKNOWN
+    UNKNOWN;
+
+    public static JvmVendor getJvmVendor()
+    {
+        final String property = String.valueOf(System.getProperty(StandardSystemProperty.JAVA_VENDOR.key())).toUpperCase();
+        if (property.contains("IBM"))
+        {
+            return JvmVendor.IBM;
+        }
+        else if (property.contains("ORACLE"))
+        {
+            return JvmVendor.ORACLE;
+        }
+        else if (property.contains("OPENJDK"))
+        {
+            return JvmVendor.OPENJDK;
+        }
+        else
+        {
+            return JvmVendor.UNKNOWN;
+        }
+    }
 }
diff --git a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java
index 4dcfab0..4d71700 100644
--- a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java
+++ b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java
@@ -77,23 +77,7 @@ public class UnitTestBase
 
     public static JvmVendor getJvmVendor()
     {
-        final String property = String.valueOf(System.getProperty(StandardSystemProperty.JAVA_VENDOR.key())).toUpperCase();
-        if (property.contains("IBM"))
-        {
-            return JvmVendor.IBM;
-        }
-        else if (property.contains("ORACLE"))
-        {
-            return JvmVendor.ORACLE;
-        }
-        else if (property.contains("OPENJDK"))
-        {
-            return JvmVendor.OPENJDK;
-        }
-        else
-        {
-            return JvmVendor.UNKNOWN;
-        }
+        return JvmVendor.getJvmVendor();
     }
 
     public VirtualHostNodeStoreType getVirtualHostNodeStoreType()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org