Преглед изворни кода

Implementation of beeswax security level 1.

vinithra пре 15 година
родитељ
комит
de52b9afd7

+ 76 - 65
apps/beeswax/java/src/com/cloudera/beeswax/BeeswaxServiceImpl.java

@@ -43,7 +43,6 @@ import java.util.Vector;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 
-import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.metastore.api.Schema;
@@ -97,8 +96,6 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
 
   private static Logger LOG = Logger.getLogger(BeeswaxServiceImpl.class.getName());
 
-  private UserGroupInformation ugi;
-
   /**
    * To be read and modified while holding a lock on the state object.
    *
@@ -244,16 +241,6 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
       if (query.hadoop_user == null) {
         throw new RuntimeException("User must be specified.");
       }
-      /*
-      StringBuilder ugi = new StringBuilder();
-      ugi.append(query.hadoop_user);
-      for (String group : query.hadoop_groups) {
-        ugi.append(",");
-        ugi.append(group);
-      }
-
-      hiveConf.set(UnixUserGroupInformation.UGI_PROPERTY_NAME, ugi.toString());
-      */
 
       // Update scratch dir (to have one per user)
       File scratchDir = new File("/tmp/hive-beeswax-" + query.hadoop_user);
@@ -611,32 +598,33 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
     // First, create an id and reset the LogContext
     String uuid = UUID.randomUUID().toString();
     final QueryHandle handle = new QueryHandle(uuid, uuid);
