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