diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java
index bab479120b0..07f03211915 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java
@@ -29,7 +29,7 @@ import org.apache.hadoop.security.AccessControlException;
*
* This class does not provide the stack trace for security purposes.
*/
-@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
+@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce", "YARN"})
@InterfaceStability.Evolving
public class AuthorizationException extends AccessControlException {
private static final long serialVersionUID = 1L;
diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt
index 323bacfa6f2..f1ff99538de 100644
--- a/hadoop-yarn-project/CHANGES.txt
+++ b/hadoop-yarn-project/CHANGES.txt
@@ -736,6 +736,9 @@ Release 2.6.0 - UNRELEASED
YARN-2726. CapacityScheduler should explicitly log when an accessible
label has no capacity. (Wangda Tan via xgong)
+ YARN-2591. Fixed AHSWebServices to return FORBIDDEN(403) if the request user
+ doesn't have access to the history data. (Zhijie Shen via jianhe)
+
Release 2.5.1 - 2014-09-05
INCOMPATIBLE CHANGES
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryManagerOnTimelineStore.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryManagerOnTimelineStore.java
index e1a4d1b1e9f..cd429d02301 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryManagerOnTimelineStore.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryManagerOnTimelineStore.java
@@ -26,6 +26,7 @@ import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
@@ -504,8 +505,8 @@ public class ApplicationHistoryManagerOnTimelineStore extends AbstractService
app.appReport.setOriginalTrackingUrl(appAttempt.getOriginalTrackingUrl());
}
}
- } catch (YarnException e) {
- // YarnExcetpion is thrown because the user doesn't have access
+ } catch (AuthorizationException e) {
+ // AuthorizationException is thrown because the user doesn't have access
app.appReport.setDiagnostics(null);
app.appReport.setCurrentApplicationAttemptId(null);
}
@@ -554,7 +555,7 @@ public class ApplicationHistoryManagerOnTimelineStore extends AbstractService
if (!aclsManager.checkAccess(UserGroupInformation.getCurrentUser(),
ApplicationAccessType.VIEW_APP, app.appReport.getUser(),
app.appReport.getApplicationId())) {
- throw new YarnException("User "
+ throw new AuthorizationException("User "
+ UserGroupInformation.getCurrentUser().getShortUserName()
+ " does not have privilage to see this application "
+ app.appReport.getApplicationId());
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryManagerOnTimelineStore.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryManagerOnTimelineStore.java
index 311626eef50..856b88d28e6 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryManagerOnTimelineStore.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryManagerOnTimelineStore.java
@@ -18,7 +18,6 @@
package org.apache.hadoop.yarn.server.applicationhistoryservice;
-import java.lang.reflect.UndeclaredThrowableException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Collection;
@@ -28,6 +27,7 @@ import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport;
import org.apache.hadoop.yarn.api.records.ApplicationId;
@@ -74,8 +74,13 @@ public class TestApplicationHistoryManagerOnTimelineStore {
@BeforeClass
public static void prepareStore() throws Exception {
- store = new MemoryTimelineStore();
- prepareTimelineStore(store);
+ store = createStore(SCALE);
+ }
+
+ public static TimelineStore createStore(int scale) throws Exception {
+ TimelineStore store = new MemoryTimelineStore();
+ prepareTimelineStore(store, scale);
+ return store;
}
@Before
@@ -117,9 +122,9 @@ public class TestApplicationHistoryManagerOnTimelineStore {
}
}
- private static void prepareTimelineStore(TimelineStore store)
+ private static void prepareTimelineStore(TimelineStore store, int scale)
throws Exception {
- for (int i = 1; i <= SCALE; ++i) {
+ for (int i = 1; i <= scale; ++i) {
TimelineEntities entities = new TimelineEntities();
ApplicationId appId = ApplicationId.newInstance(0, i);
if (i == 2) {
@@ -128,13 +133,13 @@ public class TestApplicationHistoryManagerOnTimelineStore {
entities.addEntity(createApplicationTimelineEntity(appId, false));
}
store.put(entities);
- for (int j = 1; j <= SCALE; ++j) {
+ for (int j = 1; j <= scale; ++j) {
entities = new TimelineEntities();
ApplicationAttemptId appAttemptId =
ApplicationAttemptId.newInstance(appId, j);
entities.addEntity(createAppAttemptTimelineEntity(appAttemptId));
store.put(entities);
- for (int k = 1; k <= SCALE; ++k) {
+ for (int k = 1; k <= scale; ++k) {
entities = new TimelineEntities();
ContainerId containerId = ContainerId.newInstance(appAttemptId, k);
entities.addEntity(createContainerEntity(containerId));
@@ -223,13 +228,10 @@ public class TestApplicationHistoryManagerOnTimelineStore {
// The exception is expected
Assert.fail();
}
- } catch (UndeclaredThrowableException e) {
+ } catch (AuthorizationException e) {
if (callerUGI != null && callerUGI.getShortUserName().equals("user3")) {
- if (e.getCause().getMessage().contains(
- "does not have privilage to see this application")) {
- // The exception is expected
- return;
- }
+ // The exception is expected
+ return;
}
throw e;
}
@@ -269,13 +271,10 @@ public class TestApplicationHistoryManagerOnTimelineStore {
// The exception is expected
Assert.fail();
}
- } catch (UndeclaredThrowableException e) {
+ } catch (AuthorizationException e) {
if (callerUGI != null && callerUGI.getShortUserName().equals("user3")) {
- if (e.getCause().getMessage().contains(
- "does not have privilage to see this application")) {
- // The exception is expected
- return;
- }
+ // The exception is expected
+ return;
}
throw e;
}
@@ -324,13 +323,10 @@ public class TestApplicationHistoryManagerOnTimelineStore {
// The exception is expected
Assert.fail();
}
- } catch (UndeclaredThrowableException e) {
+ } catch (AuthorizationException e) {
if (callerUGI != null && callerUGI.getShortUserName().equals("user3")) {
- if (e.getCause().getMessage().contains(
- "does not have privilage to see this application")) {
- // The exception is expected
- return;
- }
+ // The exception is expected
+ return;
}
throw e;
}
@@ -359,13 +355,10 @@ public class TestApplicationHistoryManagerOnTimelineStore {
// The exception is expected
Assert.fail();
}
- } catch (UndeclaredThrowableException e) {
+ } catch (AuthorizationException e) {
if (callerUGI != null && callerUGI.getShortUserName().equals("user3")) {
- if (e.getCause().getMessage().contains(
- "does not have privilage to see this application")) {
- // The exception is expected
- return;
- }
+ // The exception is expected
+ return;
}
throw e;
}
@@ -394,13 +387,10 @@ public class TestApplicationHistoryManagerOnTimelineStore {
// The exception is expected
Assert.fail();
}
- } catch (UndeclaredThrowableException e) {
+ } catch (AuthorizationException e) {
if (callerUGI != null && callerUGI.getShortUserName().equals("user3")) {
- if (e.getCause().getMessage().contains(
- "does not have privilage to see this application")) {
- // The exception is expected
- return;
- }
+ // The exception is expected
+ return;
}
throw e;
}
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/TestAHSWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java
index b06c6463adf..da39ce3928b 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java
@@ -21,36 +21,51 @@ package org.apache.hadoop.yarn.server.applicationhistoryservice.webapp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import javax.ws.rs.core.MediaType;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Properties;
-import org.junit.Assert;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.http.lib.StaticUserWebFilter.StaticUserFilter;
+import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerState;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.NodeId;
-import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.YarnApplicationAttemptState;
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.api.ApplicationContext;
-import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryManager;
-import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryStore;
-import org.apache.hadoop.yarn.server.applicationhistoryservice.MemoryApplicationHistoryStore;
+import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryManagerOnTimelineStore;
+import org.apache.hadoop.yarn.server.applicationhistoryservice.TestApplicationHistoryManagerOnTimelineStore;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.server.timeline.TimelineDataManager;
+import org.apache.hadoop.yarn.server.timeline.TimelineStore;
+import org.apache.hadoop.yarn.server.timeline.security.TimelineACLsManager;
import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
import org.apache.hadoop.yarn.webapp.util.WebAppUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
-import org.junit.Before;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.google.inject.Singleton;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
import com.sun.jersey.api.client.ClientResponse;
@@ -61,9 +76,40 @@ import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;
+@RunWith(Parameterized.class)
public class TestAHSWebServices extends JerseyTest {
- private static ApplicationHistoryManager ahManager;
+ private static ApplicationHistoryManagerOnTimelineStore historyManager;
+ private static final String[] USERS = new String[] { "foo" , "bar" };
+
+ @BeforeClass
+ public static void setupClass() throws Exception {
+ Configuration conf = new YarnConfiguration();
+ TimelineStore store =
+ TestApplicationHistoryManagerOnTimelineStore.createStore(5);
+ TimelineACLsManager aclsManager = new TimelineACLsManager(conf);
+ TimelineDataManager dataManager =
+ new TimelineDataManager(store, aclsManager);
+ conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true);
+ conf.set(YarnConfiguration.YARN_ADMIN_ACL, "foo");
+ ApplicationACLsManager appAclsManager = new ApplicationACLsManager(conf);
+ historyManager =
+ new ApplicationHistoryManagerOnTimelineStore(dataManager, appAclsManager);
+ historyManager.init(conf);
+ historyManager.start();
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ if (historyManager != null) {
+ historyManager.stop();
+ }
+ }
+
+ @Parameterized.Parameters
+ public static Collection