diff --git a/CHANGES.txt b/CHANGES.txt index bcd323ade5d..43c4f060a80 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -567,6 +567,7 @@ Release 0.90.5 - Unreleased (Gaojinchao) HBASE-4294 HLogSplitter sleeps with 1-second granularity (todd) HBASE-4270 IOE ignored during flush-on-close causes dataloss + HBASE-4180 HBase should check the isSecurityEnabled flag before login IMPROVEMENT HBASE-4205 Enhance HTable javadoc (Eric Charles) diff --git a/src/main/java/org/apache/hadoop/hbase/security/User.java b/src/main/java/org/apache/hadoop/hbase/security/User.java index 8002c89516d..d90f2c72211 100644 --- a/src/main/java/org/apache/hadoop/hbase/security/User.java +++ b/src/main/java/org/apache/hadoop/hbase/security/User.java @@ -22,12 +22,13 @@ package org.apache.hadoop.hbase.security; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.util.Methods; +import org.apache.hadoop.mapred.JobConf; +import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.security.UserGroupInformation; import java.io.IOException; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; @@ -43,15 +44,13 @@ import org.apache.commons.logging.Log; * {@link org.apache.hadoop.security.UserGroupInformation} currently needed by * HBase, but can be extended as needs change. *
- * - *- * Note: this class does not attempt to support any of the Kerberos - * authentication methods exposed in security-enabled Hadoop (for the moment - * at least), as they're not yet needed. Properly supporting - * authentication is left up to implementation in secure HBase. - *
*/ public abstract class User { + /** + * Flag to differentiate between API-incompatible changes to + * {@link org.apache.hadoop.security.UserGroupInformation} between vanilla + * Hadoop 0.20.x and secure Hadoop 0.20+. + */ private static boolean IS_SECURE_HADOOP = true; static { try { @@ -144,6 +143,20 @@ public abstract class User { } } + /** + * Returns whether or not Kerberos authentication is configured. For + * non-secure Hadoop, this always returnsfalse
.
+ * For secure Hadoop, it will return the value from
+ * {@code UserGroupInformation.isSecurityEnabled()}.
+ */
+ public static boolean isSecurityEnabled() {
+ if (IS_SECURE_HADOOP) {
+ return SecureHadoopUser.isSecurityEnabled();
+ } else {
+ return HadoopUser.isSecurityEnabled();
+ }
+ }
+
/* Concrete implementations */
/**
@@ -230,6 +243,7 @@ public abstract class User {
return result;
}
+ /** @see User#createUserForTesting(org.apache.hadoop.conf.Configuration, String, String[]) */
public static User createUserForTesting(Configuration conf,
String name, String[] groups) {
try {
@@ -258,10 +272,20 @@ public abstract class User {
}
}
+ /**
+ * No-op since we're running on a version of Hadoop that doesn't support
+ * logins.
+ * @see User#login(org.apache.hadoop.conf.Configuration, String, String, String)
+ */
public static void login(Configuration conf, String fileConfKey,
String principalConfKey, String localhost) throws IOException {
LOG.info("Skipping login, not running on secure Hadoop");
}
+
+ /** Always returns {@code false}. */
+ public static boolean isSecurityEnabled() {
+ return false;
+ }
}
/**
@@ -331,6 +355,7 @@ public abstract class User {
}
}
+ /** @see User#createUserForTesting(org.apache.hadoop.conf.Configuration, String, String[]) */
public static User createUserForTesting(Configuration conf,
String name, String[] groups) {
try {
@@ -347,27 +372,55 @@ public abstract class User {
}
}
+ /**
+ * Obtain credentials for the current process using the configured
+ * Kerberos keytab file and principal.
+ * @see User#login(org.apache.hadoop.conf.Configuration, String, String, String)
+ *
+ * @param conf the Configuration to use
+ * @param fileConfKey Configuration property key used to store the path
+ * to the keytab file
+ * @param principalConfKey Configuration property key used to store the
+ * principal name to login as
+ * @param localhost the local hostname
+ */
public static void login(Configuration conf, String fileConfKey,
String principalConfKey, String localhost) throws IOException {
- // check for SecurityUtil class
+ if (isSecurityEnabled()) {
+ // check for SecurityUtil class
+ try {
+ Class c = Class.forName("org.apache.hadoop.security.SecurityUtil");
+ Class[] types = new Class[]{
+ Configuration.class, String.class, String.class, String.class };
+ Object[] args = new Object[]{
+ conf, fileConfKey, principalConfKey, localhost };
+ Methods.call(c, null, "login", types, args);
+ } catch (ClassNotFoundException cnfe) {
+ throw new RuntimeException("Unable to login using " +
+ "org.apache.hadoop.security.SecurityUtil.login(). SecurityUtil class " +
+ "was not found! Is this a version of secure Hadoop?", cnfe);
+ } catch (IOException ioe) {
+ throw ioe;
+ } catch (RuntimeException re) {
+ throw re;
+ } catch (Exception e) {
+ throw new UndeclaredThrowableException(e,
+ "Unhandled exception in User.login()");
+ }
+ }
+ }
+
+ /**
+ * Returns the result of {@code UserGroupInformation.isSecurityEnabled()}.
+ */
+ public static boolean isSecurityEnabled() {
try {
- Class c = Class.forName("org.apache.hadoop.security.SecurityUtil");
- Class[] types = new Class[]{
- Configuration.class, String.class, String.class, String.class };
- Object[] args = new Object[]{
- conf, fileConfKey, principalConfKey, localhost };
- call(c, null, "login", types, args);
- } catch (ClassNotFoundException cnfe) {
- throw new RuntimeException("Unable to login using " +
- "org.apache.hadoop.security.Security.login(). SecurityUtil class " +
- "was not found! Is this a version of secure Hadoop?", cnfe);
- } catch (IOException ioe) {
- throw ioe;
+ return (Boolean)callStatic("isSecurityEnabled");
} catch (RuntimeException re) {
throw re;
} catch (Exception e) {
throw new UndeclaredThrowableException(e,
- "Unhandled exception in User.login()");
+ "Unexpected exception calling UserGroupInformation.isSecurityEnabled()");
}
}
}
@@ -384,54 +437,7 @@ public abstract class User {
private static Object call(UserGroupInformation instance, String methodName,
Class[] types, Object[] args) throws Exception {
- return call(UserGroupInformation.class, instance, methodName, types, args);
- }
-
- private static