Return-Path: X-Original-To: apmail-hadoop-common-commits-archive@www.apache.org Delivered-To: apmail-hadoop-common-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9C7EB173DA for ; Wed, 29 Apr 2015 21:29:10 +0000 (UTC) Received: (qmail 48292 invoked by uid 500); 29 Apr 2015 21:29:05 -0000 Delivered-To: apmail-hadoop-common-commits-archive@hadoop.apache.org Received: (qmail 48230 invoked by uid 500); 29 Apr 2015 21:29:05 -0000 Mailing-List: contact common-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: common-dev@hadoop.apache.org Delivered-To: mailing list common-commits@hadoop.apache.org Received: (qmail 48221 invoked by uid 99); 29 Apr 2015 21:29:05 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Apr 2015 21:29:05 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 4B5B9DFF8C; Wed, 29 Apr 2015 21:29:05 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: tgraves@apache.org To: common-commits@hadoop.apache.org Message-Id: <79753ffec0244b93bf6c3827405b1d7a@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: hadoop git commit: YARN-3517. RM web ui for dumping scheduler logs should be for admins only (Varun Vasudev via tgraves) (cherry picked from commit 2e215484bd05cd5e3b7a81d3558c6879a05dd2d2) Date: Wed, 29 Apr 2015 21:29:05 +0000 (UTC) Repository: hadoop Updated Branches: refs/heads/branch-2 460127e6f -> 2e13183f6 YARN-3517. RM web ui for dumping scheduler logs should be for admins only (Varun Vasudev via tgraves) (cherry picked from commit 2e215484bd05cd5e3b7a81d3558c6879a05dd2d2) Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/2e13183f Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/2e13183f Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/2e13183f Branch: refs/heads/branch-2 Commit: 2e13183f6010182aef7b1dfec2f9c1f1e9968011 Parents: 460127e Author: tgraves Authored: Wed Apr 29 21:25:42 2015 +0000 Committer: tgraves Committed: Wed Apr 29 21:27:16 2015 +0000 ---------------------------------------------------------------------- hadoop-yarn-project/CHANGES.txt | 3 + .../server/security/ApplicationACLsManager.java | 11 +++ .../webapp/CapacitySchedulerPage.java | 51 +++++++++---- .../resourcemanager/webapp/RMWebServices.java | 13 +++- .../webapp/TestRMWebServices.java | 77 ++++++++++++++++++++ 5 files changed, 139 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/2e13183f/hadoop-yarn-project/CHANGES.txt ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index 98e42c1..8f4907f 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -220,6 +220,9 @@ Release 2.8.0 - UNRELEASED YARN-2740. Fix NodeLabelsManager to properly handle node label modifications when distributed node label configuration enabled. (Naganarasimha G R via wangda) + YARN-3517. RM web ui for dumping scheduler logs should be for admins only + (Varun Vasudev via tgraves) + Release 2.7.1 - UNRELEASED INCOMPATIBLE CHANGES http://git-wip-us.apache.org/repos/asf/hadoop/blob/2e13183f/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java index 4daaa68..97b4163 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java @@ -138,4 +138,15 @@ public class ApplicationACLsManager { } return false; } + + /** + * Check if the given user in an admin. + * + * @param calledUGI + * UserGroupInformation for the user + * @return true if the user is an admin, false otherwise + */ + public final boolean isAdmin(final UserGroupInformation calledUGI) { + return this.adminAclsManager.isAdmin(calledUGI); + } } http://git-wip-us.apache.org/repos/asf/hadoop/blob/2e13183f/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java index 2eeda66..fa22a0d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/CapacitySchedulerPage.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerHealth; @@ -33,6 +34,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.UserInfo import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.CapacitySchedulerInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.CapacitySchedulerLeafQueueInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.CapacitySchedulerQueueInfo; +import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; import org.apache.hadoop.yarn.util.Times; import org.apache.hadoop.yarn.webapp.ResponseInfo; import org.apache.hadoop.yarn.webapp.SubView; @@ -190,28 +192,46 @@ class CapacitySchedulerPage extends RmView { static class QueuesBlock extends HtmlBlock { final CapacityScheduler cs; final CSQInfo csqinfo; + private final ResourceManager rm; @Inject QueuesBlock(ResourceManager rm, CSQInfo info) { cs = (CapacityScheduler) rm.getResourceScheduler(); csqinfo = info; + this.rm = rm; } @Override public void render(Block html) { html._(MetricsOverviewTable.class); - // Dump CapacityScheduler debug logs - html.div() + + UserGroupInformation callerUGI = this.getCallerUGI(); + boolean isAdmin = false; + ApplicationACLsManager aclsManager = rm.getApplicationACLsManager(); + if (aclsManager.areACLsEnabled()) { + if (callerUGI != null && aclsManager.isAdmin(callerUGI)) { + isAdmin = true; + } + } else { + isAdmin = true; + } + + // only show button to dump CapacityScheduler debug logs to admins + if (isAdmin) { + html.div() .button() - .$onclick("confirmAction()").b("Dump scheduler logs")._() - .select().$id("time") - .option().$value("60")._("1 min")._() - .option().$value("300")._("5 min")._() - .option().$value("600")._("10 min")._() + .$style( + "border-style: solid; border-color: #000000; border-width: 1px;" + + " cursor: hand; cursor: pointer; border-radius: 4px") + .$onclick("confirmAction()").b("Dump scheduler logs")._().select() + .$id("time").option().$value("60")._("1 min")._().option() + .$value("300")._("5 min")._().option().$value("600")._("10 min")._() ._()._(); - StringBuilder script = new StringBuilder(); - script.append("function confirmAction() {") - .append(" b = confirm(\"Are you sure you wish to generate scheduler logs?\");") + StringBuilder script = new StringBuilder(); + script + .append("function confirmAction() {") + .append(" b = confirm(\"Are you sure you wish to generate" + + " scheduler logs?\");") .append(" if (b == true) {") .append(" var timePeriod = $(\"#time\").val();") .append(" $.ajax({") @@ -225,13 +245,14 @@ class CapacitySchedulerPage extends RmView { .append(" alert(\"Scheduler log is being generated.\");") .append(" }, 1000);") .append(" }).fail(function(data){") - .append(" alert(\"Scheduler log generation failed. Please check the ResourceManager log for more informtion.\");") - .append(" console.log(data);") - .append(" });") - .append(" }") + .append( + " alert(\"Scheduler log generation failed. Please check the" + + " ResourceManager log for more informtion.\");") + .append(" console.log(data);").append(" });").append(" }") .append("}"); - html.script().$type("text/javascript")._(script.toString())._(); + html.script().$type("text/javascript")._(script.toString())._(); + } UL>> ul = html. div("#cs-wrapper.ui-widget"). http://git-wip-us.apache.org/repos/asf/hadoop/blob/2e13183f/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java index 9aea62d..4ce2b54 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java @@ -142,10 +142,12 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ResourceInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerTypeInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.StatisticsItemInfo; +import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; import org.apache.hadoop.yarn.server.utils.BuilderUtils; import org.apache.hadoop.yarn.util.AdHocLogDumper; import org.apache.hadoop.yarn.util.ConverterUtils; import org.apache.hadoop.yarn.webapp.BadRequestException; +import org.apache.hadoop.yarn.webapp.ForbiddenException; import org.apache.hadoop.yarn.webapp.NotFoundException; import org.apache.hadoop.yarn.webapp.util.WebAppUtils; @@ -263,8 +265,17 @@ public class RMWebServices { @POST @Path("/scheduler/logs") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public String dumpSchedulerLogs(@FormParam("time") String time) throws IOException { + public String dumpSchedulerLogs(@FormParam("time") String time, + @Context HttpServletRequest hsr) throws IOException { init(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + ApplicationACLsManager aclsManager = rm.getApplicationACLsManager(); + if (aclsManager.areACLsEnabled()) { + if (callerUGI == null || !aclsManager.isAdmin(callerUGI)) { + String msg = "Only admins can carry out this operation."; + throw new ForbiddenException(msg); + } + } ResourceScheduler rs = rm.getResourceScheduler(); int period = Integer.parseInt(time); if (period <= 0) { http://git-wip-us.apache.org/repos/asf/hadoop/blob/2e13183f/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java index e4614f8..cd1d771 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java @@ -26,7 +26,9 @@ import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.File; import java.io.StringReader; +import java.security.Principal; import java.util.Arrays; import java.util.Collections; import java.util.Set; @@ -37,6 +39,7 @@ import javax.ws.rs.core.MediaType; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.service.Service.STATE; import org.apache.hadoop.util.VersionInfo; @@ -54,9 +57,13 @@ import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.QueueMetrics; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppsInfo; +import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; import org.apache.hadoop.yarn.util.YarnVersionInfo; +import org.apache.hadoop.yarn.webapp.ForbiddenException; import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; import org.apache.hadoop.yarn.webapp.JerseyTestBase; import org.apache.hadoop.yarn.webapp.WebServicesTestUtils; @@ -643,4 +650,74 @@ public class TestRMWebServices extends JerseyTestBase { null, null, null, null, null, null, null, emptySet, emptySet); assertTrue(appsInfo.getApps().isEmpty()); } + + @Test + public void testDumpingSchedulerLogs() throws Exception { + + ResourceManager mockRM = mock(ResourceManager.class); + Configuration conf = new YarnConfiguration(); + HttpServletRequest mockHsr = mock(HttpServletRequest.class); + ApplicationACLsManager aclsManager = new ApplicationACLsManager(conf); + when(mockRM.getApplicationACLsManager()).thenReturn(aclsManager); + RMWebServices webSvc = + new RMWebServices(mockRM, conf, mock(HttpServletResponse.class)); + + // nothing should happen + webSvc.dumpSchedulerLogs("1", mockHsr); + Thread.sleep(1000); + checkSchedulerLogFileAndCleanup(); + + conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); + conf.setStrings(YarnConfiguration.YARN_ADMIN_ACL, "admin"); + aclsManager = new ApplicationACLsManager(conf); + when(mockRM.getApplicationACLsManager()).thenReturn(aclsManager); + webSvc = new RMWebServices(mockRM, conf, mock(HttpServletResponse.class)); + boolean exceptionThrown = false; + try { + webSvc.dumpSchedulerLogs("1", mockHsr); + fail("Dumping logs should fail"); + } catch (ForbiddenException ae) { + exceptionThrown = true; + } + assertTrue("ForbiddenException expected", exceptionThrown); + exceptionThrown = false; + when(mockHsr.getUserPrincipal()).thenReturn(new Principal() { + @Override + public String getName() { + return "testuser"; + } + }); + try { + webSvc.dumpSchedulerLogs("1", mockHsr); + fail("Dumping logs should fail"); + } catch (ForbiddenException ae) { + exceptionThrown = true; + } + assertTrue("ForbiddenException expected", exceptionThrown); + + when(mockHsr.getUserPrincipal()).thenReturn(new Principal() { + @Override + public String getName() { + return "admin"; + } + }); + webSvc.dumpSchedulerLogs("1", mockHsr); + Thread.sleep(1000); + checkSchedulerLogFileAndCleanup(); + } + + private void checkSchedulerLogFileAndCleanup() { + String targetFile; + ResourceScheduler scheduler = rm.getResourceScheduler(); + if (scheduler instanceof FairScheduler) { + targetFile = "yarn-fair-scheduler-debug.log"; + } else if (scheduler instanceof CapacityScheduler) { + targetFile = "yarn-capacity-scheduler-debug.log"; + } else { + targetFile = "yarn-scheduler-debug.log"; + } + File logFile = new File(System.getProperty("yarn.log.dir"), targetFile); + assertTrue("scheduler log file doesn't exist", logFile.exists()); + FileUtils.deleteQuietly(logFile); + } }