HADOOP-9446. Support Kerberos SPNEGO for IBM JDK. (Yu Gao via llu)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1513688 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luke Lu 2013-08-13 23:13:07 +00:00
parent 5a33cdabd8
commit 8a7cec29fe
6 changed files with 112 additions and 38 deletions

View File

@ -37,6 +37,8 @@ import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Map;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
/**
* The {@link KerberosAuthenticator} implements the Kerberos SPNEGO authentication sequence.
* <p/>
@ -75,13 +77,29 @@ public class KerberosAuthenticator implements Authenticator {
private static final String OS_LOGIN_MODULE_NAME;
private static final boolean windows = System.getProperty("os.name").startsWith("Windows");
private static final boolean is64Bit = System.getProperty("os.arch").contains("64");
private static final boolean aix = System.getProperty("os.name").equals("AIX");
/* Return the OS login module class name */
private static String getOSLoginModuleName() {
if (IBM_JAVA) {
if (windows) {
return is64Bit ? "com.ibm.security.auth.module.Win64LoginModule"
: "com.ibm.security.auth.module.NTLoginModule";
} else if (aix) {
return is64Bit ? "com.ibm.security.auth.module.AIX64LoginModule"
: "com.ibm.security.auth.module.AIXLoginModule";
} else {
return "com.ibm.security.auth.module.LinuxLoginModule";
}
} else {
return windows ? "com.sun.security.auth.module.NTLoginModule"
: "com.sun.security.auth.module.UnixLoginModule";
}
}
static {
if (windows) {
OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.NTLoginModule";
} else {
OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.UnixLoginModule";
}
OS_LOGIN_MODULE_NAME = getOSLoginModuleName();
}
private static final AppConfigurationEntry OS_SPECIFIC_LOGIN =
@ -92,13 +110,22 @@ public class KerberosAuthenticator implements Authenticator {
private static final Map<String, String> USER_KERBEROS_OPTIONS = new HashMap<String, String>();
static {
USER_KERBEROS_OPTIONS.put("doNotPrompt", "true");
USER_KERBEROS_OPTIONS.put("useTicketCache", "true");
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
String ticketCache = System.getenv("KRB5CCNAME");
if (ticketCache != null) {
USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache);
if (IBM_JAVA) {
USER_KERBEROS_OPTIONS.put("useDefaultCcache", "true");
} else {
USER_KERBEROS_OPTIONS.put("doNotPrompt", "true");
USER_KERBEROS_OPTIONS.put("useTicketCache", "true");
}
if (ticketCache != null) {
if (IBM_JAVA) {
// The first value searched when "useDefaultCcache" is used.
System.setProperty("KRB5CCNAME", ticketCache);
} else {
USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache);
}
}
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
}
private static final AppConfigurationEntry USER_KERBEROS_LOGIN =

View File

