Browse Source

HDFS-14647. NPE during secure namenode startup. Contributed by Fengnan Li.

Chen Liang 5 years ago
parent
commit
4cf7bbf043

+ 9 - 2
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/JspHelper.java

@@ -43,10 +43,12 @@ import org.apache.hadoop.hdfs.protocol.LocatedBlock;
 import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
 import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
 import org.apache.hadoop.hdfs.security.token.delegation.DelegationUtilsClient;
+import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
 import org.apache.hadoop.hdfs.server.namenode.NameNode;
 import org.apache.hadoop.hdfs.server.namenode.NameNodeHttpServer;
 import org.apache.hadoop.hdfs.web.resources.DoAsParam;
 import org.apache.hadoop.hdfs.web.resources.UserParam;
+import org.apache.hadoop.ipc.RetriableException;
 import org.apache.hadoop.net.NetUtils;
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.SecurityUtil;
@@ -270,7 +272,6 @@ public class JspHelper {
       SecurityUtil.setTokenService(token, serviceAddress);
       token.setKind(DelegationTokenIdentifier.HDFS_DELEGATION_KIND);
     }
-
     ByteArrayInputStream buf =
         new ByteArrayInputStream(token.getIdentifier());
     DataInputStream in = new DataInputStream(buf);
@@ -279,8 +280,14 @@ public class JspHelper {
     if (context != null) {
       final NameNode nn = NameNodeHttpServer.getNameNodeFromContext(context);
       if (nn != null) {
+        FSNamesystem namesystem = nn.getNamesystem();
+        // namesystem can be null during startup period at this moment.
+        // so bypass this verification step
+        if (namesystem == null) {
+          throw new RetriableException("Namenode is in startup mode");
+        }
         // Verify the token.
-        nn.getNamesystem().verifyToken(id, token.getPassword());
+        namesystem.verifyToken(id, token.getPassword());
       }
     }
     UserGroupInformation ugi = id.getUser();

+ 35 - 0
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java

@@ -22,12 +22,14 @@ import org.apache.hadoop.hdfs.DFSConfigKeys;
 import org.apache.hadoop.hdfs.HdfsConfiguration;
 import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
 import org.apache.hadoop.hdfs.security.token.delegation.DelegationUtilsClient;
+import org.apache.hadoop.hdfs.server.namenode.NameNode;
 import org.apache.hadoop.hdfs.server.namenode.NameNodeHttpServer;
 import org.apache.hadoop.hdfs.web.resources.DoAsParam;
 import org.apache.hadoop.hdfs.web.resources.UserParam;
 import org.apache.hadoop.io.DataInputBuffer;
 import org.apache.hadoop.io.DataOutputBuffer;
 import org.apache.hadoop.io.Text;
+import org.apache.hadoop.ipc.RetriableException;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 import org.apache.hadoop.security.authorize.AuthorizationException;
@@ -369,6 +371,39 @@ public class TestJspHelper {
     }
   }
 
+  @Test
+  public void testGetUgiDuringStartup() throws IOException {
+    conf.set(DFSConfigKeys.FS_DEFAULT_NAME_KEY, "hdfs://localhost:4321/");
+    ServletContext context = mock(ServletContext.class);
+    String realUser = "TheDoctor";
+    String user = "TheNurse";
+    conf.set(DFSConfigKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
+    UserGroupInformation.setConfiguration(conf);
+    HttpServletRequest request;
+
+    Text ownerText = new Text(user);
+    DelegationTokenIdentifier dtId = new DelegationTokenIdentifier(
+        ownerText, ownerText, new Text(realUser));
+    Token<DelegationTokenIdentifier> token = new Token<DelegationTokenIdentifier>(
+        dtId, new DummySecretManager(0, 0, 0, 0));
+    String tokenString = token.encodeToUrlString();
+
+    // token with auth-ed user
+    request = getMockRequest(realUser, null, null);
+    when(request.getParameter(DelegationUtilsClient.DELEGATION_PARAMETER_NAME)).thenReturn(
+        tokenString);
+
+    NameNode mockNN = mock(NameNode.class);
+    when(mockNN.getNamesystem()).thenReturn(null);
+    when(context.getAttribute("name.node")).thenReturn(mockNN);
+
+    try {
+      JspHelper.getUGI(context, request, conf);
+    } catch (RetriableException e) {
+      Assert.assertEquals("Namenode is in startup mode", e.getMessage());
+    }
+  }
+
   private HttpServletRequest getMockRequest(String remoteUser, String user, String doAs) {
     HttpServletRequest request = mock(HttpServletRequest.class);
     when(request.getParameter(UserParam.NAME)).thenReturn(user);