From 1f47d355234777b707191b9c8e813c0000ecf212 Mon Sep 17 00:00:00 2001 From: Vinod Kumar Vavilapalli Date: Fri, 23 May 2014 22:41:24 +0000 Subject: [PATCH] YARN-2059. Added admin ACLs support to Timeline Server. Contributed by Zhijie Shen. svn merge --ignore-ancestry -c 1597207 ../../trunk/ git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1597208 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-yarn-project/CHANGES.txt | 3 +++ .../security/TimelineACLsManager.java | 24 ++++++++++-------- .../webapp/TimelineWebServices.java | 13 +++++++--- .../security/TestTimelineACLsManager.java | 6 +++++ .../webapp/TestTimelineWebServices.java | 25 +++++++++++++------ 5 files changed, 49 insertions(+), 22 deletions(-) diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index e34b930003f..c74e777d400 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -87,6 +87,9 @@ Release 2.5.0 - UNRELEASED YARN-2012. Fair Scheduler: allow default queue placement rule to take an arbitrary queue (Ashwin Shankar via Sandy Ryza) + YARN-2059. Added admin ACLs support to Timeline Server. (Zhijie Shen via + vinodkv) + OPTIMIZATIONS BUG FIXES diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TimelineACLsManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TimelineACLsManager.java index 5bc8705222f..8009b39c94f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TimelineACLsManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TimelineACLsManager.java @@ -27,8 +27,8 @@ import org.apache.hadoop.classification.InterfaceAudience.Private; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.api.records.timeline.TimelineEntity; -import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.security.AdminACLsManager; import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.EntityIdentifier; import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.TimelineStore.SystemFilter; @@ -42,11 +42,10 @@ public class TimelineACLsManager { private static final Log LOG = LogFactory.getLog(TimelineACLsManager.class); - private boolean aclsEnabled; + private AdminACLsManager adminAclsManager; public TimelineACLsManager(Configuration conf) { - aclsEnabled = conf.getBoolean(YarnConfiguration.YARN_ACL_ENABLE, - YarnConfiguration.DEFAULT_YARN_ACL_ENABLE); + this.adminAclsManager = new AdminACLsManager(conf); } public boolean checkAccess(UserGroupInformation callerUGI, @@ -57,7 +56,7 @@ public class TimelineACLsManager { + new EntityIdentifier(entity.getEntityId(), entity.getEntityType())); } - if (!aclsEnabled) { + if (!adminAclsManager.areACLsEnabled()) { return true; } @@ -70,10 +69,12 @@ public class TimelineACLsManager { + " is corrupted."); } String owner = values.iterator().next().toString(); - // TODO: Currently we just check the user is the timeline entity owner. In - // the future, we need to check whether the user is admin or is in the + // TODO: Currently we just check the user is the admin or the timeline + // entity owner. In the future, we need to check whether the user is in the // allowed user/group list - if (callerUGI != null && callerUGI.getShortUserName().equals(owner)) { + if (callerUGI != null + && (adminAclsManager.isAdmin(callerUGI) || + callerUGI.getShortUserName().equals(owner))) { return true; } return false; @@ -81,8 +82,11 @@ public class TimelineACLsManager { @Private @VisibleForTesting - public void setACLsEnabled(boolean aclsEnabled) { - this.aclsEnabled = aclsEnabled; + public AdminACLsManager + setAdminACLsManager(AdminACLsManager adminAclsManager) { + AdminACLsManager oldAdminACLsManager = this.adminAclsManager; + this.adminAclsManager = adminAclsManager; + return oldAdminACLsManager; } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TimelineWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TimelineWebServices.java index 6041779b13a..5d749fa0906 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TimelineWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TimelineWebServices.java @@ -346,8 +346,9 @@ public class TimelineWebServices { new EntityIdentifier(entity.getEntityId(), entity.getEntityType()); // check if there is existing entity + TimelineEntity existingEntity = null; try { - TimelineEntity existingEntity = + existingEntity = store.getEntity(entityID.getId(), entityID.getType(), EnumSet.of(Field.PRIMARY_FILTERS)); if (existingEntity != null @@ -369,10 +370,14 @@ public class TimelineWebServices { continue; } - // inject owner information for the access check + // inject owner information for the access check if this is the first + // time to post the entity, in case it's the admin who is updating + // the timeline data. try { - injectOwnerInfo(entity, - callerUGI == null ? "" : callerUGI.getShortUserName()); + if (existingEntity == null) { + injectOwnerInfo(entity, + callerUGI == null ? "" : callerUGI.getShortUserName()); + } } catch (YarnException e) { // Skip the entity which messes up the primary filter and record the // error diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TestTimelineACLsManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TestTimelineACLsManager.java index 2c536681aed..39102b43bad 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TestTimelineACLsManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/timeline/security/TestTimelineACLsManager.java @@ -49,6 +49,7 @@ public class TestTimelineACLsManager { public void testYarnACLsEnabled() throws Exception { Configuration conf = new YarnConfiguration(); conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); + conf.set(YarnConfiguration.YARN_ADMIN_ACL, "admin"); TimelineACLsManager timelineACLsManager = new TimelineACLsManager(conf); TimelineEntity entity = new TimelineEntity(); @@ -63,12 +64,17 @@ public class TestTimelineACLsManager { "Other shouldn't be allowed to access", timelineACLsManager.checkAccess( UserGroupInformation.createRemoteUser("other"), entity)); + Assert.assertTrue( + "Admin should be allowed to access", + timelineACLsManager.checkAccess( + UserGroupInformation.createRemoteUser("admin"), entity)); } @Test public void testCorruptedOwnerInfo() throws Exception { Configuration conf = new YarnConfiguration(); conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); + conf.set(YarnConfiguration.YARN_ADMIN_ACL, "owner"); TimelineACLsManager timelineACLsManager = new TimelineACLsManager(conf); TimelineEntity entity = new TimelineEntity(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestTimelineWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestTimelineWebServices.java index 9b0ae3761d2..7e3e4099403 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestTimelineWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestTimelineWebServices.java @@ -40,6 +40,7 @@ import org.apache.hadoop.yarn.api.records.timeline.TimelineEvent; import org.apache.hadoop.yarn.api.records.timeline.TimelineEvents; import org.apache.hadoop.yarn.api.records.timeline.TimelinePutResponse; import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.security.AdminACLsManager; import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.TestMemoryTimelineStore; import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.TimelineStore; import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.security.TimelineACLsManager; @@ -64,6 +65,7 @@ public class TestTimelineWebServices extends JerseyTest { private static TimelineStore store; private static TimelineACLsManager timelineACLsManager; + private static AdminACLsManager adminACLsManager; private static String remoteUser; private long beforeTime; @@ -83,6 +85,9 @@ public class TestTimelineWebServices extends JerseyTest { Configuration conf = new YarnConfiguration(); conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, false); timelineACLsManager = new TimelineACLsManager(conf); + conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); + conf.set(YarnConfiguration.YARN_ADMIN_ACL, "admin"); + adminACLsManager = new AdminACLsManager(conf); bind(TimelineACLsManager.class).toInstance(timelineACLsManager); serve("/*").with(GuiceContainer.class); filter("/*").through(TestFilter.class); @@ -387,7 +392,8 @@ public class TestTimelineWebServices extends JerseyTest { @Test public void testPostEntitiesWithYarnACLsEnabled() throws Exception { - timelineACLsManager.setACLsEnabled(true); + AdminACLsManager oldAdminACLsManager = + timelineACLsManager.setAdminACLsManager(adminACLsManager); remoteUser = "tester"; try { TimelineEntities entities = new TimelineEntities(); @@ -419,14 +425,15 @@ public class TestTimelineWebServices extends JerseyTest { Assert.assertEquals(TimelinePutResponse.TimelinePutError.ACCESS_DENIED, putResponse.getErrors().get(0).getErrorCode()); } finally { - timelineACLsManager.setACLsEnabled(false); + timelineACLsManager.setAdminACLsManager(oldAdminACLsManager); remoteUser = null; } } @Test public void testGetEntityWithYarnACLsEnabled() throws Exception { - timelineACLsManager.setACLsEnabled(true); + AdminACLsManager oldAdminACLsManager = + timelineACLsManager.setAdminACLsManager(adminACLsManager); remoteUser = "tester"; try { TimelineEntities entities = new TimelineEntities(); @@ -481,14 +488,15 @@ public class TestTimelineWebServices extends JerseyTest { assertEquals(ClientResponse.Status.NOT_FOUND, response.getClientResponseStatus()); } finally { - timelineACLsManager.setACLsEnabled(false); + timelineACLsManager.setAdminACLsManager(oldAdminACLsManager); remoteUser = null; } } @Test public void testGetEntitiesWithYarnACLsEnabled() { - timelineACLsManager.setACLsEnabled(true); + AdminACLsManager oldAdminACLsManager = + timelineACLsManager.setAdminACLsManager(adminACLsManager); remoteUser = "tester"; try { TimelineEntities entities = new TimelineEntities(); @@ -526,14 +534,15 @@ public class TestTimelineWebServices extends JerseyTest { assertEquals("test type 4", entities.getEntities().get(0).getEntityType()); assertEquals("test id 5", entities.getEntities().get(0).getEntityId()); } finally { - timelineACLsManager.setACLsEnabled(false); + timelineACLsManager.setAdminACLsManager(oldAdminACLsManager); remoteUser = null; } } @Test public void testGetEventsWithYarnACLsEnabled() { - timelineACLsManager.setACLsEnabled(true); + AdminACLsManager oldAdminACLsManager = + timelineACLsManager.setAdminACLsManager(adminACLsManager); remoteUser = "tester"; try { TimelineEntities entities = new TimelineEntities(); @@ -579,7 +588,7 @@ public class TestTimelineWebServices extends JerseyTest { assertEquals(1, events.getAllEvents().size()); assertEquals("test id 6", events.getAllEvents().get(0).getEntityId()); } finally { - timelineACLsManager.setACLsEnabled(false); + timelineACLsManager.setAdminACLsManager(oldAdminACLsManager); remoteUser = null; } }