diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index 40729d4e6eb..06c3fa4c64a 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -4219,6 +4219,10 @@ public static boolean areNodeLabelsEnabled( "yarn.webapp.filter-invalid-xml-chars"; public static final boolean DEFAULT_FILTER_INVALID_XML_CHARS = false; + public static final String ENABLE_REST_APP_SUBMISSIONS = + "yarn.webapp.enable-rest-app-submissions"; + public static final boolean DEFAULT_ENABLE_REST_APP_SUBMISSIONS = true; + // RM and NM CSRF props public static final String REST_CSRF = "webapp.rest-csrf."; public static final String RM_CSRF_PREFIX = RM_PREFIX + REST_CSRF; diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml index a1422166f51..c96a7e4cfe5 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml @@ -4487,4 +4487,10 @@ yarn.workflow-id.tag-prefix workflowid: + + + Whether or not to allow application submissions via REST. Default is true. + yarn.webapp.enable-rest-app-submissions + true + diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java 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 67d09da6aba..5ff4b06acc3 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java @@ -244,6 +244,7 @@ boolean isCentralizedNodeLabelConfiguration = true; private boolean filterAppsByUser = false; private boolean filterInvalidXMLChars = false; + private boolean enableRestAppSubmissions = true; public final static String DELEGATION_TOKEN_HEADER = "Hadoop-YARN-RM-Delegation-Token"; @@ -262,6 +263,9 @@ public RMWebServices(final ResourceManager rm, Configuration conf) { this.filterInvalidXMLChars = conf.getBoolean( YarnConfiguration.FILTER_INVALID_XML_CHARS, YarnConfiguration.DEFAULT_FILTER_INVALID_XML_CHARS); + this.enableRestAppSubmissions = conf.getBoolean( + YarnConfiguration.ENABLE_REST_APP_SUBMISSIONS, + YarnConfiguration.DEFAULT_ENABLE_REST_APP_SUBMISSIONS); } RMWebServices(ResourceManager rm, Configuration conf, @@ -1716,6 +1720,10 @@ private boolean isStaticUser(UserGroupInformation callerUGI) { @Override public Response createNewApplication(@Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { + if (!enableRestAppSubmissions) { + String msg = "App submission via REST is disabled."; + return Response.status(Status.FORBIDDEN).entity(msg).build(); + } UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); initForWritableEndpoints(callerUGI, false); @@ -1736,6 +1744,10 @@ public Response createNewApplication(@Context HttpServletRequest hsr) public Response submitApplication(ApplicationSubmissionContextInfo newApp, @Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { + if (!enableRestAppSubmissions) { + String msg = "App submission via REST is disabled."; + return Response.status(Status.FORBIDDEN).entity(msg).build(); + } UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); initForWritableEndpoints(callerUGI, false); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java 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 d9d1d9b0d39..e73462f9638 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java @@ -43,6 +43,7 @@ import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -76,6 +77,7 @@ 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.ApplicationSubmissionContextInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterUserInfo; import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; @@ -952,6 +954,24 @@ public void testInvalidXMLChars() throws Exception { "java.lang.Exception: \uFFFD", appsInfo.getApps().get(0).getNote()); } + @Test + public void testDisableRestAppSubmission() throws Exception { + Configuration conf = new YarnConfiguration(); + conf.setBoolean(YarnConfiguration.ENABLE_REST_APP_SUBMISSIONS, false); + RMWebServices webSvc = new RMWebServices(mock(ResourceManager.class), conf, + mock(HttpServletResponse.class)); + HttpServletRequest request = mock(HttpServletRequest.class); + + Response response = webSvc.createNewApplication(request); + assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); + assertEquals("App submission via REST is disabled.", response.getEntity()); + + response = webSvc.submitApplication( + mock(ApplicationSubmissionContextInfo.class), request); + assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); + assertEquals("App submission via REST is disabled.", response.getEntity()); + } + public void verifyClusterUserInfo(ClusterUserInfo userInfo, String rmLoginUser, String requestedUser) { assertEquals("rmLoginUser doesn't match: ",