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
This commit is contained in:
Vinod Kumar Vavilapalli 2014-05-23 22:41:24 +00:00
parent 98c6a60864
commit 1f47d35523
5 changed files with 49 additions and 22 deletions

View File

@ -87,6 +87,9 @@ Release 2.5.0 - UNRELEASED
YARN-2012. Fair Scheduler: allow default queue placement rule to take an YARN-2012. Fair Scheduler: allow default queue placement rule to take an
arbitrary queue (Ashwin Shankar via Sandy Ryza) arbitrary queue (Ashwin Shankar via Sandy Ryza)
YARN-2059. Added admin ACLs support to Timeline Server. (Zhijie Shen via
vinodkv)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -27,8 +27,8 @@ import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.api.records.timeline.TimelineEntity; 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.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.EntityIdentifier;
import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.TimelineStore.SystemFilter; 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 static final Log LOG = LogFactory.getLog(TimelineACLsManager.class);
private boolean aclsEnabled; private AdminACLsManager adminAclsManager;
public TimelineACLsManager(Configuration conf) { public TimelineACLsManager(Configuration conf) {
aclsEnabled = conf.getBoolean(YarnConfiguration.YARN_ACL_ENABLE, this.adminAclsManager = new AdminACLsManager(conf);
YarnConfiguration.DEFAULT_YARN_ACL_ENABLE);
} }
public boolean checkAccess(UserGroupInformation callerUGI, public boolean checkAccess(UserGroupInformation callerUGI,
@ -57,7 +56,7 @@ public class TimelineACLsManager {
+ new EntityIdentifier(entity.getEntityId(), entity.getEntityType())); + new EntityIdentifier(entity.getEntityId(), entity.getEntityType()));
} }
if (!aclsEnabled) { if (!adminAclsManager.areACLsEnabled()) {
return true; return true;
} }
@ -70,10 +69,12 @@ public class TimelineACLsManager {
+ " is corrupted."); + " is corrupted.");
} }
String owner = values.iterator().next().toString(); String owner = values.iterator().next().toString();
// TODO: Currently we just check the user is the timeline entity owner. In // TODO: Currently we just check the user is the admin or the timeline
// the future, we need to check whether the user is admin or is in the // entity owner. In the future, we need to check whether the user is in the
// allowed user/group list // allowed user/group list
if (callerUGI != null && callerUGI.getShortUserName().equals(owner)) { if (callerUGI != null
&& (adminAclsManager.isAdmin(callerUGI) ||
callerUGI.getShortUserName().equals(owner))) {
return true; return true;
} }
return false; return false;
@ -81,8 +82,11 @@ public class TimelineACLsManager {
@Private @Private
@VisibleForTesting @VisibleForTesting
public void setACLsEnabled(boolean aclsEnabled) { public AdminACLsManager
this.aclsEnabled = aclsEnabled; setAdminACLsManager(AdminACLsManager adminAclsManager) {
AdminACLsManager oldAdminACLsManager = this.adminAclsManager;
this.adminAclsManager = adminAclsManager;
return oldAdminACLsManager;
} }
} }

View File

