From d3106426262daa2431b4d25a310ca20cf7b617a0 Mon Sep 17 00:00:00 2001 From: hchaverri <55413673+hchaverri@users.noreply.github.com> Date: Tue, 7 Feb 2023 10:45:05 -0800 Subject: [PATCH] HDFS-16895. [RBF] NamenodeHeartbeatService should use credentials of logged in user --- .../router/NamenodeHeartbeatService.java | 12 ++++++- .../router/TestRouterNamenodeHeartbeat.java | 32 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/NamenodeHeartbeatService.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/NamenodeHeartbeatService.java index b2f60d9314..86e24a0b24 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/NamenodeHeartbeatService.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/NamenodeHeartbeatService.java @@ -26,6 +26,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; +import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -45,6 +46,7 @@ import org.apache.hadoop.hdfs.tools.NNHAServiceTarget; import org.apache.hadoop.hdfs.web.URLConnectionFactory; import org.apache.hadoop.net.NetUtils; +import org.apache.hadoop.security.SecurityUtil; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; @@ -236,7 +238,15 @@ protected void serviceInit(Configuration configuration) throws Exception { @Override public void periodicInvoke() { - updateState(); + try { + // Run using the login user credentials + SecurityUtil.doAsLoginUser((PrivilegedExceptionAction) () -> { + updateState(); + return null; + }); + } catch (IOException e) { + LOG.error("Cannot update namenode state", e); + } } /** diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterNamenodeHeartbeat.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterNamenodeHeartbeat.java index 04b4b58bcb..bb284c49ce 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterNamenodeHeartbeat.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterNamenodeHeartbeat.java @@ -26,6 +26,7 @@ import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.NAMENODES; import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.NAMESERVICES; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -36,6 +37,7 @@ import java.util.List; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.contract.router.SecurityConfUtil; import org.apache.hadoop.hdfs.DFSUtil; import org.apache.hadoop.hdfs.HdfsConfiguration; import org.apache.hadoop.hdfs.server.federation.MockResolver; @@ -44,6 +46,7 @@ import org.apache.hadoop.hdfs.server.federation.resolver.ActiveNamenodeResolver; import org.apache.hadoop.hdfs.server.federation.resolver.FederationNamenodeContext; import org.apache.hadoop.net.MockDomainNameResolver; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.service.Service.STATE; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -318,4 +321,33 @@ private Configuration generateNamenodeConfiguration( return conf; } + + @Test + public void testNamenodeHeartbeatWithSecurity() throws Exception { + Configuration conf = SecurityConfUtil.initSecurity(); + MiniRouterDFSCluster testCluster = null; + try { + testCluster = new MiniRouterDFSCluster(true, 1, conf); + // Start Namenodes and routers + testCluster.startCluster(conf); + testCluster.startRouters(); + + // Register Namenodes to generate a NamenodeStatusReport + testCluster.registerNamenodes(); + testCluster.waitNamenodeRegistration(); + + for (MiniRouterDFSCluster.RouterContext routerContext : testCluster.getRouters()) { + ActiveNamenodeResolver resolver = routerContext.getRouter().getNamenodeResolver(); + // Validate that NamenodeStatusReport has been registered + assertNotNull(resolver.getNamespaces()); + assertFalse(resolver.getNamespaces().isEmpty()); + } + } finally { + if (testCluster != null) { + testCluster.shutdown(); + } + UserGroupInformation.reset(); + SecurityConfUtil.destroy(); + } + } }