Skip to content

Commit

Permalink
HADOOP-18329. Support for IBM Semeru JVM > 11.0.15.0 Vendor Name Chan…
Browse files Browse the repository at this point in the history
…ges (#4537)


The static boolean PlatformName.IBM_JAVA now identifies
Java 11+ IBM Semeru runtimes as IBM JVM releases.

Contributed by Jack Buggins.
  • Loading branch information
JackBuggins authored Dec 10, 2022
1 parent 0a7dfcc commit a46b20d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

package org.apache.hadoop.util;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;

Expand All @@ -33,21 +37,71 @@ public class PlatformName {
* per the java-vm.
*/
public static final String PLATFORM_NAME =
(System.getProperty("os.name").startsWith("Windows")
? System.getenv("os") : System.getProperty("os.name"))
+ "-" + System.getProperty("os.arch")
+ "-" + System.getProperty("sun.arch.data.model");
(System.getProperty("os.name").startsWith("Windows") ?
System.getenv("os") : System.getProperty("os.name"))
+ "-" + System.getProperty("os.arch") + "-"
+ System.getProperty("sun.arch.data.model");

/**
* The java vendor name used in this platform.
*/
public static final String JAVA_VENDOR_NAME = System.getProperty("java.vendor");

/**
* Define a system class accessor that is open to changes in underlying implementations
* of the system class loader modules.
*/
private static final class SystemClassAccessor extends ClassLoader {
public Class<?> getSystemClass(String className) throws ClassNotFoundException {
return findSystemClass(className);
}
}

/**
* A public static variable to indicate the current java vendor is
* IBM java or not.
* IBM and the type is Java Technology Edition which provides its
* own implementations of many security packages and Cipher suites.
* Note that these are not provided in Semeru runtimes:
* See https://developer.ibm.com/languages/java/semeru-runtimes for details.
*/
public static final boolean IBM_JAVA = JAVA_VENDOR_NAME.contains("IBM");
public static final boolean IBM_JAVA = JAVA_VENDOR_NAME.contains("IBM") &&
hasIbmTechnologyEditionModules();

private static boolean hasIbmTechnologyEditionModules() {
return Arrays.asList(
"com.ibm.security.auth.module.JAASLoginModule",
"com.ibm.security.auth.module.Win64LoginModule",
"com.ibm.security.auth.module.NTLoginModule",
"com.ibm.security.auth.module.AIX64LoginModule",
"com.ibm.security.auth.module.LinuxLoginModule",
"com.ibm.security.auth.module.Krb5LoginModule"
).stream().anyMatch((module) -> isSystemClassAvailable(module));
}

/**
* In rare cases where different behaviour is performed based on the JVM vendor
* this method should be used to test for a unique JVM class provided by the
* vendor rather than using the vendor method. For example if on JVM provides a
* different Kerberos login module testing for that login module being loadable
* before configuring to use it is preferable to using the vendor data.
*
* @param className the name of a class in the JVM to test for
* @return true if the class is available, false otherwise.
*/
private static boolean isSystemClassAvailable(String className) {
return AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
try {
// Using ClassLoader.findSystemClass() instead of
// Class.forName(className, false, null) because Class.forName with a null
// ClassLoader only looks at the boot ClassLoader with Java 9 and above
// which doesn't look at all the modules available to the findSystemClass.
new SystemClassAccessor().getSystemClass(className);
return true;
} catch (Exception ignored) {
return false;
}
});
}

public static void main(String[] args) {
System.out.println(PLATFORM_NAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import org.apache.hadoop.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.hadoop.util.PlatformName.JAVA_VENDOR_NAME;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
Expand Down Expand Up @@ -102,11 +102,11 @@ public enum Mode { CLIENT, SERVER }
"ssl.server.exclude.cipher.list";

public static final String KEY_MANAGER_SSLCERTIFICATE =
JAVA_VENDOR_NAME.contains("IBM") ? "ibmX509" :
IBM_JAVA ? "ibmX509" :
KeyManagerFactory.getDefaultAlgorithm();

public static final String TRUST_MANAGER_SSLCERTIFICATE =
JAVA_VENDOR_NAME.contains("IBM") ? "ibmX509" :
IBM_JAVA ? "ibmX509" :
TrustManagerFactory.getDefaultAlgorithm();

public static final String KEYSTORES_FACTORY_CLASS_KEY =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,35 @@
import java.util.Arrays;

public class TestMiniKdc extends KerberosSecurityTestcase {
private static final boolean IBM_JAVA = System.getProperty("java.vendor")
.contains("IBM");
private static final boolean IBM_JAVA = shouldUseIbmPackages();
// duplicated to avoid cycles in the build
private static boolean shouldUseIbmPackages() {
final List<String> ibmTechnologyEditionSecurityModules = Arrays.asList(
"com.ibm.security.auth.module.JAASLoginModule",
"com.ibm.security.auth.module.Win64LoginModule",
"com.ibm.security.auth.module.NTLoginModule",
"com.ibm.security.auth.module.AIX64LoginModule",
"com.ibm.security.auth.module.LinuxLoginModule",
"com.ibm.security.auth.module.Krb5LoginModule"
);

if (System.getProperty("java.vendor").contains("IBM")) {
return ibmTechnologyEditionSecurityModules
.stream().anyMatch((module) -> isSystemClassAvailable(module));
}

return false;
}

private static boolean isSystemClassAvailable(String className) {
try {
Class.forName(className);
return true;
} catch (Exception ignored) {
return false;
}
}

@Test
public void testMiniKdcStart() {
MiniKdc kdc = getKdc();
Expand Down Expand Up @@ -117,9 +144,9 @@ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
options.put("debug", "true");

return new AppConfigurationEntry[]{
new AppConfigurationEntry(getKrb5LoginModuleName(),
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
options)};
new AppConfigurationEntry(getKrb5LoginModuleName(),
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
options)};
}
}

Expand Down

0 comments on commit a46b20d

Please sign in to comment.