@ -346,8 +346,9 @@ public class TimelineWebServices {
new EntityIdentifier(entity.getEntityId(), entity.getEntityType()); new EntityIdentifier(entity.getEntityId(), entity.getEntityType());
// check if there is existing entity // check if there is existing entity
TimelineEntity existingEntity = null;
try { try {
TimelineEntity existingEntity = existingEntity =
store.getEntity(entityID.getId(), entityID.getType(), store.getEntity(entityID.getId(), entityID.getType(),
EnumSet.of(Field.PRIMARY_FILTERS)); EnumSet.of(Field.PRIMARY_FILTERS));
if (existingEntity != null if (existingEntity != null
@ -369,10 +370,14 @@ public class TimelineWebServices {
continue; 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 { try {
injectOwnerInfo(entity, if (existingEntity == null) {
callerUGI == null ? "" : callerUGI.getShortUserName()); injectOwnerInfo(entity,
callerUGI == null ? "" : callerUGI.getShortUserName());
}
} catch (YarnException e) { } catch (YarnException e) {
// Skip the entity which messes up the primary filter and record the // Skip the entity which messes up the primary filter and record the
// error // error

View File

@ -49,6 +49,7 @@ public class TestTimelineACLsManager {
public void testYarnACLsEnabled() throws Exception { public void testYarnACLsEnabled() throws Exception {
Configuration conf = new YarnConfiguration(); Configuration conf = new YarnConfiguration();
conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true);
conf.set(YarnConfiguration.YARN_ADMIN_ACL, "admin");
TimelineACLsManager timelineACLsManager = TimelineACLsManager timelineACLsManager =
new TimelineACLsManager(conf); new TimelineACLsManager(conf);
TimelineEntity entity = new TimelineEntity(); TimelineEntity entity = new TimelineEntity();
@ -63,12 +64,17 @@ public class TestTimelineACLsManager {
"Other shouldn't be allowed to access", "Other shouldn't be allowed to access",
timelineACLsManager.checkAccess( timelineACLsManager.checkAccess(
UserGroupInformation.createRemoteUser("other"), entity)); UserGroupInformation.createRemoteUser("other"), entity));
Assert.assertTrue(
"Admin should be allowed to access",
timelineACLsManager.checkAccess(
UserGroupInformation.createRemoteUser("admin"), entity));
} }
@Test @Test
public void testCorruptedOwnerInfo() throws Exception { public void testCorruptedOwnerInfo() throws Exception {
Configuration conf = new YarnConfiguration(); Configuration conf = new YarnConfiguration();
conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true);
conf.set(YarnConfiguration.YARN_ADMIN_ACL, "owner");
TimelineACLsManager timelineACLsManager = TimelineACLsManager timelineACLsManager =
new TimelineACLsManager(conf); new TimelineACLsManager(conf);
TimelineEntity entity = new TimelineEntity(); TimelineEntity entity = new TimelineEntity();

View File

@ -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.TimelineEvents;
import org.apache.hadoop.yarn.api.records.timeline.TimelinePutResponse; import org.apache.hadoop.yarn.api.records.timeline.TimelinePutResponse;
import org.apache.hadoop.yarn.conf.YarnConfiguration; 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.TestMemoryTimelineStore;
import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.TimelineStore; import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.TimelineStore;
import org.apache.hadoop.yarn.server.applicationhistoryservice.timeline.security.TimelineACLsManager; 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 TimelineStore store;
private static TimelineACLsManager timelineACLsManager; private static TimelineACLsManager timelineACLsManager;
private static AdminACLsManager adminACLsManager;
private static String remoteUser; private static String remoteUser;
private long beforeTime; private long beforeTime;
@ -83,6 +85,9 @@ public class TestTimelineWebServices extends JerseyTest {
Configuration conf = new YarnConfiguration(); Configuration conf = new YarnConfiguration();
conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, false); conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, false);
timelineACLsManager = new TimelineACLsManager(conf); 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); bind(TimelineACLsManager.class).toInstance(timelineACLsManager);
serve("/*").with(GuiceContainer.class); serve("/*").with(GuiceContainer.class);
filter("/*").through(TestFilter.class); filter("/*").through(TestFilter.class);
@ -387,7 +392,8 @@ public class TestTimelineWebServices extends JerseyTest {
@Test @Test
public void testPostEntitiesWithYarnACLsEnabled() throws Exception { public void testPostEntitiesWithYarnACLsEnabled() throws Exception {
timelineACLsManager.setACLsEnabled(true); AdminACLsManager oldAdminACLsManager =
timelineACLsManager.setAdminACLsManager(adminACLsManager);
remoteUser = "tester"; remoteUser = "tester";
try { try {
TimelineEntities entities = new TimelineEntities(); TimelineEntities entities = new TimelineEntities();
@ -419,14 +425,15 @@ public class TestTimelineWebServices extends JerseyTest {
Assert.assertEquals(TimelinePutResponse.TimelinePutError.ACCESS_DENIED, Assert.assertEquals(TimelinePutResponse.TimelinePutError.ACCESS_DENIED,
putResponse.getErrors().get(0).getErrorCode()); putResponse.getErrors().get(0).getErrorCode());
} finally { } finally {
timelineACLsManager.setACLsEnabled(false); timelineACLsManager.setAdminACLsManager(oldAdminACLsManager);
remoteUser = null; remoteUser = null;
} }
} }
@Test @Test
public void testGetEntityWithYarnACLsEnabled() throws Exception { public void testGetEntityWithYarnACLsEnabled() throws Exception {
timelineACLsManager.setACLsEnabled(true); AdminACLsManager oldAdminACLsManager =
timelineACLsManager.setAdminACLsManager(adminACLsManager);
remoteUser = "tester"; remoteUser = "tester";
try { try {
TimelineEntities entities = new TimelineEntities(); TimelineEntities entities = new TimelineEntities();
@ -481,14 +488,15 @@ public class TestTimelineWebServices extends JerseyTest {
assertEquals(ClientResponse.Status.NOT_FOUND, assertEquals(ClientResponse.Status.NOT_FOUND,
response.getClientResponseStatus()); response.getClientResponseStatus());
} finally { } finally {
timelineACLsManager.setACLsEnabled(false); timelineACLsManager.setAdminACLsManager(oldAdminACLsManager);
remoteUser = null; remoteUser = null;
} }
} }
@Test @Test
public void testGetEntitiesWithYarnACLsEnabled() { public void testGetEntitiesWithYarnACLsEnabled() {
timelineACLsManager.setACLsEnabled(true); AdminACLsManager oldAdminACLsManager =
timelineACLsManager.setAdminACLsManager(adminACLsManager);
remoteUser = "tester"; remoteUser = "tester";
try { try {
TimelineEntities entities = new TimelineEntities(); TimelineEntities entities = new TimelineEntities();
@ -526,14 +534,15 @@ public class TestTimelineWebServices extends JerseyTest {
assertEquals("test type 4", entities.getEntities().get(0).getEntityType()); assertEquals("test type 4", entities.getEntities().get(0).getEntityType());
assertEquals("test id 5", entities.getEntities().get(0).getEntityId()); assertEquals("test id 5", entities.getEntities().get(0).getEntityId());
} finally { } finally {
timelineACLsManager.setACLsEnabled(false); timelineACLsManager.setAdminACLsManager(oldAdminACLsManager);
remoteUser = null; remoteUser = null;
} }
} }
@Test @Test
public void testGetEventsWithYarnACLsEnabled() { public void testGetEventsWithYarnACLsEnabled() {
timelineACLsManager.setACLsEnabled(true); AdminACLsManager oldAdminACLsManager =
timelineACLsManager.setAdminACLsManager(adminACLsManager);
remoteUser = "tester"; remoteUser = "tester";
try { try {
TimelineEntities entities = new TimelineEntities(); TimelineEntities entities = new TimelineEntities();
@ -579,7 +588,7 @@ public class TestTimelineWebServices extends JerseyTest {
assertEquals(1, events.getAllEvents().size()); assertEquals(1, events.getAllEvents().size());
assertEquals("test id 6", events.getAllEvents().get(0).getEntityId()); assertEquals("test id 6", events.getAllEvents().get(0).getEntityId());
} finally { } finally {
timelineACLsManager.setACLsEnabled(false); timelineACLsManager.setAdminACLsManager(oldAdminACLsManager);
remoteUser = null; remoteUser = null;
} }
} }