From 62deab17a33cef723d73f8d8b9e37e5bddbc1813 Mon Sep 17 00:00:00 2001 From: Ayush Saxena Date: Thu, 25 Jul 2019 06:51:07 +0530 Subject: [PATCH] HDFS-14647. NPE during secure namenode startup. Contributed by Fengnan Li. --- .../hadoop/hdfs/server/namenode/NameNode.java | 4 +++ .../hdfs/server/common/TestJspHelper.java | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java index ec6ce36cf8..c3107d5317 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java @@ -682,6 +682,10 @@ public static UserGroupInformation getRemoteUser() throws IOException { @Override public void verifyToken(DelegationTokenIdentifier id, byte[] password) throws IOException { + // during startup namesystem is null, let client retry + if (namesystem == null) { + throw new RetriableException("Namenode is in startup mode"); + } namesystem.verifyToken(id, password); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java index 5a1661c987..1aff7669e9 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java @@ -21,12 +21,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.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; @@ -36,9 +38,11 @@ import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; +import org.apache.hadoop.test.LambdaTestUtils; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -371,8 +375,38 @@ public void testGetProxyUgi() throws IOException { } } + @Test + public void testGetUgiDuringStartup() throws Exception { + 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 token = + new Token(dtId, + new DummySecretManager(0, 0, 0, 0)); + String tokenString = token.encodeToUrlString(); + // token with auth-ed user + request = getMockRequest(realUser, null, null); + when(request.getParameter(JspHelper.DELEGATION_PARAMETER_NAME)).thenReturn( + tokenString); + + NameNode mockNN = mock(NameNode.class); + Mockito.doCallRealMethod().when(mockNN) + .verifyToken(Mockito.any(), Mockito.any()); + when(context.getAttribute("name.node")).thenReturn(mockNN); + + LambdaTestUtils.intercept(RetriableException.class, + "Namenode is in startup mode", + () -> JspHelper.getUGI(context, request, conf)); + } private HttpServletRequest getMockRequest(String remoteUser, String user, String doAs) { HttpServletRequest request = mock(HttpServletRequest.class);