Ver código fonte

HADOOP-8988. Allow configuration of authorization for JmxJsonServlet and MetricsServlet. Contributed by Jing Zhao.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1@1404882 13f79535-47bb-0310-9956-ffa450edef68
Suresh Srinivas 12 anos atrás
pai
commit
dc934ed109

+ 3 - 0
CHANGES.txt

@@ -29,6 +29,9 @@ Release 1.2.0 - unreleased
     HDFS-3912. Detect and avoid stale datanodes for writes.
     (Jing Zhao via suresh)
 
+    HADOOP-8988. Allow configuration of authorization for JmxJsonServlet and 
+    MetricsServlet. (tucu, Jing Zhao via suresh)
+
   IMPROVEMENTS
 
     HDFS-3515. Port HDFS-1457 to branch-1. (eli)

+ 9 - 0
src/core/core-default.xml

@@ -44,6 +44,15 @@
   <description>Is service-level authorization enabled?</description>
 </property>
 
+<property>
+  <name>hadoop.security.instrumentation.requires.admin</name>
+  <value>false</value>
+  <description>
+    Indicates if administrator ACLs are required to access
+    instrumentation servlets (JMX, METRICS, CONF, STACKS).
+  </description>
+</property>
+
 <property>
   <name>hadoop.security.authentication</name>
   <value>simple</value>

+ 4 - 0
src/core/org/apache/hadoop/conf/ConfServlet.java

@@ -55,6 +55,10 @@ public class ConfServlet extends HttpServlet {
   @Override
   public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
+    if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(),
+        request, response)) {
+      return;
+    }
     String format = request.getParameter(FORMAT_PARAM);
     if (null == format) {
       format = FORMAT_XML;

+ 3 - 0
src/core/org/apache/hadoop/fs/CommonConfigurationKeys.java

@@ -40,6 +40,9 @@ public class CommonConfigurationKeys {
   public static final String HADOOP_SECURITY_AUTHORIZATION =
     "hadoop.security.authorization";
   /** See src/core/core-default.xml */
+  public static final String HADOOP_SECURITY_INSTRUMENTATION_REQUIRES_ADMIN = 
+      "hadoop.security.instrumentation.requires.admin";
+  /** See src/core/core-default.xml */
   public static final String  HADOOP_SECURITY_SERVICE_USER_NAME_KEY = 
     "hadoop.security.service.user.name.key";
   /** See src/core/core-default.xml */

+ 33 - 2
src/core/org/apache/hadoop/http/HttpServer.java

@@ -692,6 +692,37 @@ public class HttpServer implements FilterContainer {
     webServer.join();
   }
 
+  /**
+   * Checks the user has privileges to access to instrumentation servlets.
+   * <p/>
+   * If <code>hadoop.security.instrumentation.requires.admin</code> is set to 
+   * FALSE (default value) it returns always returns TRUE.
+   * <p/>
+   * If <code>hadoop.security.instrumentation.requires.admin</code> is set to 
+   * TRUE it will check that if the current user is in the admin ACLS. If the 
+   * user is in the admin ACLs it returns TRUE, otherwise it returns FALSE.
+   *
+   * @param servletContext the servlet context.
+   * @param request the servlet request.
+   * @param response the servlet response.
+   * @return TRUE/FALSE based on the logic decribed above.
+   */
+  public static boolean isInstrumentationAccessAllowed(
+      ServletContext servletContext, HttpServletRequest request,
+      HttpServletResponse response) throws IOException {
+    Configuration conf = (Configuration) servletContext
+        .getAttribute(CONF_CONTEXT_ATTRIBUTE);
+
+    boolean access = true;
+    boolean adminAccess = conf.getBoolean(
+        CommonConfigurationKeys.HADOOP_SECURITY_INSTRUMENTATION_REQUIRES_ADMIN,
+        false);
+    if (adminAccess) {
+      access = hasAdministratorAccess(servletContext, request, response);
+    }
+    return access;
+  }
+  
   /**
    * Does the user sending the HttpServletRequest has the administrator ACLs? If
    * it isn't the case, response will be modified to send an error to the user.
@@ -749,8 +780,8 @@ public class HttpServer implements FilterContainer {
       throws ServletException, IOException {
 
       // Do the authorization
-      if (!HttpServer.hasAdministratorAccess(getServletContext(), request,
-          response)) {
+      if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(),
+          request, response)) {
         return;
       }
 

+ 2 - 2
src/core/org/apache/hadoop/jmx/JMXJsonServlet.java

@@ -134,8 +134,8 @@ public class JMXJsonServlet extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) {
     try {
       // Do the authorization
-      if (!HttpServer.hasAdministratorAccess(getServletContext(), request,
-          response)) {
+      if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(),
+          request, response)) {
         return;
       }
 

+ 2 - 2
src/core/org/apache/hadoop/metrics/MetricsServlet.java

@@ -109,8 +109,8 @@ public class MetricsServlet extends HttpServlet {
       throws ServletException, IOException {
 
     // Do the authorization
-    if (!HttpServer.hasAdministratorAccess(getServletContext(), request,
-        response)) {
+    if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(),
+        request, response)) {
       return;
     }
 

+ 29 - 1
src/test/org/apache/hadoop/http/TestHttpServer.java

@@ -23,7 +23,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
-import java.net.URLConnection;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.Arrays;
@@ -310,6 +309,9 @@ public class TestHttpServer {
     Configuration conf = new Configuration();
     conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION,
         true);
+    conf.setBoolean(
+        CommonConfigurationKeys.HADOOP_SECURITY_INSTRUMENTATION_REQUIRES_ADMIN,
+        true);
     conf.set(HttpServer.FILTER_INITIALIZER_PROPERTY,
         DummyFilterInitializer.class.getName());
 
@@ -395,5 +397,31 @@ public class TestHttpServer {
     Assert.assertTrue(HttpServer.hasAdministratorAccess(context, request, response));
 
   }
+  
+  @Test
+  public void testRequiresAuthorizationAccess() throws Exception {
+    Configuration conf = new Configuration();
+    ServletContext context = Mockito.mock(ServletContext.class);
+    Mockito.when(context.getAttribute(HttpServer.CONF_CONTEXT_ATTRIBUTE))
+        .thenReturn(conf);
+    HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+    HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
 
+    // requires admin access to instrumentation, FALSE by default
+    Assert.assertTrue(HttpServer.isInstrumentationAccessAllowed(context,
+        request, response));
+
+    // requires admin access to instrumentation, TRUE
+    conf.setBoolean(
+        CommonConfigurationKeys.HADOOP_SECURITY_INSTRUMENTATION_REQUIRES_ADMIN,
+        true);
+    conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION, true);
+    AccessControlList acls = Mockito.mock(AccessControlList.class);
+    Mockito.when(acls.isUserAllowed(Mockito.<UserGroupInformation> any()))
+        .thenReturn(false);
+    Mockito.when(context.getAttribute(HttpServer.ADMINS_ACL)).thenReturn(acls);
+    Assert.assertFalse(HttpServer.isInstrumentationAccessAllowed(context,
+        request, response));
+  }
+  
 }