HADOOP-6941. Adds support for building Hadoop with IBM's JDK. Contributed by Stephen Watt, Eli Collins and Devaraj Das.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1301308 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
483ca92d9b
commit
2a0147f8f6
|
@ -13,12 +13,12 @@
|
|||
*/
|
||||
package org.apache.hadoop.security.authentication.client;
|
||||
|
||||
import com.sun.security.auth.module.Krb5LoginModule;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
|
@ -26,6 +26,7 @@ import javax.security.auth.login.Configuration;
|
|||
import javax.security.auth.login.LoginContext;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.AccessControlContext;
|
||||
|
@ -97,7 +98,7 @@ public class KerberosAuthenticator implements Authenticator {
|
|||
}
|
||||
|
||||
private static final AppConfigurationEntry USER_KERBEROS_LOGIN =
|
||||
new AppConfigurationEntry(Krb5LoginModule.class.getName(),
|
||||
new AppConfigurationEntry(KerberosUtil.getKrb5LoginModuleName(),
|
||||
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL,
|
||||
USER_KERBEROS_OPTIONS);
|
||||
|
||||
|
@ -109,7 +110,7 @@ public class KerberosAuthenticator implements Authenticator {
|
|||
return USER_KERBEROS_CONF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private URL url;
|
||||
private HttpURLConnection conn;
|
||||
private Base64 base64;
|
||||
|
@ -195,9 +196,12 @@ public class KerberosAuthenticator implements Authenticator {
|
|||
try {
|
||||
GSSManager gssManager = GSSManager.getInstance();
|
||||
String servicePrincipal = "HTTP/" + KerberosAuthenticator.this.url.getHost();
|
||||
|
||||
GSSName serviceName = gssManager.createName(servicePrincipal,
|
||||
GSSUtil.NT_GSS_KRB5_PRINCIPAL);
|
||||
gssContext = gssManager.createContext(serviceName, GSSUtil.GSS_KRB5_MECH_OID, null,
|
||||
GSSName.NT_HOSTBASED_SERVICE);
|
||||
Oid oid = KerberosUtil.getOidClassInstance(servicePrincipal,
|
||||
gssManager);
|
||||
gssContext = gssManager.createContext(serviceName, oid, null,
|
||||
GSSContext.DEFAULT_LIFETIME);
|
||||
gssContext.requestCredDeleg(true);
|
||||
gssContext.requestMutualAuth(true);
|
||||
|
|
|
@ -15,9 +15,9 @@ package org.apache.hadoop.security.authentication.server;
|
|||
|
||||
import org.apache.hadoop.security.authentication.client.AuthenticationException;
|
||||
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
|
||||
import com.sun.security.auth.module.Krb5LoginModule;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosName;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSCredential;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
|
@ -95,7 +95,7 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
|
|||
}
|
||||
|
||||
return new AppConfigurationEntry[]{
|
||||
new AppConfigurationEntry(Krb5LoginModule.class.getName(),
|
||||
new AppConfigurationEntry(KerberosUtil.getKrb5LoginModuleName(),
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
||||
options),};
|
||||
}
|
||||
|
|
|
@ -23,12 +23,11 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
|
||||
import sun.security.krb5.Config;
|
||||
import sun.security.krb5.KrbException;
|
||||
|
||||
/**
|
||||
* This class implements parsing and handling of Kerberos principal names. In
|
||||
|
@ -77,13 +76,11 @@ public class KerberosName {
|
|||
private static List<Rule> rules;
|
||||
|
||||
private static String defaultRealm;
|
||||
private static Config kerbConf;
|
||||
|
||||
static {
|
||||
try {
|
||||
kerbConf = Config.getInstance();
|
||||
defaultRealm = kerbConf.getDefaultRealm();
|
||||
} catch (KrbException ke) {
|
||||
defaultRealm = KerberosUtil.getDefaultRealm();
|
||||
} catch (Exception ke) {
|
||||
defaultRealm="";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package org.apache.hadoop.security.authentication.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
public class KerberosUtil {
|
||||
|
||||
/* Return the Kerberos login module name */
|
||||
public static String getKrb5LoginModuleName() {
|
||||
return System.getProperty("java.vendor").contains("IBM")
|
||||
? "com.ibm.security.auth.module.Krb5LoginModule"
|
||||
: "com.sun.security.auth.module.Krb5LoginModule";
|
||||
}
|
||||
|
||||
public static Oid getOidClassInstance(String servicePrincipal,
|
||||
GSSManager gssManager)
|
||||
throws ClassNotFoundException, GSSException, NoSuchFieldException,
|
||||
IllegalAccessException {
|
||||
Class<?> oidClass;
|
||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
||||
oidClass = Class.forName("com.ibm.security.jgss.GSSUtil");
|
||||
} else {
|
||||
oidClass = Class.forName("sun.security.jgss.GSSUtil");
|
||||
}
|
||||
Field oidField = oidClass.getDeclaredField("GSS_KRB5_MECH_OID");
|
||||
return (Oid)oidField.get(oidClass);
|
||||
}
|
||||
|
||||
public static String getDefaultRealm()
|
||||
throws ClassNotFoundException, NoSuchMethodException,
|
||||
IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
Object kerbConf;
|
||||
Class<?> classRef;
|
||||
Method getInstanceMethod;
|
||||
Method getDefaultRealmMethod;
|
||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
||||
classRef = Class.forName("com.ibm.security.krb5.internal.Config");
|
||||
} else {
|
||||
classRef = Class.forName("sun.security.krb5.Config");
|
||||
}
|
||||
getInstanceMethod = classRef.getMethod("getInstance", new Class[0]);
|
||||
kerbConf = getInstanceMethod.invoke(classRef, new Object[0]);
|
||||
getDefaultRealmMethod = classRef.getDeclaredMethod("getDefaultRealm",
|
||||
new Class[0]);
|
||||
return (String)getDefaultRealmMethod.invoke(kerbConf, new Object[0]);
|
||||
}
|
||||
}
|
|
@ -13,13 +13,15 @@
|
|||
*/
|
||||
package org.apache.hadoop.security.authentication;
|
||||
|
||||
import com.sun.security.auth.module.Krb5LoginModule;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.Configuration;
|
||||
import javax.security.auth.login.LoginContext;
|
||||
|
||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivilegedActionException;
|
||||
|
@ -88,7 +90,7 @@ public class KerberosTestUtils {
|
|||
options.put("debug", "true");
|
||||
|
||||
return new AppConfigurationEntry[]{
|
||||
new AppConfigurationEntry(Krb5LoginModule.class.getName(),
|
||||
new AppConfigurationEntry(KerberosUtil.getKrb5LoginModuleName(),
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
||||
options),};
|
||||
}
|
||||
|
|
|
@ -19,14 +19,16 @@ import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
|
|||
import junit.framework.TestCase;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosName;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import org.mockito.Mockito;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
|
@ -143,9 +145,12 @@ public class TestKerberosAuthenticationHandler extends TestCase {
|
|||
GSSContext gssContext = null;
|
||||
try {
|
||||
String servicePrincipal = KerberosTestUtils.getServerPrincipal();
|
||||
GSSName serviceName = gssManager.createName(servicePrincipal, GSSUtil.NT_GSS_KRB5_PRINCIPAL);
|
||||
gssContext = gssManager.createContext(serviceName, GSSUtil.GSS_KRB5_MECH_OID, null,
|
||||
GSSContext.DEFAULT_LIFETIME);
|
||||
GSSName serviceName = gssManager.createName(servicePrincipal,
|
||||
GSSName.NT_HOSTBASED_SERVICE);
|
||||
Oid oid = KerberosUtil.getOidClassInstance(servicePrincipal,
|
||||
gssManager);
|
||||
gssContext = gssManager.createContext(serviceName, oid, null,
|
||||
GSSContext.DEFAULT_LIFETIME);
|
||||
gssContext.requestCredDeleg(true);
|
||||
gssContext.requestMutualAuth(true);
|
||||
|
||||
|
|
|
@ -190,6 +190,9 @@ Release 0.23.3 - UNRELEASED
|
|||
|
||||
HADOOP-7806. Support binding to sub-interfaces (eli)
|
||||
|
||||
HADOOP-6941. Adds support for building Hadoop with IBM's JDK
|
||||
(Stephen Watt, Eli and ddas)
|
||||
|
||||
OPTIMIZATIONS
|
||||
|
||||
BUG FIXES
|
||||
|
|
|
@ -24,9 +24,7 @@ import org.apache.hadoop.classification.InterfaceAudience;
|
|||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosName;
|
||||
|
||||
import sun.security.krb5.Config;
|
||||
import sun.security.krb5.KrbException;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||
|
||||
/**
|
||||
* This class implements parsing and handling of Kerberos principal names. In
|
||||
|
@ -40,8 +38,8 @@ public class HadoopKerberosName extends KerberosName {
|
|||
|
||||
static {
|
||||
try {
|
||||
Config.getInstance().getDefaultRealm();
|
||||
} catch (KrbException ke) {
|
||||
KerberosUtil.getDefaultRealm();
|
||||
} catch (Exception ke) {
|
||||
if(UserGroupInformation.isSecurityEnabled())
|
||||
throw new IllegalArgumentException("Can't get Kerberos configuration",ke);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
package org.apache.hadoop.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
|
@ -49,9 +53,6 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
//this will need to be replaced someday when there is a suitable replacement
|
||||
import sun.net.dns.ResolverConfiguration;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
import sun.security.jgss.krb5.Krb5Util;
|
||||
import sun.security.krb5.Credentials;
|
||||
import sun.security.krb5.PrincipalName;
|
||||
|
||||
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
|
||||
@InterfaceStability.Evolving
|
||||
|
@ -155,12 +156,41 @@ public class SecurityUtil {
|
|||
String serviceName = "host/" + remoteHost.getHost();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Fetching service ticket for host at: " + serviceName);
|
||||
Credentials serviceCred = null;
|
||||
Object serviceCred = null;
|
||||
Method credsToTicketMeth;
|
||||
Class<?> krb5utilClass;
|
||||
try {
|
||||
PrincipalName principal = new PrincipalName(serviceName,
|
||||
PrincipalName.KRB_NT_SRV_HST);
|
||||
serviceCred = Credentials.acquireServiceCreds(principal
|
||||
.toString(), Krb5Util.ticketToCreds(getTgtFromSubject()));
|
||||
Class<?> principalClass;
|
||||
Class<?> credentialsClass;
|
||||
|
||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
||||
principalClass = Class.forName("com.ibm.security.krb5.PrincipalName");
|
||||
|
||||
credentialsClass = Class.forName("com.ibm.security.krb5.Credentials");
|
||||
krb5utilClass = Class.forName("com.ibm.security.jgss.mech.krb5");
|
||||
} else {
|
||||
principalClass = Class.forName("sun.security.krb5.PrincipalName");
|
||||
credentialsClass = Class.forName("sun.security.krb5.Credentials");
|
||||
krb5utilClass = Class.forName("sun.security.jgss.krb5");
|
||||
}
|
||||
@SuppressWarnings("rawtypes")
|
||||
Constructor principalConstructor = principalClass.getConstructor(String.class,
|
||||
int.class);
|
||||
Field KRB_NT_SRV_HST = principalClass.getDeclaredField("KRB_NT_SRV_HST");
|
||||
Method acquireServiceCredsMeth =
|
||||
credentialsClass.getDeclaredMethod("acquireServiceCreds",
|
||||
String.class, credentialsClass);
|
||||
Method ticketToCredsMeth = krb5utilClass.getDeclaredMethod("ticketToCreds",
|
||||
KerberosTicket.class);
|
||||
credsToTicketMeth = krb5utilClass.getDeclaredMethod("credsToTicket",
|
||||
credentialsClass);
|
||||
|
||||
Object principal = principalConstructor.newInstance(serviceName,
|
||||
KRB_NT_SRV_HST.get(principalClass));
|
||||
|
||||
serviceCred = acquireServiceCredsMeth.invoke(credentialsClass,
|
||||
principal.toString(),
|
||||
ticketToCredsMeth.invoke(krb5utilClass, getTgtFromSubject()));
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Can't get service ticket for: "
|
||||
+ serviceName, e);
|
||||
|
@ -168,8 +198,13 @@ public class SecurityUtil {
|
|||
if (serviceCred == null) {
|
||||
throw new IOException("Can't get service ticket for " + serviceName);
|
||||
}
|
||||
Subject.getSubject(AccessController.getContext()).getPrivateCredentials()
|
||||
.add(Krb5Util.credsToTicket(serviceCred));
|
||||
try {
|
||||
Subject.getSubject(AccessController.getContext()).getPrivateCredentials()
|
||||
.add(credsToTicketMeth.invoke(krb5utilClass, serviceCred));
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Can't get service ticket for: "
|
||||
+ serviceName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,14 +58,11 @@ import org.apache.hadoop.metrics2.annotation.Metrics;
|
|||
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
|
||||
import org.apache.hadoop.metrics2.lib.MutableRate;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosName;
|
||||
import org.apache.hadoop.security.authentication.util.KerberosUtil;
|
||||
import org.apache.hadoop.security.token.Token;
|
||||
import org.apache.hadoop.security.token.TokenIdentifier;
|
||||
import org.apache.hadoop.util.Shell;
|
||||
|
||||
import com.sun.security.auth.NTUserPrincipal;
|
||||
import com.sun.security.auth.UnixPrincipal;
|
||||
import com.sun.security.auth.module.Krb5LoginModule;
|
||||
|
||||
/**
|
||||
* User and group information for Hadoop.
|
||||
* This class wraps around a JAAS Subject and provides methods to determine the
|
||||
|
@ -289,20 +286,51 @@ public class UserGroupInformation {
|
|||
private final boolean isKeytab;
|
||||
private final boolean isKrbTkt;
|
||||
|
||||
private static final String OS_LOGIN_MODULE_NAME;
|
||||
private static final Class<? extends Principal> OS_PRINCIPAL_CLASS;
|
||||
private static String OS_LOGIN_MODULE_NAME;
|
||||
private static Class<? extends Principal> OS_PRINCIPAL_CLASS;
|
||||
private static final boolean windows =
|
||||
System.getProperty("os.name").startsWith("Windows");
|
||||
static {
|
||||
if (windows) {
|
||||
OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.NTLoginModule";
|
||||
OS_PRINCIPAL_CLASS = NTUserPrincipal.class;
|
||||
/* Return the OS login module class name */
|
||||
private static String getOSLoginModuleName() {
|
||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
||||
return windows ? "com.ibm.security.auth.module.NTLoginModule"
|
||||
: "com.ibm.security.auth.module.LinuxLoginModule";
|
||||
} else {
|
||||
OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.UnixLoginModule";
|
||||
OS_PRINCIPAL_CLASS = UnixPrincipal.class;
|
||||
return windows ? "com.sun.security.auth.module.NTLoginModule"
|
||||
: "com.sun.security.auth.module.UnixLoginModule";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return the OS principal class */
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Class<? extends Principal> getOsPrincipalClass() {
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
try {
|
||||
if (System.getProperty("java.vendor").contains("IBM")) {
|
||||
if (windows) {
|
||||
return (Class<? extends Principal>)
|
||||
cl.loadClass("com.ibm.security.auth.UsernamePrincipal");
|
||||
} else {
|
||||
return (Class<? extends Principal>)
|
||||
(System.getProperty("os.arch").contains("64")
|
||||
? cl.loadClass("com.ibm.security.auth.UsernamePrincipal")
|
||||
: cl.loadClass("com.ibm.security.auth.LinuxPrincipal"));
|
||||
}
|
||||
} else {
|
||||
return (Class<? extends Principal>) (windows
|
||||
? cl.loadClass("com.sun.security.auth.NTUserPrincipal")
|
||||
: cl.loadClass("com.sun.security.auth.UnixPrincipal"));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOG.error("Unable to find JAAS classes:" + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
static {
|
||||
OS_LOGIN_MODULE_NAME = getOSLoginModuleName();
|
||||
OS_PRINCIPAL_CLASS = getOsPrincipalClass();
|
||||
}
|
||||
|
||||
private static class RealUser implements Principal {
|
||||
private final UserGroupInformation realUser;
|
||||
|
||||
|
@ -382,7 +410,7 @@ public class UserGroupInformation {
|
|||
USER_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
|
||||
}
|
||||
private static final AppConfigurationEntry USER_KERBEROS_LOGIN =
|
||||
new AppConfigurationEntry(Krb5LoginModule.class.getName(),
|
||||
new AppConfigurationEntry(KerberosUtil.getKrb5LoginModuleName(),
|
||||
LoginModuleControlFlag.OPTIONAL,
|
||||
USER_KERBEROS_OPTIONS);
|
||||
private static final Map<String,String> KEYTAB_KERBEROS_OPTIONS =
|
||||
|
@ -395,7 +423,7 @@ public class UserGroupInformation {
|
|||
KEYTAB_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
|
||||
}
|
||||
private static final AppConfigurationEntry KEYTAB_KERBEROS_LOGIN =
|
||||
new AppConfigurationEntry(Krb5LoginModule.class.getName(),
|
||||
new AppConfigurationEntry(KerberosUtil.getKrb5LoginModuleName(),
|
||||
LoginModuleControlFlag.REQUIRED,
|
||||
KEYTAB_KERBEROS_OPTIONS);
|
||||
|
||||
|
|
Loading…
Reference in New Issue