diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java 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 b348443..1595662 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java +++ 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,14 +21,23 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + import javax.ws.rs.core.MediaType; import org.junit.Assert; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; +import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport; import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ApplicationReport; import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.api.records.ContainerReport; import org.apache.hadoop.yarn.api.records.ContainerState; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.NodeId; @@ -36,6 +45,7 @@ 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.exceptions.YarnException; import org.apache.hadoop.yarn.server.api.ApplicationContext; import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryManager; import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryStore; @@ -48,6 +58,9 @@ import org.codehaus.jettison.json.JSONObject; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import com.google.inject.Guice; import com.google.inject.Injector; @@ -61,9 +74,17 @@ 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 int round; + + @Parameters + public static Collection callers() { + return Arrays.asList( + new Object[][] { { 0 }, { 1 } }); + } private Injector injector = Guice.createInjector(new ServletModule() { @@ -73,7 +94,7 @@ protected void configureServlets() { bind(AHSWebServices.class); bind(GenericExceptionHandler.class); try { - ahManager = mockApplicationHistoryManager(); + ahManager = mockApplicationHistoryManager(round); } catch (Exception e) { Assert.fail(); } @@ -90,17 +111,79 @@ protected Injector getInjector() { } } - private ApplicationHistoryManager mockApplicationHistoryManager() + private ApplicationHistoryManager mockApplicationHistoryManager(int round) throws Exception { - ApplicationHistoryStore store = new MemoryApplicationHistoryStore(); - TestAHSWebApp testAHSWebApp = new TestAHSWebApp(); - testAHSWebApp.setApplicationHistoryStore(store); - ApplicationHistoryManager ahManager = - testAHSWebApp.mockApplicationHistoryManager(5, 5, 5); - return ahManager; + if (round == 0) { + ApplicationHistoryStore store = new MemoryApplicationHistoryStore(); + TestAHSWebApp testAHSWebApp = new TestAHSWebApp(); + testAHSWebApp.setApplicationHistoryStore(store); + ApplicationHistoryManager ahManager = + testAHSWebApp.mockApplicationHistoryManager(5, 5, 5); + return ahManager; + } else { + return new ApplicationHistoryManager() { + + @Override + public ApplicationReport getApplication(ApplicationId appId) + throws YarnException, IOException { + return null; + } + + @Override + public Map getAllApplications() + throws YarnException, IOException { + return Collections.emptyMap(); + } + + @Override + public Map + getApplicationAttempts(ApplicationId appId) throws YarnException, + IOException { + throwException(); + return Collections.emptyMap(); + } + + @Override + public ApplicationAttemptReport getApplicationAttempt( + ApplicationAttemptId appAttemptId) throws YarnException, + IOException { + throwException(); + return null; + } + + @Override + public ContainerReport getContainer(ContainerId containerId) + throws YarnException, IOException { + throwException(); + return null; + } + + @Override + public ContainerReport + getAMContainer(ApplicationAttemptId appAttemptId) + throws YarnException, IOException { + throwException(); + return null; + } + + @Override + public Map getContainers( + ApplicationAttemptId appAttemptId) throws YarnException, + IOException { + throwException(); + return Collections.emptyMap(); + } + + private void throwException() throws YarnException { + throw new YarnException( + "User tester does not have privilage to see this application " + + ApplicationId.newInstance(0, 1)); + } + }; + } } - public TestAHSWebServices() { + public TestAHSWebServices(int round) { super(new WebAppDescriptor.Builder( "org.apache.hadoop.yarn.server.applicationhistoryservice.webapp") .contextListenerClass(GuiceServletConfig.class) @@ -116,6 +199,9 @@ public void setUp() throws Exception { @Test public void testInvalidUri() throws JSONException, Exception { + if (round == 1) { + return; + } WebResource r = resource(); String responseStr = ""; try { @@ -134,6 +220,9 @@ public void testInvalidUri() throws JSONException, Exception { @Test public void testInvalidUri2() throws JSONException, Exception { + if (round == 1) { + return; + } WebResource r = resource(); String responseStr = ""; try { @@ -149,6 +238,9 @@ public void testInvalidUri2() throws JSONException, Exception { @Test public void testInvalidAccept() throws JSONException, Exception { + if (round == 1) { + return; + } WebResource r = resource(); String responseStr = ""; try { @@ -167,6 +259,9 @@ public void testInvalidAccept() throws JSONException, Exception { @Test public void testAppsQuery() throws Exception { + if (round == 1) { + return; + } WebResource r = resource(); ClientResponse response = r.path("ws").path("v1").path("applicationhistory").path("apps") @@ -183,6 +278,9 @@ public void testAppsQuery() throws Exception { @Test public void testSingleApp() throws Exception { + if (round == 1) { + return; + } ApplicationId appId = ApplicationId.newInstance(0, 1); WebResource r = resource(); ClientResponse response = @@ -212,6 +310,11 @@ public void testMultipleAttempts() throws Exception { r.path("ws").path("v1").path("applicationhistory").path("apps") .path(appId.toString()).path("appattempts") .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + if (round == 1) { + assertEquals(ClientResponse.Status.FORBIDDEN, + response.getClientResponseStatus()); + return; + } assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -232,6 +335,11 @@ public void testSingleAttempt() throws Exception { .path(appId.toString()).path("appattempts") .path(appAttemptId.toString()).accept(MediaType.APPLICATION_JSON) .get(ClientResponse.class); + if (round == 1) { + assertEquals(ClientResponse.Status.FORBIDDEN, + response.getClientResponseStatus()); + return; + } assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -256,6 +364,11 @@ public void testMultipleContainers() throws Exception { .path(appId.toString()).path("appattempts") .path(appAttemptId.toString()).path("containers") .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + if (round == 1) { + assertEquals(ClientResponse.Status.FORBIDDEN, + response.getClientResponseStatus()); + return; + } assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -278,6 +391,11 @@ public void testSingleContainer() throws Exception { .path(appAttemptId.toString()).path("containers") .path(containerId.toString()).accept(MediaType.APPLICATION_JSON) .get(ClientResponse.class); + if (round == 1) { + assertEquals(ClientResponse.Status.FORBIDDEN, + response.getClientResponseStatus()); + return; + } assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java index ce846b2..c5683ac 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java @@ -18,6 +18,7 @@ package org.apache.hadoop.yarn.server.webapp; +import java.lang.reflect.UndeclaredThrowableException; import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.Collection; @@ -37,6 +38,7 @@ import org.apache.hadoop.yarn.api.records.ContainerReport; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.YarnApplicationState; +import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.api.ApplicationContext; import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptInfo; import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptsInfo; @@ -46,6 +48,7 @@ import org.apache.hadoop.yarn.server.webapp.dao.ContainersInfo; 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; public class WebServices { @@ -151,7 +154,7 @@ public AppsInfo getApps(HttpServletRequest req, HttpServletResponse res, }); } } catch (Exception e) { - throw new WebApplicationException(e); + rewrapAndThrowException(e); } for (ApplicationReport appReport : appReports) { @@ -221,7 +224,7 @@ public ApplicationReport run() throws Exception { }); } } catch (Exception e) { - throw new WebApplicationException(e); + rewrapAndThrowException(e); } if (app == null) { throw new NotFoundException("app with id: " + appId + " not found"); @@ -247,7 +250,7 @@ public AppAttemptsInfo getAppAttempts(HttpServletRequest req, }); } } catch (Exception e) { - throw new WebApplicationException(e); + rewrapAndThrowException(e); } AppAttemptsInfo appAttemptsInfo = new AppAttemptsInfo(); for (ApplicationAttemptReport appAttemptReport : appAttemptReports) { @@ -278,7 +281,7 @@ public ApplicationAttemptReport run() throws Exception { }); } } catch (Exception e) { - throw new WebApplicationException(e); + rewrapAndThrowException(e); } if (appAttempt == null) { throw new NotFoundException("app attempt with id: " + appAttemptId @@ -307,7 +310,7 @@ public ContainersInfo getContainers(HttpServletRequest req, }); } } catch (Exception e) { - throw new WebApplicationException(e); + rewrapAndThrowException(e); } ContainersInfo containersInfo = new ContainersInfo(); for (ContainerReport containerReport : containerReports) { @@ -339,7 +342,7 @@ public ContainerReport run() throws Exception { }); } } catch (Exception e) { - throw new WebApplicationException(e); + rewrapAndThrowException(e); } if (container == null) { throw new NotFoundException("container with id: " + containerId @@ -441,4 +444,21 @@ protected static UserGroupInformation getUser(HttpServletRequest req) { return callerUGI; } + private static void checkAndThrowForbiddenException(Throwable t) { + if (t instanceof YarnException && t.getMessage().contains( + " does not have privilage to see this application ")) { + throw new ForbiddenException(t); + } + } + + private static void rewrapAndThrowException(Exception e) { + if (e instanceof UndeclaredThrowableException) { + checkAndThrowForbiddenException(e.getCause()); + throw new WebApplicationException(e.getCause()); + } else { + checkAndThrowForbiddenException(e); + throw new WebApplicationException(e); + } + } + }