Browse Source

Merged r1179713 from branch-0.20-security for HADOOP-7721 and HDFS-2405.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20-security-205@1179716 13f79535-47bb-0310-9956-ffa450edef68
Jitendra Nath Pandey 14 years ago
parent
commit
5617c763cf

+ 3 - 0
CHANGES.txt

@@ -271,6 +271,9 @@ Release 0.20.205.0 - 2011.09.28
     HDFS-2408. DFSClient#getNumCurrentReplicas is package private in 205 but
                public in branch-0.20-append (stack via atm)
 
+    HADOOP-7721. dfs.web.authentication.kerberos.principal expects the full 
+    hostname and does not replace _HOST with the hostname. (jitendra)
+
   IMPROVEMENTS
 
     MAPREDUCE-2928. MR-2413 improvements (Eli Collins via mattf)

+ 1 - 0
src/core/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java

@@ -160,6 +160,7 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler {
 
       KerberosConfiguration kerberosConfiguration = new KerberosConfiguration(keytab, principal);
 
+      LOG.info("Login using keytab "+keytab+", for principal "+principal);
       loginContext = new LoginContext("", subject, null, kerberosConfiguration);
       loginContext.login();
 

+ 3 - 0
src/hdfs/org/apache/hadoop/hdfs/DFSConfigKeys.java

@@ -216,4 +216,7 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
   public static final String  DFS_SECONDARY_NAMENODE_KRB_HTTPS_USER_NAME_KEY = "dfs.secondary.namenode.kerberos.https.principal";
   public static final String  DFS_NAMENODE_NAME_CACHE_THRESHOLD_KEY = "dfs.namenode.name.cache.threshold";
   public static final int     DFS_NAMENODE_NAME_CACHE_THRESHOLD_DEFAULT = 10;
+  
+  public static final String  DFS_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY = "dfs.web.authentication.kerberos.principal";
+  public static final String  DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY = "dfs.web.authentication.kerberos.keytab";
 }

+ 28 - 1
src/hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java

@@ -25,8 +25,10 @@ import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -363,7 +365,8 @@ public class NameNode implements ClientProtocol, DatanodeProtocol,
                 final String name = "SPNEGO";
                 final String classname =  AuthFilter.class.getName();
                 final String pathSpec = "/" + WebHdfsFileSystem.PATH_PREFIX + "/*";
-                defineFilter(webAppContext, name, classname, null,
+                Map<String, String> params = getAuthFilterParams(conf);
+                defineFilter(webAppContext, name, classname, params,
                     new String[]{pathSpec});
                 LOG.info("Added filter '" + name + "' (class=" + classname + ")");
 
@@ -373,6 +376,30 @@ public class NameNode implements ClientProtocol, DatanodeProtocol,
                     + ";" + Param.class.getPackage().getName(), pathSpec);
               }
             }
+
+            private Map<String, String> getAuthFilterParams(Configuration conf)
+                throws IOException {
+              Map<String, String> params = new HashMap<String, String>();
+              String principalInConf = conf
+                  .get(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY);
+              if (principalInConf != null && !principalInConf.isEmpty()) {
+                params
+                    .put(
+                        DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY,
+                        SecurityUtil.getServerPrincipal(principalInConf,
+                            serverAddress.getHostName()));
+              }
+              String httpKeytab = conf
+                  .get(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY);
+              if (httpKeytab != null && !httpKeytab.isEmpty()) {
+                params.put(
+                    DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY,
+                    httpKeytab);
+              }
+              params.put("kerberos.name.rules",
+                  conf.get("hadoop.security.auth_to_local", "DEFAULT"));
+              return params;
+            }
           };
           
           boolean certSSL = conf.getBoolean("dfs.https.enable", false);

+ 8 - 18
src/hdfs/org/apache/hadoop/hdfs/web/AuthFilter.java

@@ -17,12 +17,11 @@
  */
 package org.apache.hadoop.hdfs.web;
 
-import java.util.Map;
 import java.util.Properties;
 
 import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
 
-import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
 import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