+    final LogContext lc = LogContext.registerCurrentThread(handle.log_context);
+    lc.resetLog();
+
+    // Make an administrative record
+    final RunningQueryState state = new RunningQueryState(query, lc);
 
     try {
-      UserGroupInformation ugi = UserGroupInformation.createProxyUser("hue", UserGroupInformation.getLoginUser());
-      ugi.doAs(new PrivilegedExceptionAction<Void>() {
-        public Void run() throws Exception {
-          final LogContext lc = LogContext.registerCurrentThread(handle.log_context);
-          lc.resetLog();
-			    // Make an administrative record
-			    final RunningQueryState state = new RunningQueryState(query, lc);
-			    state.setQueryHandle(handle);
-			    runningQueries.put(handle.id, state);
-			    state.initialize();
-			    // All kinds of things can go wrong when we compile it. So catch all.
-			    try {
-			      state.compile();
-			    } catch (BeeswaxException perr) {
-			      state.saveException(perr);
-			      throw perr;
-			    } catch (Throwable t) {
-			      state.saveException(t);
-			      throw new BeeswaxException(t.toString(), handle.log_context, handle);
-			    }
-			    // Now spin off the query.
-			    state.submitTo(executor, lc);
-			    return null;
-			  }
+      UserGroupInformation ugi = UserGroupInformation.createProxyUser(query.hadoop_user, UserGroupInformation.getLoginUser());
+      return ugi.doAs(new PrivilegedExceptionAction<QueryHandle>() {
+        public QueryHandle run() throws Exception {
+          state.setQueryHandle(handle);
+          runningQueries.put(handle.id, state);
+          state.initialize();
+          // All kinds of things can go wrong when we compile it. So catch all.
+          try {
+            state.compile();
+          } catch (BeeswaxException perr) {
+            state.saveException(perr);
+            throw perr;
+          } catch (Throwable t) {
+            state.saveException(t);
+            throw new BeeswaxException(t.toString(), handle.log_context, handle);
+          }
+          // Now spin off the query.
+          state.submitTo(executor, lc);
+          return handle;
+        }
       });
     } catch (IOException e) {
       String errorMsg = "Error while creating proxy user";
@@ -647,8 +635,6 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
       LOG.error(errorMsg);
       throw new BeeswaxException(errorMsg, handle.log_context, handle);
     }
-
-    return handle;
   }
 
   /**
@@ -675,19 +661,18 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
    */
   @Override
   public QueryExplanation explain(final Query query) throws BeeswaxException, TException {
-    QueryExplanation exp;
+    final String contextName = UUID.randomUUID().toString();
+    LogContext lc = LogContext.registerCurrentThread(contextName);
+    final RunningQueryState state = new RunningQueryState(query, lc);
     try {
-      UserGroupInformation ugi = UserGroupInformation.createProxyUser("hue", UserGroupInformation.getLoginUser());
-      exp = ugi.doAs(new PrivilegedExceptionAction<QueryExplanation>() {
+      UserGroupInformation ugi = UserGroupInformation.createProxyUser(query.hadoop_user, UserGroupInformation.getLoginUser());
+      return ugi.doAs(new PrivilegedExceptionAction<QueryExplanation>() {
         public QueryExplanation run() throws Exception {
-          String contextName = UUID.randomUUID().toString();
-          LogContext lc = LogContext.registerCurrentThread(contextName);
-          RunningQueryState state = new RunningQueryState(query, lc);
           state.initialize();
-          QueryExplanation expl;
+          QueryExplanation exp;
           // All kinds of things can go wrong when we compile it. So catch all.
           try {
-            expl = state.explain();
+            exp = state.explain();
           } catch (BeeswaxException perr) {
             throw perr;
           } catch (Throwable t) {
@@ -695,23 +680,18 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
           }
           // On success, we remove the LogContext
           LogContext.destroyContext(contextName);
-          return expl;
+          return exp;
         }
       });
     } catch (IOException e) {
       String errorMsg = "Error while creating proxy user";
       LOG.error(errorMsg);
-      BeeswaxException bwe = new BeeswaxException();
-      bwe.setMessage(errorMsg);
-      throw bwe;
+      throw new BeeswaxException(errorMsg, state.handle.log_context, state.handle);
     } catch (InterruptedException e) {
       String errorMsg = "Error while submitting query";
       LOG.error(errorMsg);
-      BeeswaxException bwe = new BeeswaxException();
-      bwe.setMessage(errorMsg);
-      throw bwe;
+      throw new BeeswaxException(errorMsg, state.handle.log_context, state.handle);
     }
-    return exp;
   }
 
   /**
@@ -722,17 +702,32 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
    * @param fromBeginning  If true, rewind to the first row. Otherwise fetch from last position.
    */
   @Override
-  public Results fetch(QueryHandle handle, boolean fromBeginning)
+  public Results fetch(final QueryHandle handle, final boolean fromBeginning)
       throws QueryNotFoundException, BeeswaxException {
     LogContext.unregisterCurrentThread();
     validateHandle(handle);
     LogContext.registerCurrentThread(handle.log_context);
-    RunningQueryState state = runningQueries.get(handle.id);
-    if (state == null) {
-      throw new QueryNotFoundException();
+    final RunningQueryState state = runningQueries.get(handle.id);
+    try {
+      UserGroupInformation ugi = UserGroupInformation.createProxyUser(state.query.hadoop_user, UserGroupInformation.getLoginUser());
+
+      return ugi.doAs(new PrivilegedExceptionAction<Results>() {
+        public Results run() throws Exception {
+          if (state == null) {
+            throw new QueryNotFoundException();
+          }
+          return state.fetch(fromBeginning);
+        }
+      });
+    } catch (IOException e) {
+      String errorMsg = "Error while creating proxy user";
+      LOG.error(errorMsg);
+      throw new BeeswaxException(errorMsg, handle.log_context, handle);
+    } catch (InterruptedException e) {
+      String errorMsg = "Error while submitting query";
+      LOG.error(errorMsg);
+      throw new BeeswaxException(errorMsg, handle.log_context, handle);
     }
-    Results res = state.fetch(fromBeginning);
-    return res;
   }
 
   @Override
@@ -770,15 +765,31 @@ public class BeeswaxServiceImpl implements BeeswaxService.Iface {
    * @param handle
    */
   @Override
-  public ResultsMetadata get_results_metadata(QueryHandle handle) throws QueryNotFoundException {
+  public ResultsMetadata get_results_metadata(final QueryHandle handle) throws QueryNotFoundException {
     LogContext.unregisterCurrentThread();
     validateHandle(handle);
     LogContext.registerCurrentThread(handle.log_context);
-    RunningQueryState state = runningQueries.get(handle.id);
-    if (state == null) {
+    final RunningQueryState state = runningQueries.get(handle.id);
+    try {
+      UserGroupInformation ugi = UserGroupInformation.createProxyUser(state.query.hadoop_user, UserGroupInformation.getLoginUser());
+
+      return ugi.doAs(new PrivilegedExceptionAction<ResultsMetadata>() {
+        public ResultsMetadata run() throws Exception {
+          if (state == null) {
+            throw new QueryNotFoundException();
+          }
+          return state.getResultMetadata();
+        }
+      });
+    } catch (IOException e) {
+      String errorMsg = "Error while creating proxy user";
+      LOG.error(errorMsg);
+      throw new QueryNotFoundException();
+    } catch (InterruptedException e) {
+      String errorMsg = "Error while submitting query";
+      LOG.error(errorMsg);
       throw new QueryNotFoundException();
     }
-    return state.getResultMetadata();
   }
 
   /**

+ 1 - 1
apps/beeswax/java/src/com/cloudera/beeswax/Server.java

@@ -157,8 +157,8 @@ public class Server {
    */
   private static void createDirectoriesAsNecessary() {
     try {
+      LOG.info("Classpath: " + System.getProperty("java.class.path"));
       HiveConf conf = new HiveConf(Driver.class);
-      conf.set("hadoop.ugi", superUser + ",supergroup");
       FileSystem fs = FileSystem.get(conf);
       Path tmpDir = new Path("/tmp");
       Path metaDir = new Path(conf

+ 2 - 1
apps/beeswax/src/beeswax/management/commands/beeswax_server.py

@@ -52,7 +52,8 @@ class Command(NoArgsCommand):
       '--desktop-host',
       str(dt_host),
       '--desktop-port',
-      str(desktop.conf.HTTP_PORT.get()),
+      "8000",
+      #str(desktop.conf.HTTP_PORT.get()),
     ]
 
     # Running on HTTPS?

+ 5 - 5
apps/beeswax/src/beeswax/views.py

@@ -66,7 +66,7 @@ def show_tables(request):
 def describe_table(request, table):
   table_obj = db_utils.meta_client().get_table("default", table)
   # Show the first few rows
-  hql = "SELECT * FROM `%s`" % (table,)
+  hql = "SELECT * FROM %s" % (table,)
   query_msg = make_beeswax_query(request, hql)
   try:
     results = db_utils.execute_and_wait(request.user, query_msg, timeout_sec=5.0)
@@ -93,7 +93,7 @@ def drop_table(request, table):
     title = "This may delete the underlying data as well as the metadata.  Drop table %s?" % table
     return render('confirm.html', request, dict(url=request.path, title=title))
   elif request.method == 'POST':
-    hql = "DROP TABLE `%s`" % (table,)
+    hql = "DROP TABLE %s" % (table,)
     query_msg = make_beeswax_query(request, hql)
     try:
       return execute_directly(request,
@@ -108,7 +108,7 @@ def drop_table(request, table):
 
 def read_table(request, table):
   """View function for select * from table"""
-  hql = "SELECT * FROM `%s`" % (table,)
+  hql = "SELECT * FROM %s" % (table,)
   query_msg = make_beeswax_query(request, hql)
   try:
     return execute_directly(request, query_msg, tablename=table)
@@ -962,7 +962,7 @@ def _save_results_ctas(request, query_history, target_table, result_meta):
   """
   # Case 1: The results are straight from an existing table
   if result_meta.in_tablename:
-    hql = 'CREATE TABLE `%s` AS SELECT * FROM `%s`' % (target_table, result_meta.in_tablename)
+    hql = 'CREATE TABLE %s AS SELECT * FROM %s' % (target_table, result_meta.in_tablename)
     query_msg = make_beeswax_query(request, hql)
     # Display the CTAS running. Could take a long time.
     return execute_directly(request, query_msg, on_success_url=urlresolvers.reverse(show_tables))
@@ -1031,7 +1031,7 @@ def load_table(request, table):
       if form.cleaned_data['overwrite']:
         hql += " OVERWRITE"
       hql += " INTO TABLE "
-      hql += "`%s`" % (table,)
+      hql += "%s" % (table,)
       if len(form.partition_columns) > 0:
         hql += " PARTITION ("
         vals = []

+ 6 - 3
desktop/libs/hadoop/src/hadoop/mini_cluster.py

@@ -59,7 +59,7 @@ MAX_CLUSTER_STARTUP_TIME = 120.0
 
 # users and their groups which are used in Hue tests.
 TEST_USER_GROUP_MAPPING = {
-   'test': ['test'], 'chown_test': ['chown_test'],
+   'test': ['test','users'], 'chown_test': ['chown_test'],
    'notsuperuser': ['notsuperuser'], 'gamma': ['gamma'],
    'webui': ['webui']
 }
@@ -123,7 +123,9 @@ rpc.class=org.apache.hadoop.metrics.spi.NoEmitMetricsContext
       tmppath('ugm.properties'))
 
     write_config({'hadoop.security.group.mapping': 'org.apache.hadoop.security.StaticUserGroupMapping',
-      'hadoop.security.static.group.mapping.file': tmppath('ugm.properties')}, tmppath('in-conf/core-site.xml'))
+      'hadoop.security.static.group.mapping.file': tmppath('ugm.properties'),
+      'hadoop.proxyuser.'+self.superuser+'.groups': 'users',
+      'hadoop.proxyuser.'+self.superuser+'.hosts': 'localhost'}, tmppath('in-conf/core-site.xml'))
 
     hadoop_policy_keys = ['client', 'client.datanode', 'datanode', 'inter.datanode', 'namenode', 'inter.tracker', 'job.submission', 'task.umbilical', 'refresh.policy', 'admin.operations']
     hadoop_policy_config = {}
@@ -241,7 +243,8 @@ rpc.class=org.apache.hadoop.metrics.spi.NoEmitMetricsContext
     write_config(self.config, tmppath("conf/core-site.xml"), 
       ["fs.default.name", "jobclient.completion.poll.interval",
        "fs.checkpoint.period", "fs.checkpoint.dir",
-       'hadoop.security.group.mapping', 'hadoop.security.static.group.mapping.file'])
+       'hadoop.security.group.mapping', 'hadoop.security.static.group.mapping.file',
+       'hadoop.proxyuser.'+self.superuser+'.groups', 'hadoop.proxyuser.'+self.superuser+'.hosts'])
     write_config(self.config, tmppath("conf/hdfs-site.xml"), ["fs.default.name", "dfs.http.address", "dfs.secondary.http.address"])
     # mapred.job.tracker isn't written out into self.config, so we fill
     # that one out more manually.