Author: garyh
Date: Mon Sep 12 19:59:17 2011
New Revision: 1169902

URL: http://svn.apache.org/viewvc?rev=1169902&view=rev
Log:
HBASE-4180  Check isSecurityEnabled before User.login for 0.21 compatibility

Added:
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Methods.java
Modified:
    hbase/trunk/CHANGES.txt
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/security/User.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Classes.java

Modified: hbase/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hbase/trunk/CHANGES.txt?rev=1169902&r1=1169901&r2=1169902&view=diff
==============================================================================
--- hbase/trunk/CHANGES.txt (original)
+++ hbase/trunk/CHANGES.txt Mon Sep 12 19:59:17 2011
@@ -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)

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/security/User.java
URL: 
http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/security/User.java?rev=1169902&r1=1169901&r2=1169902&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/security/User.java 
(original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/security/User.java Mon 
Sep 12 19:59:17 2011
@@ -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.
  * </p>
- *
- * <p>
- * 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.
- * </p>
  */
 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 returns <code>false</code>.
+   * 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 <T> Object call(Class<T> clazz, T instance, String methodName,
-      Class[] types, Object[] args) throws Exception {
-    try {
-      Method m = clazz.getMethod(methodName, types);
-      return m.invoke(instance, args);
-    } catch (IllegalArgumentException arge) {
-      LOG.fatal("Constructed invalid call. class="+clazz.getName()+
-          " method=" + methodName + " types=" + stringify(types), arge);
-      throw arge;
-    } catch (NoSuchMethodException nsme) {
-      throw new IllegalArgumentException(
-          "Can't find method "+methodName+" in "+clazz.getName()+"!", nsme);
-    } catch (InvocationTargetException ite) {
-      // unwrap the underlying exception and rethrow
-      if (ite.getTargetException() != null) {
-        if (ite.getTargetException() instanceof Exception) {
-          throw (Exception)ite.getTargetException();
-        } else if (ite.getTargetException() instanceof Error) {
-          throw (Error)ite.getTargetException();
-        }
-      }
-      throw new UndeclaredThrowableException(ite,
-          "Unknown exception invoking "+clazz.getName()+"."+methodName+"()");
-    } catch (IllegalAccessException iae) {
-      throw new IllegalArgumentException(
-          "Denied access calling "+clazz.getName()+"."+methodName+"()", iae);
-    } catch (SecurityException se) {
-      LOG.fatal("SecurityException calling method. class="+clazz.getName()+
-          " method=" + methodName + " types=" + stringify(types), se);
-      throw se;
-    }
-  }
-
-  private static String stringify(Class[] classes) {
-    StringBuilder buf = new StringBuilder();
-    if (classes != null) {
-      for (Class c : classes) {
-        if (buf.length() > 0) {
-          buf.append(",");
-        }
-        buf.append(c.getName());
-      }
-    } else {
-      buf.append("NULL");
-    }
-    return buf.toString();
+    return Methods.call(UserGroupInformation.class, instance, methodName, 
types,
+        args);
   }
 }

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Classes.java
URL: 
http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Classes.java?rev=1169902&r1=1169901&r2=1169902&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Classes.java 
(original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Classes.java Mon Sep 
12 19:59:17 2011
@@ -1,3 +1,23 @@
+/*
+ * Copyright The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package org.apache.hadoop.hbase.util;
 
 /**
@@ -41,4 +61,18 @@ public class Classes {
     return valueType;
   }
 
+  public static String stringify(Class[] classes) {
+    StringBuilder buf = new StringBuilder();
+    if (classes != null) {
+      for (Class c : classes) {
+        if (buf.length() > 0) {
+          buf.append(",");
+        }
+        buf.append(c.getName());
+      }
+    } else {
+      buf.append("NULL");
+    }
+    return buf.toString();
+  }
 }

Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Methods.java
URL: 
http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Methods.java?rev=1169902&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Methods.java (added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/Methods.java Mon Sep 
12 19:59:17 2011
@@ -0,0 +1,65 @@
+/*
+ * Copyright The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class Methods {
+  private static Log LOG = LogFactory.getLog(Methods.class);
+
+  public static <T> Object call(Class<T> clazz, T instance, String methodName,
+      Class[] types, Object[] args) throws Exception {
+    try {
+      Method m = clazz.getMethod(methodName, types);
+      return m.invoke(instance, args);
+    } catch (IllegalArgumentException arge) {
+      LOG.fatal("Constructed invalid call. class="+clazz.getName()+
+          " method=" + methodName + " types=" + Classes.stringify(types), 
arge);
+      throw arge;
+    } catch (NoSuchMethodException nsme) {
+      throw new IllegalArgumentException(
+          "Can't find method "+methodName+" in "+clazz.getName()+"!", nsme);
+    } catch (InvocationTargetException ite) {
+      // unwrap the underlying exception and rethrow
+      if (ite.getTargetException() != null) {
+        if (ite.getTargetException() instanceof Exception) {
+          throw (Exception)ite.getTargetException();
+        } else if (ite.getTargetException() instanceof Error) {
+          throw (Error)ite.getTargetException();
+        }
+      }
+      throw new UndeclaredThrowableException(ite,
+          "Unknown exception invoking "+clazz.getName()+"."+methodName+"()");
+    } catch (IllegalAccessException iae) {
+      throw new IllegalArgumentException(
+          "Denied access calling "+clazz.getName()+"."+methodName+"()", iae);
+    } catch (SecurityException se) {
+      LOG.fatal("SecurityException calling method. class="+clazz.getName()+
+          " method=" + methodName + " types=" + Classes.stringify(types), se);
+      throw se;
+    }
+  }
+}


Reply via email to