From 363bd16e314490e31758cc82de584e75cd8357cc Mon Sep 17 00:00:00 2001 From: Wei-Chiu Chuang Date: Tue, 14 Aug 2018 17:19:00 -0700 Subject: [PATCH] HADOOP-14212. Expose SecurityEnabled boolean field in JMX for other services besides NameNode. Contributed by Adam Antal. --- .../hadoop/hdfs/server/datanode/DataNode.java | 5 ++ .../hdfs/server/datanode/DataNodeMXBean.java | 7 +++ .../server/namenode/SecondaryNameNode.java | 5 ++ .../namenode/SecondaryNameNodeInfoMXBean.java | 7 +++ .../server/datanode/TestDataNodeMXBean.java | 47 ++++++++++++++++- .../server/namenode/TestSecureNameNode.java | 52 ++++++++++++++++++- .../yarn/server/nodemanager/NodeManager.java | 20 ++++++- .../resourcemanager/ResourceManager.java | 18 ++++++- 8 files changed, 156 insertions(+), 5 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java index aa044f9e7bb..ea3bab646c9 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java @@ -3142,6 +3142,11 @@ public String getDiskBalancerStatus() { } } + @Override + public boolean isSecurityEnabled() { + return UserGroupInformation.isSecurityEnabled(); + } + public void refreshNamenodes(Configuration conf) throws IOException { blockPoolManager.refreshNamenodes(conf); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNodeMXBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNodeMXBean.java index b5f0cd0a5d3..9d11e148847 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNodeMXBean.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNodeMXBean.java @@ -146,4 +146,11 @@ public interface DataNodeMXBean { * @return list of slow disks */ String getSlowDisks(); + + /** + * Gets if security is enabled. + * + * @return true, if security is enabled. + */ + boolean isSecurityEnabled(); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java index ff83e3493c6..4d7b7473eee 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java @@ -722,6 +722,11 @@ public String getHostAndPort() { return NetUtils.getHostPortString(nameNodeAddr); } + @Override + public boolean isSecurityEnabled() { + return UserGroupInformation.isSecurityEnabled(); + } + @Override // SecondaryNameNodeInfoMXBean public long getStartTime() { return starttime; diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNodeInfoMXBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNodeInfoMXBean.java index 785c5ee3103..a042dc24f69 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNodeInfoMXBean.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNodeInfoMXBean.java @@ -31,6 +31,13 @@ public interface SecondaryNameNodeInfoMXBean extends VersionInfoMXBean { */ public String getHostAndPort(); + /** + * Gets if security is enabled. + * + * @return true, if security is enabled. + */ + boolean isSecurityEnabled(); + /** * @return the timestamp of when the SNN starts */ diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeMXBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeMXBean.java index 9107aaef600..3546ad880ca 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeMXBean.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeMXBean.java @@ -38,6 +38,8 @@ import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSTestUtil; import org.apache.hadoop.hdfs.MiniDFSCluster; +import org.apache.hadoop.hdfs.protocol.datatransfer.sasl.SaslDataTransferTestCase; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.test.GenericTestUtils; import org.junit.Assert; import org.junit.Test; @@ -49,7 +51,7 @@ /** * Class for testing {@link DataNodeMXBean} implementation */ -public class TestDataNodeMXBean { +public class TestDataNodeMXBean extends SaslDataTransferTestCase { public static final Log LOG = LogFactory.getLog(TestDataNodeMXBean.class); @@ -117,6 +119,49 @@ public void testDataNodeMXBean() throws Exception { } } } + + @Test + public void testDataNodeMXBeanSecurityEnabled() throws Exception { + Configuration simpleConf = new Configuration(); + Configuration secureConf = createSecureConfig("authentication"); + + // get attribute "SecurityEnabled" with simple configuration + try (MiniDFSCluster cluster = + new MiniDFSCluster.Builder(simpleConf).build()) { + List datanodes = cluster.getDataNodes(); + Assert.assertEquals(datanodes.size(), 1); + DataNode datanode = datanodes.get(0); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName mxbeanName = new ObjectName( + "Hadoop:service=DataNode,name=DataNodeInfo"); + + boolean securityEnabled = (boolean) mbs.getAttribute(mxbeanName, + "SecurityEnabled"); + Assert.assertFalse(securityEnabled); + Assert.assertEquals(datanode.isSecurityEnabled(), securityEnabled); + } + + // get attribute "SecurityEnabled" with secure configuration + try (MiniDFSCluster cluster = + new MiniDFSCluster.Builder(secureConf).build()) { + List datanodes = cluster.getDataNodes(); + Assert.assertEquals(datanodes.size(), 1); + DataNode datanode = datanodes.get(0); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName mxbeanName = new ObjectName( + "Hadoop:service=DataNode,name=DataNodeInfo"); + + boolean securityEnabled = (boolean) mbs.getAttribute(mxbeanName, + "SecurityEnabled"); + Assert.assertTrue(securityEnabled); + Assert.assertEquals(datanode.isSecurityEnabled(), securityEnabled); + } + + // setting back the authentication method + UserGroupInformation.setConfiguration(simpleConf); + } private static String replaceDigits(final String s) { return s.replaceAll("[0-9]+", "_DIGITS_"); diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSecureNameNode.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSecureNameNode.java index 6b6ce53d82a..c90a91c67d4 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSecureNameNode.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSecureNameNode.java @@ -22,8 +22,10 @@ import static org.junit.Assert.fail; import java.io.IOException; +import java.lang.management.ManagementFactory; import java.security.PrivilegedExceptionAction; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; @@ -33,10 +35,12 @@ import org.apache.hadoop.hdfs.protocol.datatransfer.sasl.SaslDataTransferTestCase; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; - +import javax.management.MBeanServer; +import javax.management.ObjectName; public class TestSecureNameNode extends SaslDataTransferTestCase { final static private int NUM_OF_DATANODES = 0; @@ -117,4 +121,50 @@ public void testKerberosHdfsBlockTokenInconsistencyNNStartup() throws Exception return; } + /** + * Test NameNodeStatusMXBean with security enabled and disabled. + * + * @throws Exception + */ + @Test + public void testNameNodeStatusMXBeanSecurityEnabled() throws Exception { + Configuration simpleConf = new Configuration(); + Configuration secureConf = createSecureConfig("authentication"); + + // disabling security + UserGroupInformation.setConfiguration(simpleConf); + + // get attribute "SecurityEnabled" with simple configuration + try (MiniDFSCluster cluster = + new MiniDFSCluster.Builder(simpleConf).build()) { + cluster.waitActive(); + NameNode namenode = cluster.getNameNode(); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName mxbeanName = new ObjectName( + "Hadoop:service=NameNode,name=NameNodeStatus"); + + boolean securityEnabled = (boolean) mbs.getAttribute(mxbeanName, + "SecurityEnabled"); + Assert.assertFalse(securityEnabled); + Assert.assertEquals(namenode.isSecurityEnabled(), securityEnabled); + } + + // get attribute "SecurityEnabled" with secure configuration + try (MiniDFSCluster cluster = + new MiniDFSCluster.Builder(secureConf).build()) { + cluster.waitActive(); + NameNode namenode = cluster.getNameNode(); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName mxbeanName = new ObjectName( + "Hadoop:service=NameNode,name=NameNodeStatus"); + + boolean securityEnabled = (boolean) mbs.getAttribute(mxbeanName, + "SecurityEnabled"); + Assert.assertTrue(securityEnabled); + Assert.assertEquals(namenode.isSecurityEnabled(), securityEnabled); + } + } + } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java index c8234bd2d47..b54a6b7400e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java @@ -25,8 +25,10 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; +import org.apache.hadoop.metrics2.util.MBeans; import org.apache.hadoop.security.Credentials; import org.apache.hadoop.security.SecurityUtil; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.service.CompositeService; import org.apache.hadoop.util.ExitUtil; import org.apache.hadoop.util.GenericOptionsParser; @@ -87,8 +89,8 @@ import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.atomic.AtomicBoolean; -public class NodeManager extends CompositeService - implements EventHandler { +public class NodeManager extends CompositeService + implements EventHandler, NodeManagerMXBean { /** * Node manager return status codes. @@ -470,6 +472,8 @@ protected void serviceInit(Configuration conf) throws Exception { throw new YarnRuntimeException("Failed NodeManager login", e); } + registerMXBean(); + super.serviceInit(conf); // TODO add local dirs to del } @@ -947,6 +951,18 @@ public void handle(NodeManagerEvent event) { LOG.warn("Invalid shutdown event " + event.getType() + ". Ignoring."); } } + + /** + * Register NodeManagerMXBean. + */ + private void registerMXBean() { + MBeans.register("NodeManager", "NodeManager", this); + } + + @Override + public boolean isSecurityEnabled() { + return UserGroupInformation.isSecurityEnabled(); + } // For testing NodeManager createNewNodeManager() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java index bb85b6798e8..d459f0e952b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java @@ -33,6 +33,7 @@ import org.apache.hadoop.metrics2.MetricsSystem; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; import org.apache.hadoop.metrics2.source.JvmMetrics; +import org.apache.hadoop.metrics2.util.MBeans; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; @@ -140,7 +141,8 @@ * */ @SuppressWarnings("unchecked") -public class ResourceManager extends CompositeService implements Recoverable { +public class ResourceManager extends CompositeService + implements Recoverable, ResourceManagerMXBean { /** * Priority of the ResourceManager shutdown hook. @@ -337,6 +339,8 @@ protected void serviceInit(Configuration conf) throws Exception { addIfService(systemMetricsPublisher); rmContext.setSystemMetricsPublisher(systemMetricsPublisher); + registerMXBean(); + super.serviceInit(this.conf); } @@ -1600,4 +1604,16 @@ private static void printUsage(PrintStream out) { protected RMAppLifetimeMonitor createRMAppLifetimeMonitor() { return new RMAppLifetimeMonitor(this.rmContext); } + + /** + * Register ResourceManagerMXBean. + */ + private void registerMXBean() { + MBeans.register("ResourceManager", "ResourceManager", this); + } + + @Override + public boolean isSecurityEnabled() { + return UserGroupInformation.isSecurityEnabled(); + } }