Repository: kafka Updated Branches: refs/heads/trunk c1fdf575d -> 65edd64ca
KAFKA-3070: SASL unit tests dont work with IBM JDK Use IBM Kerberos module for SASL tests if running on IBM JDK Developed with edoardocomar Based on https://github.com/apache/kafka/pull/738 by rajinisivaram Author: Mickael Maison <mickael.mai...@gmail.com> Reviewers: Ismael Juma <ism...@juma.me.uk>, Rajini Sivaram <rajinisiva...@googlemail.com>, Edoardo Comar <eco...@uk.ibm.com> Closes #2878 from mimaison/KAFKA-3070 Project: http://git-wip-us.apache.org/repos/asf/kafka/repo Commit: http://git-wip-us.apache.org/repos/asf/kafka/commit/65edd64c Tree: http://git-wip-us.apache.org/repos/asf/kafka/tree/65edd64c Diff: http://git-wip-us.apache.org/repos/asf/kafka/diff/65edd64c Branch: refs/heads/trunk Commit: 65edd64ca4902c9b2bc48e952056235f016031e1 Parents: c1fdf57 Author: Mickael Maison <mickael.mai...@gmail.com> Authored: Thu May 18 16:11:14 2017 -0400 Committer: Rajini Sivaram <rajinisiva...@googlemail.com> Committed: Thu May 18 16:11:14 2017 -0400 ---------------------------------------------------------------------- .../common/network/SaslChannelBuilder.java | 3 +- .../org/apache/kafka/common/utils/Java.java | 4 ++ .../org/apache/kafka/common/utils/JavaTest.java | 56 ++++++++++++++++++++ .../scala/kafka/security/minikdc/MiniKdc.scala | 4 +- .../scala/unit/kafka/utils/JaasTestUtils.scala | 49 +++++++++++++---- .../test/scala/unit/kafka/utils/TestUtils.scala | 12 ++--- 6 files changed, 105 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kafka/blob/65edd64c/clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java ---------------------------------------------------------------------- diff --git a/clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java b/clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java index 6b5668f..9fe200f 100644 --- a/clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java +++ b/clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java @@ -32,6 +32,7 @@ import org.apache.kafka.common.security.authenticator.LoginManager; import org.apache.kafka.common.security.authenticator.SaslClientAuthenticator; import org.apache.kafka.common.security.authenticator.SaslServerAuthenticator; import org.apache.kafka.common.security.ssl.SslFactory; +import org.apache.kafka.common.utils.Java; import org.apache.kafka.common.protocol.SecurityProtocol; import org.apache.kafka.common.KafkaException; import org.slf4j.Logger; @@ -143,7 +144,7 @@ public class SaslChannelBuilder implements ChannelBuilder { Class<?> classRef; Method getInstanceMethod; Method getDefaultRealmMethod; - if (System.getProperty("java.vendor").contains("IBM")) { + if (Java.isIBMJdk()) { classRef = Class.forName("com.ibm.security.krb5.internal.Config"); } else { classRef = Class.forName("sun.security.krb5.Config"); http://git-wip-us.apache.org/repos/asf/kafka/blob/65edd64c/clients/src/main/java/org/apache/kafka/common/utils/Java.java ---------------------------------------------------------------------- diff --git a/clients/src/main/java/org/apache/kafka/common/utils/Java.java b/clients/src/main/java/org/apache/kafka/common/utils/Java.java index 34eb6bf..b374c24 100644 --- a/clients/src/main/java/org/apache/kafka/common/utils/Java.java +++ b/clients/src/main/java/org/apache/kafka/common/utils/Java.java @@ -41,4 +41,8 @@ public final class Java { public static final boolean IS_JAVA9_COMPATIBLE = JVM_MAJOR_VERSION > 1 || (JVM_MAJOR_VERSION == 1 && JVM_MINOR_VERSION >= 9); + public static boolean isIBMJdk() { + return System.getProperty("java.vendor").contains("IBM"); + } + } http://git-wip-us.apache.org/repos/asf/kafka/blob/65edd64c/clients/src/test/java/org/apache/kafka/common/utils/JavaTest.java ---------------------------------------------------------------------- diff --git a/clients/src/test/java/org/apache/kafka/common/utils/JavaTest.java b/clients/src/test/java/org/apache/kafka/common/utils/JavaTest.java new file mode 100644 index 0000000..057ff50 --- /dev/null +++ b/clients/src/test/java/org/apache/kafka/common/utils/JavaTest.java @@ -0,0 +1,56 @@ +/* + * 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.kafka.common.utils; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class JavaTest { + + private String javaVendor; + + @Before + public void before() { + javaVendor = System.getProperty("java.vendor"); + } + + @After + public void after() { + System.setProperty("java.vendor", javaVendor); + } + + @Test + public void testIsIBMJdk() { + System.setProperty("java.vendor", "Oracle Corporation"); + assertFalse(Java.isIBMJdk()); + System.setProperty("java.vendor", "IBM Corporation"); + assertTrue(Java.isIBMJdk()); + } + + @Test + public void testLoadKerberosLoginModule() throws ClassNotFoundException { + String clazz = Java.isIBMJdk() + ? "com.ibm.security.auth.module.Krb5LoginModule" + : "com.sun.security.auth.module.Krb5LoginModule"; + Class.forName(clazz); + } + +} http://git-wip-us.apache.org/repos/asf/kafka/blob/65edd64c/core/src/test/scala/kafka/security/minikdc/MiniKdc.scala ---------------------------------------------------------------------- diff --git a/core/src/test/scala/kafka/security/minikdc/MiniKdc.scala b/core/src/test/scala/kafka/security/minikdc/MiniKdc.scala index c08dd99..c7b8973 100644 --- a/core/src/test/scala/kafka/security/minikdc/MiniKdc.scala +++ b/core/src/test/scala/kafka/security/minikdc/MiniKdc.scala @@ -50,7 +50,7 @@ import org.apache.directory.server.kerberos.shared.keytab.{Keytab, KeytabEntry} import org.apache.directory.server.protocol.shared.transport.{TcpTransport, UdpTransport} import org.apache.directory.server.xdbm.Index import org.apache.directory.shared.kerberos.KerberosTime -import org.apache.kafka.common.utils.Utils +import org.apache.kafka.common.utils.{Java, Utils} /** * Mini KDC based on Apache Directory Server that can be embedded in tests or used from command line as a standalone @@ -256,7 +256,7 @@ class MiniKdc(config: Properties, workDir: File) extends Logging { private def refreshJvmKerberosConfig(): Unit = { val klass = - if (System.getProperty("java.vendor").contains("IBM")) + if (Java.isIBMJdk) Class.forName("com.ibm.security.krb5.internal.Config") else Class.forName("sun.security.krb5.Config") http://git-wip-us.apache.org/repos/asf/kafka/blob/65edd64c/core/src/test/scala/unit/kafka/utils/JaasTestUtils.scala ---------------------------------------------------------------------- diff --git a/core/src/test/scala/unit/kafka/utils/JaasTestUtils.scala b/core/src/test/scala/unit/kafka/utils/JaasTestUtils.scala index d10e861..9517789 100644 --- a/core/src/test/scala/unit/kafka/utils/JaasTestUtils.scala +++ b/core/src/test/scala/unit/kafka/utils/JaasTestUtils.scala @@ -17,6 +17,9 @@ package kafka.utils import java.io.{File, BufferedWriter, FileWriter} +import java.util.Properties +import kafka.server.KafkaConfig +import org.apache.kafka.common.utils.Java object JaasTestUtils { @@ -27,15 +30,25 @@ object JaasTestUtils { debug: Boolean, serviceName: Option[String]) extends JaasModule { - def name = "com.sun.security.auth.module.Krb5LoginModule" - - def entries: Map[String, String] = Map( - "useKeyTab" -> useKeyTab.toString, - "storeKey" -> storeKey.toString, - "keyTab" -> keyTab, - "principal" -> principal - ) ++ serviceName.map(s => Map("serviceName" -> s)).getOrElse(Map.empty) - + def name = + if (Java.isIBMJdk) + "com.ibm.security.auth.module.Krb5LoginModule" + else + "com.sun.security.auth.module.Krb5LoginModule" + + def entries: Map[String, String] = + if (Java.isIBMJdk) + Map( + "principal" -> principal, + "credsType" -> "both" + ) ++ (if (useKeyTab) Map("useKeytab" -> s"file:$keyTab") else Map.empty) + else + Map( + "useKeyTab" -> useKeyTab.toString, + "storeKey" -> storeKey.toString, + "keyTab" -> keyTab, + "principal" -> principal + ) ++ serviceName.map(s => Map("serviceName" -> s)).getOrElse(Map.empty) } case class PlainLoginModule(username: String, @@ -120,6 +133,20 @@ object JaasTestUtils { val KafkaScramAdmin = "scram-admin" val KafkaScramAdminPassword = "scram-admin-secret" + val serviceName = "kafka" + + def saslConfigs(saslProperties: Option[Properties]): Properties = { + val result = saslProperties match { + case Some(properties) => properties + case None => new Properties + } + // IBM Kerberos module doesn't support the serviceName JAAS property, hence it needs to be + // passed as a Kafka property + if (Java.isIBMJdk && !result.contains(KafkaConfig.SaslKerberosServiceNameProp)) + result.put(KafkaConfig.SaslKerberosServiceNameProp, serviceName) + result + } + def writeJaasContextsToFile(jaasSections: Seq[JaasSection]): File = { val jaasFile = TestUtils.tempFile() writeToFile(jaasFile, jaasSections) @@ -146,7 +173,7 @@ object JaasTestUtils { keyTab = keytabLocation.getOrElse(throw new IllegalArgumentException("Keytab location not specified for GSSAPI")).getAbsolutePath, principal = KafkaServerPrincipal, debug = true, - serviceName = Some("kafka")) + serviceName = Some(serviceName)) case "PLAIN" => PlainLoginModule( KafkaPlainAdmin, @@ -180,7 +207,7 @@ object JaasTestUtils { keyTab = keytabLocation.getOrElse(throw new IllegalArgumentException("Keytab location not specified for GSSAPI")).getAbsolutePath, principal = clientPrincipal, debug = true, - serviceName = Some("kafka") + serviceName = Some(serviceName) ) case "PLAIN" => PlainLoginModule( http://git-wip-us.apache.org/repos/asf/kafka/blob/65edd64c/core/src/test/scala/unit/kafka/utils/TestUtils.scala ---------------------------------------------------------------------- diff --git a/core/src/test/scala/unit/kafka/utils/TestUtils.scala b/core/src/test/scala/unit/kafka/utils/TestUtils.scala index 90dcacd..5097637 100755 --- a/core/src/test/scala/unit/kafka/utils/TestUtils.scala +++ b/core/src/test/scala/unit/kafka/utils/TestUtils.scala @@ -245,7 +245,7 @@ object TestUtils extends Logging { props.putAll(sslConfigs(Mode.SERVER, false, trustStoreFile, s"server$nodeId")) if (protocolAndPorts.exists { case (protocol, _) => usesSaslAuthentication(protocol) }) - props.putAll(saslConfigs(saslProperties)) + props.putAll(JaasTestUtils.saslConfigs(saslProperties)) interBrokerSecurityProtocol.foreach { protocol => props.put(KafkaConfig.InterBrokerSecurityProtocolProp, protocol.name) @@ -509,8 +509,9 @@ object TestUtils extends Logging { val props = new Properties if (usesSslTransportLayer(securityProtocol)) props.putAll(sslConfigs(mode, securityProtocol == SecurityProtocol.SSL, trustStoreFile, certAlias)) + if (usesSaslAuthentication(securityProtocol)) - props.putAll(saslConfigs(saslProperties)) + props.putAll(JaasTestUtils.saslConfigs(saslProperties)) props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, securityProtocol.name) props } @@ -1184,13 +1185,6 @@ object TestUtils extends Logging { sslProps } - def saslConfigs(saslProperties: Option[Properties]): Properties = { - saslProperties match { - case Some(properties) => properties - case None => new Properties - } - } - // a X509TrustManager to trust self-signed certs for unit tests. def trustAllCerts: X509TrustManager = { val trustManager = new X509TrustManager() {