@@ -41,30 +40,21 @@ public class AuthFilter extends AuthenticationFilter {
    * The prefix is removed from the returned property names.
    *
    * @param prefix parameter not used.
-   * @param config parameter not used.
+   * @param config parameter contains the initialization values.
    * @return Hadoop-Auth configuration properties.
+   * @throws ServletException 
    */
   @Override
-  protected Properties getConfiguration(String prefix, FilterConfig config) {
-    final Configuration conf = new Configuration();
-    final Properties p = new Properties();
-
-    //set authentication type
+  protected Properties getConfiguration(String prefix, FilterConfig config)
+      throws ServletException {
+    final Properties p = super.getConfiguration(CONF_PREFIX, config);
+    // set authentication type
     p.setProperty(AUTH_TYPE, UserGroupInformation.isSecurityEnabled()?
         KerberosAuthenticationHandler.TYPE: PseudoAuthenticationHandler.TYPE);
     //For Pseudo Authentication, allow anonymous.
     p.setProperty(PseudoAuthenticationHandler.ANONYMOUS_ALLOWED, "true");
     //set cookie path
     p.setProperty(COOKIE_PATH, "/");
-
-    //set other configurations with CONF_PREFIX
-    for (Map.Entry<String, String> entry : conf) {
-      final String key = entry.getKey();
-      if (key.startsWith(CONF_PREFIX)) {
-        //remove prefix from the key and set property
-        p.setProperty(key.substring(CONF_PREFIX.length()), conf.get(key));
-      }
-    }
-    return p;
+   return p;
   }
 }

+ 4 - 2
src/hdfs/org/apache/hadoop/hdfs/web/resources/UserProvider.java

@@ -20,6 +20,7 @@ package org.apache.hadoop.hdfs.web.resources;
 import java.io.IOException;
 import java.lang.reflect.Type;
 
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.ext.Provider;
@@ -42,11 +43,12 @@ public class UserProvider
     extends AbstractHttpContextInjectable<UserGroupInformation>
     implements InjectableProvider<Context, Type> {
   @Context HttpServletRequest request;
+  @Context ServletContext servletcontext;
 
   @Override
   public UserGroupInformation getValue(final HttpContext context) {
-    final Configuration conf = (Configuration)context.getProperties().get(
-        JspHelper.CURRENT_CONF);
+    final Configuration conf = (Configuration) servletcontext
+        .getAttribute(JspHelper.CURRENT_CONF);
     try {
       return JspHelper.getUGI(request, conf,
           AuthenticationMethod.KERBEROS, false);

+ 78 - 0
src/test/org/apache/hadoop/hdfs/web/TestAuthFilter.java

@@ -0,0 +1,78 @@
+/**
+ * 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.hdfs.web;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.hadoop.hdfs.DFSConfigKeys;
+import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestAuthFilter {
+  
+  private static class DummyFilterConfig implements FilterConfig {
+    final Map<String, String> map;
+    
+    DummyFilterConfig(Map<String,String> map) {
+      this.map = map;
+    }
+    
+    @Override
+    public String getFilterName() {
+      return "dummy";
+    }
+    @Override
+    public String getInitParameter(String arg0) {
+      return map.get(arg0);
+    }
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+      return Collections.enumeration(map.keySet());
+    }
+    @Override
+    public ServletContext getServletContext() {
+      return null;
+    }
+  }
+  
+  @Test
+  public void testGetConfiguration() throws ServletException {
+    AuthFilter filter = new AuthFilter();
+    Map<String, String> m = new HashMap<String,String>();
+    m.put(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY,
+        "xyz/thehost@REALM");
+    m.put(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY,
+        "thekeytab");
+    FilterConfig config = new DummyFilterConfig(m);
+    Properties p = filter.getConfiguration("random", config);
+    Assert.assertEquals("xyz/thehost@REALM",
+        p.getProperty("kerberos.principal"));
+    Assert.assertEquals("thekeytab", p.getProperty("kerberos.keytab"));
+    Assert.assertEquals("true",
+        p.getProperty(PseudoAuthenticationHandler.ANONYMOUS_ALLOWED));
+  }
+}