Explorar o código

HUE-219. Add authorization to thrift plugins

Todd Lipcon %!s(int64=15) %!d(string=hai) anos
pai
achega
1ca6d0e084

+ 5 - 1
desktop/libs/hadoop/java/src/java/org/apache/hadoop/mapred/ThriftJobTrackerPlugin.java

@@ -1239,7 +1239,11 @@ public class ThriftJobTrackerPlugin extends JobTrackerPlugin implements Configur
         @Override
         @Override
         public TProcessor getProcessor(TTransport t) {
         public TProcessor getProcessor(TTransport t) {
           ThriftServerContext context = new ThriftServerContext(t);
           ThriftServerContext context = new ThriftServerContext(t);
-          ThriftHandler impl = new ThriftHandler(context);
+          Jobtracker.Iface impl =
+            ThriftUtils.SecurityCheckingProxy.create(
+              conf,
+              new ThriftHandler(context),
+              Jobtracker.Iface.class);
           return new Jobtracker.Processor(impl);
           return new Jobtracker.Processor(impl);
         }
         }
     }
     }

+ 6 - 1
desktop/libs/hadoop/java/src/java/org/apache/hadoop/thriftfs/DatanodePlugin.java

@@ -245,7 +245,12 @@ public class DatanodePlugin
     @Override
     @Override
     public TProcessor getProcessor(TTransport t) {
     public TProcessor getProcessor(TTransport t) {
       ThriftServerContext context = new ThriftServerContext(t);
       ThriftServerContext context = new ThriftServerContext(t);
-      ThriftHandler impl = new ThriftHandler(context);
+
+      Datanode.Iface impl =
+        ThriftUtils.SecurityCheckingProxy.create(
+          conf,
+          new ThriftHandler(context),
+          Datanode.Iface.class);
       return new Datanode.Processor(impl);
       return new Datanode.Processor(impl);
     }
     }
   }
   }

+ 5 - 1
desktop/libs/hadoop/java/src/java/org/apache/hadoop/thriftfs/NamenodePlugin.java

@@ -454,7 +454,11 @@ public class NamenodePlugin extends org.apache.hadoop.hdfs.server.namenode.Namen
     @Override
     @Override
     public TProcessor getProcessor(TTransport t) {
     public TProcessor getProcessor(TTransport t) {
       ThriftServerContext context = new ThriftServerContext(t);
       ThriftServerContext context = new ThriftServerContext(t);
-      ThriftHandler impl = new ThriftHandler(context);
+      Namenode.Iface impl =
+        ThriftUtils.SecurityCheckingProxy.create(
+          conf,
+          new ThriftHandler(context),
+          Namenode.Iface.class);
       return new Namenode.Processor(impl);
       return new Namenode.Processor(impl);
     }
     }
   }
   }

+ 65 - 0
desktop/libs/hadoop/java/src/java/org/apache/hadoop/thriftfs/ThriftUtils.java

@@ -18,9 +18,12 @@
 package org.apache.hadoop.thriftfs;
 package org.apache.hadoop.thriftfs;
 
 
 import java.net.InetSocketAddress;
 import java.net.InetSocketAddress;
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.logging.LogFactory;
@@ -38,6 +41,8 @@ import org.apache.hadoop.thriftfs.api.DatanodeInfo;
 import org.apache.hadoop.thriftfs.api.DatanodeState;
 import org.apache.hadoop.thriftfs.api.DatanodeState;
 import org.apache.hadoop.thriftfs.api.IOException;
 import org.apache.hadoop.thriftfs.api.IOException;
 import org.apache.hadoop.thriftfs.api.Namenode;
 import org.apache.hadoop.thriftfs.api.Namenode;
+import org.apache.hadoop.util.StringUtils;
+import org.apache.thrift.TException;
 import org.apache.thrift.protocol.TBinaryProtocol;
 import org.apache.thrift.protocol.TBinaryProtocol;
 import org.apache.thrift.protocol.TProtocol;
 import org.apache.thrift.protocol.TProtocol;
 import org.apache.thrift.transport.TSocket;
 import org.apache.thrift.transport.TSocket;
@@ -46,6 +51,9 @@ public class ThriftUtils {
   
   
   static final Log LOG = LogFactory.getLog(ThriftUtils.class);
   static final Log LOG = LogFactory.getLog(ThriftUtils.class);
 
 
+  static final String HUE_USER_NAME_KEY = "hue.kerberos.principal.shortname";
+  static final String HUE_USER_NAME_DEFAULT = "hue";
+
   public static LocatedBlock fromThrift(Block block) {
   public static LocatedBlock fromThrift(Block block) {
     if (block == null) {
     if (block == null) {
       return null;
       return null;
@@ -165,6 +173,63 @@ public class ThriftUtils {
     return ret;
     return ret;
   }
   }
 
 
+  public static class SecurityCheckingProxy<T> implements java.lang.reflect.InvocationHandler {
+    private final T wrapped;
+    private final Configuration conf;
+
+    public static <T> T create(Configuration conf, T wrapped, Class<T> iface) {
+      return (T)java.lang.reflect.Proxy.newProxyInstance(
+        iface.getClassLoader(),
+        new Class[] { iface },
+        new SecurityCheckingProxy<T>(wrapped, conf));
+    }
+
+    private SecurityCheckingProxy(T wrapped, Configuration conf) {
+      this.wrapped = wrapped;
+      this.conf = conf;
+    }
+
+    public Object invoke(Object proxy, Method m, Object[] args)
+      throws Throwable
+    {
+      Object result;
+      try {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Call " + wrapped.getClass() + "." + m.getName() +
+                    StringUtils.joinObjects(", ", Arrays.asList(args)));
+        }
+        authorizeCall(m);
+
+	    return m.invoke(wrapped, args);
+      } catch (InvocationTargetException e) {
+	    throw e.getTargetException();
+      }
+    }
+
+    private void authorizeCall(Method m) throws IOException, TException {
+      // TODO: this should use the AccessControlList functionality,
+      // ideally.
+      try {
+        UserGroupInformation caller = UserGroupInformation.getCurrentUser();
+
+        if (!conf.get(HUE_USER_NAME_KEY, HUE_USER_NAME_DEFAULT).equals(
+              caller.getShortUserName()) &&
+            !UserGroupInformation.getLoginUser().getShortUserName().equals(
+              caller.getShortUserName())) {
+
+          String errMsg = "Unauthorized access for user " + caller.getUserName();
+          if (Arrays.asList(m.getExceptionTypes()).contains(IOException.class)) {
+            throw ThriftUtils.toThrift(new Exception(errMsg));
+          } else {
+            throw new TException(errMsg);
+          }
+        }
+      } catch (java.io.IOException ioe) {
+        throw new TException(ioe);
+      }
+    }
+  }
+
   /**
   /**
    * Creates a Thrift name node client.
    * Creates a Thrift name node client.
    * 
    *