@ -21,6 +21,7 @@ import org.apache.hadoop.security.authentication.util.KerberosUtil;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.Oid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -44,6 +45,8 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
/**
* The {@link KerberosAuthenticationHandler} implements the Kerberos SPNEGO authentication mechanism for HTTP.
* <p/>
@ -77,18 +80,33 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
Map<String, String> options = new HashMap<String, String>();
options.put("keyTab", keytab);
options.put("principal", principal);
options.put("useKeyTab", "true");
options.put("storeKey", "true");
options.put("doNotPrompt", "true");
options.put("useTicketCache", "true");
options.put("renewTGT", "true");
if (IBM_JAVA) {
options.put("useKeytab",
keytab.startsWith("file://") ? keytab : "file://" + keytab);
options.put("principal", principal);
options.put("credsType", "acceptor");
} else {
options.put("keyTab", keytab);
options.put("principal", principal);
options.put("useKeyTab", "true");
options.put("storeKey", "true");
options.put("doNotPrompt", "true");
options.put("useTicketCache", "true");
options.put("renewTGT", "true");
options.put("isInitiator", "false");
}
options.put("refreshKrb5Config", "true");
options.put("isInitiator", "false");
String ticketCache = System.getenv("KRB5CCNAME");
if (ticketCache != null) {
options.put("ticketCache", ticketCache);
if (IBM_JAVA) {
options.put("useDefaultCcache", "true");
// The first value searched when "useDefaultCcache" is used.
System.setProperty("KRB5CCNAME", ticketCache);
options.put("renewTGT", "true");
options.put("credsType", "both");
} else {
options.put("ticketCache", ticketCache);
}
}
if (LOG.isDebugEnabled()) {
options.put("debug", "true");
@ -294,8 +312,18 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
public AuthenticationToken run() throws Exception {
AuthenticationToken token = null;
GSSContext gssContext = null;
GSSCredential gssCreds = null;
try {
gssContext = gssManager.createContext((GSSCredential) null);
if (IBM_JAVA) {
// IBM JDK needs non-null credentials to be passed to createContext here, with
// SPNEGO mechanism specified, otherwise JGSS will use its default mechanism
// only, which is Kerberos V5.
gssCreds = gssManager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME,
new Oid[]{KerberosUtil.getOidInstance("GSS_SPNEGO_MECH_OID"),
KerberosUtil.getOidInstance("GSS_KRB5_MECH_OID")},
GSSCredential.ACCEPT_ONLY);
}
gssContext = gssManager.createContext(gssCreds);
byte[] serverToken = gssContext.acceptSecContext(clientToken, 0, clientToken.length);
if (serverToken != null && serverToken.length > 0) {
String authenticate = base64.encodeToString(serverToken);
@ -317,6 +345,9 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
if (gssContext != null) {
gssContext.dispose();
}
if (gssCreds != null) {
gssCreds.dispose();
}
}
return token;
}

View File

@ -27,6 +27,8 @@ import java.util.Locale;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
public class KerberosUtil {
/* Return the Kerberos login module name */
@ -40,7 +42,11 @@ public class KerberosUtil {
throws ClassNotFoundException, GSSException, NoSuchFieldException,
IllegalAccessException {
Class<?> oidClass;
if (System.getProperty("java.vendor").contains("IBM")) {
if (IBM_JAVA) {
if ("NT_GSS_KRB5_PRINCIPAL".equals(oidName)) {
// IBM JDK GSSUtil class does not have field for krb5 principal oid
return new Oid("1.2.840.113554.1.2.2.1");
}
oidClass = Class.forName("com.ibm.security.jgss.GSSUtil");
} else {
oidClass = Class.forName("sun.security.jgss.GSSUtil");

View File

@ -22,31 +22,33 @@ import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
/**
* A helper class for getting build-info of the java-vm.
*
* A helper class for getting build-info of the java-vm.
*
*/
@InterfaceAudience.LimitedPrivate({"HBase"})
@InterfaceStability.Unstable
public class PlatformName {
/**
* The complete platform 'name' to identify the platform as
* The complete platform 'name' to identify the platform as
* per the java-vm.
*/
private static final String PLATFORM_NAME = System.getProperty("os.name") + "-" +
System.getProperty("os.arch") + "-" +
System.getProperty("sun.arch.data.model");
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");
/**
* The java vendor name used in this platform.
* The java vendor name used in this platform.
*/
public static final String JAVA_VENDOR_NAME = System.getProperty("java.vendor");
/**
* A public static variable to indicate the current java vendor is
* IBM java or not.
* A public static variable to indicate the current java vendor is
* IBM java or not.
*/
public static final boolean IBM_JAVA = JAVA_VENDOR_NAME.contains("IBM");
public static void main(String[] args) {
System.out.println(PLATFORM_NAME);
}

View File

@ -52,6 +52,8 @@ Release 2.1.1-beta - UNRELEASED
IMPROVEMENTS
HADOOP-9446. Support Kerberos SPNEGO for IBM JDK. (Yu Gao via llu)
HADOOP-9787. ShutdownHelper util to shutdown threads and threadpools.
(Karthik Kambatla via Sandy Ryza)

View File

@ -427,7 +427,6 @@ public class UserGroupInformation {
} else {
USER_KERBEROS_OPTIONS.put("doNotPrompt", "true");
USER_KERBEROS_OPTIONS.put("useTicketCache", "true");
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
}
String ticketCache = System.getenv("KRB5CCNAME");
if (ticketCache != null) {
@ -438,6 +437,7 @@ public class UserGroupInformation {
USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache);
}
}
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
USER_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
}
private static final AppConfigurationEntry USER_KERBEROS_LOGIN =
@ -453,8 +453,8 @@ public class UserGroupInformation {
KEYTAB_KERBEROS_OPTIONS.put("doNotPrompt", "true");
KEYTAB_KERBEROS_OPTIONS.put("useKeyTab", "true");
KEYTAB_KERBEROS_OPTIONS.put("storeKey", "true");
KEYTAB_KERBEROS_OPTIONS.put("refreshKrb5Config", "true");
}
KEYTAB_KERBEROS_OPTIONS.put("refreshKrb5Config", "true");
KEYTAB_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
}
private static final AppConfigurationEntry KEYTAB_KERBEROS_LOGIN =
@ -615,11 +615,17 @@ public class UserGroupInformation {
}
try {
Map<String,String> krbOptions = new HashMap<String,String>();
krbOptions.put("doNotPrompt", "true");
krbOptions.put("useTicketCache", "true");
krbOptions.put("useKeyTab", "false");
if (IBM_JAVA) {
krbOptions.put("useDefaultCcache", "true");
// The first value searched when "useDefaultCcache" is used.
System.setProperty("KRB5CCNAME", ticketCache);
} else {
krbOptions.put("doNotPrompt", "true");
krbOptions.put("useTicketCache", "true");
krbOptions.put("useKeyTab", "false");
krbOptions.put("ticketCache", ticketCache);
}
krbOptions.put("renewTGT", "false");
krbOptions.put("ticketCache", ticketCache);
krbOptions.putAll(HadoopConfiguration.BASIC_JAAS_OPTIONS);
AppConfigurationEntry ace = new AppConfigurationEntry(
KerberosUtil.getKrb5LoginModuleName(),