瀏覽代碼

commit e563cb8d6f227da2933e842be75d24392bd7b9a4
Author: Jakob Homan <jhoman@yahoo-inc.com>
Date: Wed Mar 17 20:32:34 2010 -0700

HDFS:1045 from https://issues.apache.org/jira/secure/attachment/12439110/HDFS-1045-Y20.patch

+++ b/YAHOO-CHANGES.txt
+ HDFS-1045. In secure clusters, re-login is necessary for https
+ clients before opening connections (jhoman)
+


git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20-security-patches@1077331 13f79535-47bb-0310-9956-ffa450edef68

Owen O'Malley 14 年之前
父節點
當前提交
4657e67683

+ 39 - 0
src/core/org/apache/hadoop/security/UserGroupInformation.java

@@ -411,6 +411,45 @@ public class UserGroupInformation {
                             path, le);
     }
   }
+  /**
+   * Log a user in from a keytab file. Loads a user identity from a keytab
+   * file and login them in. This new user does not affect the currently
+   * logged-in user.
+   * @param user the principal name to load from the keytab
+   * @param path the path to the keytab file
+   * @throws IOException if the keytab file can't be read
+   */
+  public synchronized
+  static UserGroupInformation loginUserFromKeytabAndReturnUGI(String user,
+                                  String path
+                                  ) throws IOException {
+    if (!isSecurityEnabled())
+      return UserGroupInformation.getCurrentUser();
+    String oldKeytabFile = null;
+    String oldKeytabPrincipal = null;
+
+    try {
+      oldKeytabFile = keytabFile;
+      oldKeytabPrincipal = keytabPrincipal;
+      keytabFile = path;
+      keytabPrincipal = user;
+      Subject subject = new Subject();
+      LoginContext login = 
+        new LoginContext(HadoopConfiguration.KEYTAB_KERBEROS_CONFIG_NAME, subject); 
+       
+      login.login();
+      UserGroupInformation newLoginUser = new UserGroupInformation(subject);
+      newLoginUser.login = login;
+      
+      return newLoginUser;
+    } catch (LoginException le) {
+      throw new IOException("Login failure for " + user + " from keytab " + 
+                            path, le);
+    } finally {
+      if(oldKeytabFile != null) keytabFile = oldKeytabFile;
+      if(oldKeytabPrincipal != null) keytabPrincipal = oldKeytabPrincipal;
+    }
+  }
   
   /**
    * Re-Login a user in from a keytab file. Loads a user identity from a keytab

+ 22 - 3
src/hdfs/org/apache/hadoop/hdfs/server/namenode/GetImageServlet.java

@@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hdfs.DFSConfigKeys;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.util.StringUtils;
 
@@ -55,7 +56,7 @@ public class GetImageServlet extends HttpServlet {
       ServletContext context = getServletContext();
       final FSImage nnImage = (FSImage)context.getAttribute("name.system.image");
       final TransferFsImage ff = new TransferFsImage(pmap, request, response);
-      Configuration conf = (Configuration)getServletContext().getAttribute("name.conf");
+      final Configuration conf = (Configuration)getServletContext().getAttribute("name.conf");
       if(UserGroupInformation.isSecurityEnabled() && 
           !isValidRequestor(request.getRemoteUser(), conf)) {
         response.sendError(HttpServletResponse.SC_FORBIDDEN, 
@@ -80,12 +81,30 @@ public class GetImageServlet extends HttpServlet {
           } else if (ff.putImage()) {
             // issue a HTTP get request to download the new fsimage 
             nnImage.validateCheckpointUpload(ff.getToken());
-            TransferFsImage.getFileClient(ff.getInfoServer(), "getimage=1", 
-                                          nnImage.getFsImageNameCheckpoint());
+            reloginIfNecessary().doAs(new PrivilegedExceptionAction<Void>() {
+              @Override
+              public Void run() throws Exception {
+                TransferFsImage.getFileClient(ff.getInfoServer(), "getimage=1", 
+                    nnImage.getFsImageNameCheckpoint());
+                return null;
+              }
+            });
+
             nnImage.checkpointUploadDone();
           }
           return null;
         }
+
+        // We may have lost our ticket since the last time we tried to open
+        // an http connection, so log in just in case.
+        private UserGroupInformation reloginIfNecessary() throws IOException {
+          // This method is only called on the NN, therefore it is safe to
+          // use these key values.
+          return UserGroupInformation
+          .loginUserFromKeytabAndReturnUGI(
+              conf.get(DFS_NAMENODE_KRB_HTTPS_USER_NAME_KEY), 
+              conf.get(DFSConfigKeys.DFS_NAMENODE_KEYTAB_FILE_KEY));
+        }
       });
 
     } catch (Exception ie) {

+ 3 - 0
src/hdfs/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java

@@ -379,6 +379,9 @@ public class SecondaryNameNode implements Runnable {
                             "after creating edits.new");
     }
 
+    // We may have lost our ticket since last checkpoint, log in again, just in case
+    if(UserGroupInformation.isSecurityEnabled())
+      UserGroupInformation.getCurrentUser().reloginFromKeytab();
     downloadCheckpointFiles(sig);   // Fetch fsimage and edits
     doMerge(sig);                   // Do the merge