YARN-10039. Allow disabling app submission from REST endpoints

This commit is contained in:
Jonathan Hung 2019-12-18 10:48:05 -08:00
parent 280cd6dd1e
commit 406c35dd12
4 changed files with 42 additions and 1 deletions

View File

@ -3646,6 +3646,10 @@ public class YarnConfiguration extends Configuration {
public static final boolean DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER = public static final boolean DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER =
false; 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 // RM and NM CSRF props
public static final String REST_CSRF = "webapp.rest-csrf."; public static final String REST_CSRF = "webapp.rest-csrf.";
public static final String RM_CSRF_PREFIX = RM_PREFIX + REST_CSRF; public static final String RM_CSRF_PREFIX = RM_PREFIX + REST_CSRF;

View File

@ -3890,4 +3890,10 @@
<name>yarn.workflow-id.tag-prefix</name> <name>yarn.workflow-id.tag-prefix</name>
<value>workflowid:</value> <value>workflowid:</value>
</property> </property>
<property>
<description>Whether or not to allow application submissions via REST. Default is true.</description>
<name>yarn.webapp.enable-rest-app-submissions</name>
<value>true</value>
</property>
</configuration> </configuration>

View File

@ -232,6 +232,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
@VisibleForTesting @VisibleForTesting
boolean isCentralizedNodeLabelConfiguration = true; boolean isCentralizedNodeLabelConfiguration = true;
private boolean filterAppsByUser = false; private boolean filterAppsByUser = false;
private boolean enableRestAppSubmissions = true;
public final static String DELEGATION_TOKEN_HEADER = public final static String DELEGATION_TOKEN_HEADER =
"Hadoop-YARN-RM-Delegation-Token"; "Hadoop-YARN-RM-Delegation-Token";
@ -247,6 +248,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
this.filterAppsByUser = conf.getBoolean( this.filterAppsByUser = conf.getBoolean(
YarnConfiguration.FILTER_ENTITY_LIST_BY_USER, YarnConfiguration.FILTER_ENTITY_LIST_BY_USER,
YarnConfiguration.DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER); YarnConfiguration.DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER);
this.enableRestAppSubmissions = conf.getBoolean(
YarnConfiguration.ENABLE_REST_APP_SUBMISSIONS,
YarnConfiguration.DEFAULT_ENABLE_REST_APP_SUBMISSIONS);
} }
RMWebServices(ResourceManager rm, Configuration conf, RMWebServices(ResourceManager rm, Configuration conf,
@ -1471,6 +1475,10 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
@Override @Override
public Response createNewApplication(@Context HttpServletRequest hsr) public Response createNewApplication(@Context HttpServletRequest hsr)
throws AuthorizationException, IOException, InterruptedException { 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); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
initForWritableEndpoints(callerUGI, false); initForWritableEndpoints(callerUGI, false);
@ -1491,6 +1499,10 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
public Response submitApplication(ApplicationSubmissionContextInfo newApp, public Response submitApplication(ApplicationSubmissionContextInfo newApp,
@Context HttpServletRequest hsr) @Context HttpServletRequest hsr)
throws AuthorizationException, IOException, InterruptedException { 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); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
initForWritableEndpoints(callerUGI, false); initForWritableEndpoints(callerUGI, false);

View File

@ -36,6 +36,7 @@ import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
@ -64,6 +65,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler; 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.fair.FairScheduler;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler; 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.AppsInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterUserInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterUserInfo;
import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
@ -77,7 +79,6 @@ import org.apache.hadoop.yarn.webapp.JerseyTestBase;
import org.apache.hadoop.yarn.webapp.WebServicesTestUtils; import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONObject;
import org.eclipse.jetty.server.Response;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -856,6 +857,24 @@ public class TestRMWebServices extends JerseyTestBase {
verifyClusterUserInfo(userInfo, "yarn", "admin"); verifyClusterUserInfo(userInfo, "yarn", "admin");
} }
@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, public void verifyClusterUserInfo(ClusterUserInfo userInfo,
String rmLoginUser, String requestedUser) { String rmLoginUser, String requestedUser) {
assertEquals("rmLoginUser doesn't match: ", assertEquals("rmLoginUser doesn't match: ",