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

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1513687 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luke Lu 2013-08-13 23:12:20 +00:00
parent 36cedca874
commit 228742acad
6 changed files with 109 additions and 36 deletions

View File

@ -37,6 +37,8 @@ import java.security.PrivilegedExceptionAction;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
/** /**
* The {@link KerberosAuthenticator} implements the Kerberos SPNEGO authentication sequence. * The {@link KerberosAuthenticator} implements the Kerberos SPNEGO authentication sequence.
* <p/> * <p/>
@ -75,13 +77,29 @@ public class KerberosAuthenticator implements Authenticator {
private static final String OS_LOGIN_MODULE_NAME; private static final String OS_LOGIN_MODULE_NAME;
private static final boolean windows = System.getProperty("os.name").startsWith("Windows"); 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 { static {
if (windows) { OS_LOGIN_MODULE_NAME = getOSLoginModuleName();
OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.NTLoginModule";
} else {
OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.UnixLoginModule";
}
} }
private static final AppConfigurationEntry OS_SPECIFIC_LOGIN = 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>(); private static final Map<String, String> USER_KERBEROS_OPTIONS = new HashMap<String, String>();
static { static {
USER_KERBEROS_OPTIONS.put("doNotPrompt", "true");
USER_KERBEROS_OPTIONS.put("useTicketCache", "true");
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
String ticketCache = System.getenv("KRB5CCNAME"); String ticketCache = System.getenv("KRB5CCNAME");
if (ticketCache != null) { if (IBM_JAVA) {
USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache); 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 = 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.GSSContext;
import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSManager;
import org.ietf.jgss.Oid;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -44,6 +45,8 @@ import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
/** /**
* The {@link KerberosAuthenticationHandler} implements the Kerberos SPNEGO authentication mechanism for HTTP. * The {@link KerberosAuthenticationHandler} implements the Kerberos SPNEGO authentication mechanism for HTTP.
* <p/> * <p/>
@ -77,18 +80,33 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
@Override @Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) { public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
Map<String, String> options = new HashMap<String, String>(); Map<String, String> options = new HashMap<String, String>();
options.put("keyTab", keytab); if (IBM_JAVA) {
options.put("principal", principal); options.put("useKeytab",
options.put("useKeyTab", "true"); keytab.startsWith("file://") ? keytab : "file://" + keytab);
options.put("storeKey", "true"); options.put("principal", principal);
options.put("doNotPrompt", "true"); options.put("credsType", "acceptor");
options.put("useTicketCache", "true"); } else {
options.put("renewTGT", "true"); 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("refreshKrb5Config", "true");
options.put("isInitiator", "false");
String ticketCache = System.getenv("KRB5CCNAME"); String ticketCache = System.getenv("KRB5CCNAME");
if (ticketCache != null) { 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()) { if (LOG.isDebugEnabled()) {
options.put("debug", "true"); options.put("debug", "true");
@ -294,8 +312,18 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
public AuthenticationToken run() throws Exception { public AuthenticationToken run() throws Exception {
AuthenticationToken token = null; AuthenticationToken token = null;
GSSContext gssContext = null; GSSContext gssContext = null;
GSSCredential gssCreds = null;
try { 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); byte[] serverToken = gssContext.acceptSecContext(clientToken, 0, clientToken.length);
if (serverToken != null && serverToken.length > 0) { if (serverToken != null && serverToken.length > 0) {
String authenticate = base64.encodeToString(serverToken); String authenticate = base64.encodeToString(serverToken);
@ -317,6 +345,9 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
if (gssContext != null) { if (gssContext != null) {
gssContext.dispose(); gssContext.dispose();
} }
if (gssCreds != null) {
gssCreds.dispose();
}
} }
return token; return token;
} }

View File

@ -27,6 +27,8 @@ import java.util.Locale;
import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid; import org.ietf.jgss.Oid;
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
public class KerberosUtil { public class KerberosUtil {
/* Return the Kerberos login module name */ /* Return the Kerberos login module name */
@ -40,7 +42,11 @@ public class KerberosUtil {
throws ClassNotFoundException, GSSException, NoSuchFieldException, throws ClassNotFoundException, GSSException, NoSuchFieldException,
IllegalAccessException { IllegalAccessException {
Class<?> oidClass; 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"); oidClass = Class.forName("com.ibm.security.jgss.GSSUtil");
} else { } else {
oidClass = Class.forName("sun.security.jgss.GSSUtil"); oidClass = Class.forName("sun.security.jgss.GSSUtil");

View File

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

View File

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

View File

@ -439,7 +439,6 @@ public class UserGroupInformation {
} else { } else {
USER_KERBEROS_OPTIONS.put("doNotPrompt", "true"); USER_KERBEROS_OPTIONS.put("doNotPrompt", "true");
USER_KERBEROS_OPTIONS.put("useTicketCache", "true"); USER_KERBEROS_OPTIONS.put("useTicketCache", "true");
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
} }
String ticketCache = System.getenv("KRB5CCNAME"); String ticketCache = System.getenv("KRB5CCNAME");
if (ticketCache != null) { if (ticketCache != null) {
@ -450,6 +449,7 @@ public class UserGroupInformation {
USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache); USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache);
} }
} }
USER_KERBEROS_OPTIONS.put("renewTGT", "true");
USER_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS); USER_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
} }
private static final AppConfigurationEntry USER_KERBEROS_LOGIN = private static final AppConfigurationEntry USER_KERBEROS_LOGIN =
@ -465,8 +465,8 @@ public class UserGroupInformation {
KEYTAB_KERBEROS_OPTIONS.put("doNotPrompt", "true"); KEYTAB_KERBEROS_OPTIONS.put("doNotPrompt", "true");
KEYTAB_KERBEROS_OPTIONS.put("useKeyTab", "true"); KEYTAB_KERBEROS_OPTIONS.put("useKeyTab", "true");
KEYTAB_KERBEROS_OPTIONS.put("storeKey", "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); KEYTAB_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
} }
private static final AppConfigurationEntry KEYTAB_KERBEROS_LOGIN = private static final AppConfigurationEntry KEYTAB_KERBEROS_LOGIN =
@ -627,11 +627,17 @@ public class UserGroupInformation {
} }
try { try {
Map<String,String> krbOptions = new HashMap<String,String>(); Map<String,String> krbOptions = new HashMap<String,String>();
krbOptions.put("doNotPrompt", "true"); if (IBM_JAVA) {
krbOptions.put("useTicketCache", "true"); krbOptions.put("useDefaultCcache", "true");
krbOptions.put("useKeyTab", "false"); // 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("renewTGT", "false");
krbOptions.put("ticketCache", ticketCache);
krbOptions.putAll(HadoopConfiguration.BASIC_JAAS_OPTIONS); krbOptions.putAll(HadoopConfiguration.BASIC_JAAS_OPTIONS);
AppConfigurationEntry ace = new AppConfigurationEntry( AppConfigurationEntry ace = new AppConfigurationEntry(
KerberosUtil.getKrb5LoginModuleName(), KerberosUtil.getKrb5LoginModuleName(),