diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java index 755127b20b2..9aa71a7037d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java @@ -111,7 +111,7 @@ public class AHSWebServices extends WebServices { public TimelineAbout about( @Context HttpServletRequest req, @Context HttpServletResponse res) { - init(res); + initForReadableEndpoints(res); return TimelineUtils.createTimelineAbout("Generic History Service API"); } @@ -141,7 +141,7 @@ public class AHSWebServices extends WebServices { @QueryParam("finishedTimeBegin") String finishBegin, @QueryParam("finishedTimeEnd") String finishEnd, @QueryParam("applicationTypes") Set applicationTypes) { - init(res); + initForReadableEndpoints(res); validateStates(stateQuery, statesQuery); return super.getApps(req, res, stateQuery, statesQuery, finalStatusQuery, userQuery, queueQuery, count, startedBegin, startedEnd, finishBegin, @@ -155,7 +155,7 @@ public class AHSWebServices extends WebServices { @Override public AppInfo getApp(@Context HttpServletRequest req, @Context HttpServletResponse res, @PathParam("appid") String appId) { - init(res); + initForReadableEndpoints(res); return super.getApp(req, res, appId); } @@ -166,7 +166,7 @@ public class AHSWebServices extends WebServices { @Override public AppAttemptsInfo getAppAttempts(@Context HttpServletRequest req, @Context HttpServletResponse res, @PathParam("appid") String appId) { - init(res); + initForReadableEndpoints(res); return super.getAppAttempts(req, res, appId); } @@ -178,7 +178,7 @@ public class AHSWebServices extends WebServices { public AppAttemptInfo getAppAttempt(@Context HttpServletRequest req, @Context HttpServletResponse res, @PathParam("appid") String appId, @PathParam("appattemptid") String appAttemptId) { - init(res); + initForReadableEndpoints(res); return super.getAppAttempt(req, res, appId, appAttemptId); } @@ -190,7 +190,7 @@ public class AHSWebServices extends WebServices { public ContainersInfo getContainers(@Context HttpServletRequest req, @Context HttpServletResponse res, @PathParam("appid") String appId, @PathParam("appattemptid") String appAttemptId) { - init(res); + initForReadableEndpoints(res); return super.getContainers(req, res, appId, appAttemptId); } @@ -203,7 +203,7 @@ public class AHSWebServices extends WebServices { @Context HttpServletResponse res, @PathParam("appid") String appId, @PathParam("appattemptid") String appAttemptId, @PathParam("containerid") String containerId) { - init(res); + initForReadableEndpoints(res); return super.getContainer(req, res, appId, appAttemptId, containerId); } @@ -257,7 +257,7 @@ public class AHSWebServices extends WebServices { @QueryParam(YarnWebServiceParams.REDIRECTED_FROM_NODE) @DefaultValue("false") boolean redirected_from_node) { ContainerId containerId = null; - init(res); + initForReadableEndpoints(res); try { containerId = ContainerId.fromString(containerIdStr); } catch (IllegalArgumentException e) { @@ -392,7 +392,7 @@ public class AHSWebServices extends WebServices { @QueryParam(YarnWebServiceParams.NM_ID) String nmId, @QueryParam(YarnWebServiceParams.REDIRECTED_FROM_NODE) @DefaultValue("false") boolean redirected_from_node) { - init(res); + initForReadableEndpoints(res); ContainerId containerId; try { containerId = ContainerId.fromString(containerIdStr); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java index 1399099a28a..df4656f427f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebServices.java @@ -387,7 +387,7 @@ public class WebServices { return new ContainerInfo(container); } - protected void init(HttpServletResponse response) { + protected void initForReadableEndpoints(HttpServletResponse response) { // clear content type response.setContentType(null); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java b/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 0564b6776ed..69c95629b1e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java @@ -272,11 +272,51 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { return true; } - private void init() { + /** + * initForReadableEndpoints does the init for all readable REST end points. + */ + private void initForReadableEndpoints() { // clear content type response.setContentType(null); } + /** + * initForWritableEndpoints does the init and acls verification for all + * writable REST end points. + * + * @param callerUGI + * remote caller who initiated the request + * @param doAdminACLsCheck + * boolean flag to indicate whether ACLs check is needed + * @throws AuthorizationException + * in case of no access to perfom this op. + */ + private void initForWritableEndpoints(UserGroupInformation callerUGI, + boolean doAdminACLsCheck) throws AuthorizationException { + // clear content type + response.setContentType(null); + + if (callerUGI == null) { + String msg = "Unable to obtain user name, user not authenticated"; + throw new AuthorizationException(msg); + } + + if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { + String msg = "The default static user cannot carry out this operation."; + throw new ForbiddenException(msg); + } + + if (doAdminACLsCheck) { + ApplicationACLsManager aclsManager = rm.getApplicationACLsManager(); + if (aclsManager.areACLsEnabled()) { + if (!aclsManager.isAdmin(callerUGI)) { + String msg = "Only admins can carry out this operation."; + throw new ForbiddenException(msg); + } + } + } + } + @GET @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8, MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) @@ -291,7 +331,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) @Override public ClusterInfo getClusterInfo() { - init(); + initForReadableEndpoints(); return new ClusterInfo(this.rm); } @@ -301,7 +341,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) @Override public ClusterMetricsInfo getClusterMetricsInfo() { - init(); + initForReadableEndpoints(); return new ClusterMetricsInfo(this.rm); } @@ -311,7 +351,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) @Override public SchedulerTypeInfo getSchedulerInfo() { - init(); + initForReadableEndpoints(); + ResourceScheduler rs = rm.getResourceScheduler(); SchedulerInfo sinfo; if (rs instanceof CapacityScheduler) { @@ -336,15 +377,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public String dumpSchedulerLogs(@FormParam(RMWSConsts.TIME) String time, @Context HttpServletRequest hsr) throws IOException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - ApplicationACLsManager aclsManager = rm.getApplicationACLsManager(); - if (aclsManager.areACLsEnabled()) { - if (callerUGI == null || !aclsManager.isAdmin(callerUGI)) { - String msg = "Only admins can carry out this operation."; - throw new ForbiddenException(msg); - } - } + initForWritableEndpoints(callerUGI, true); + ResourceScheduler rs = rm.getResourceScheduler(); int period = Integer.parseInt(time); if (period <= 0) { @@ -370,7 +405,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) @Override public NodesInfo getNodes(@QueryParam(RMWSConsts.STATES) String states) { - init(); + initForReadableEndpoints(); + ResourceScheduler sched = this.rm.getResourceScheduler(); if (sched == null) { throw new NotFoundException("Null ResourceScheduler instance"); @@ -409,7 +445,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 }) @Override public NodeInfo getNode(@PathParam(RMWSConsts.NODEID) String nodeId) { - init(); + initForReadableEndpoints(); + if (nodeId == null || nodeId.isEmpty()) { throw new NotFoundException("nodeId, " + nodeId + ", is empty or null"); } @@ -453,6 +490,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @QueryParam(RMWSConsts.APPLICATION_TYPES) Set applicationTypes, @QueryParam(RMWSConsts.APPLICATION_TAGS) Set applicationTags, @QueryParam(RMWSConsts.DESELECTS) Set unselectedFields) { + + initForReadableEndpoints(); + boolean checkCount = false; boolean checkStart = false; boolean checkEnd = false; @@ -467,7 +507,6 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { long fBegin = 0; long fEnd = Long.MAX_VALUE; - init(); if (count != null && !count.isEmpty()) { checkCount = true; countNum = Long.parseLong(count); @@ -633,8 +672,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public ActivitiesInfo getActivities(@Context HttpServletRequest hsr, @QueryParam(RMWSConsts.NODEID) String nodeId) { - YarnScheduler scheduler = rm.getRMContext().getScheduler(); + initForReadableEndpoints(); + YarnScheduler scheduler = rm.getRMContext().getScheduler(); if (scheduler instanceof AbstractYarnScheduler) { String errMessage = ""; @@ -706,8 +746,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { public AppActivitiesInfo getAppActivities(@Context HttpServletRequest hsr, @QueryParam(RMWSConsts.APP_ID) String appId, @QueryParam(RMWSConsts.MAX_TIME) String time) { - YarnScheduler scheduler = rm.getRMContext().getScheduler(); + initForReadableEndpoints(); + YarnScheduler scheduler = rm.getRMContext().getScheduler(); if (scheduler instanceof AbstractYarnScheduler) { AbstractYarnScheduler abstractYarnScheduler = (AbstractYarnScheduler) scheduler; @@ -760,7 +801,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr, @QueryParam(RMWSConsts.STATES) Set stateQueries, @QueryParam(RMWSConsts.APPLICATION_TYPES) Set typeQueries) { - init(); + initForReadableEndpoints(); // parse the params and build the scoreboard // converting state/type name to lowercase @@ -847,7 +888,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { public AppInfo getApp(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId, @QueryParam(RMWSConsts.DESELECTS) Set unselectedFields) { - init(); + initForReadableEndpoints(); + ApplicationId id = WebAppUtils.parseApplicationId(recordFactory, appId); RMApp app = rm.getRMContext().getRMApps().get(id); if (app == null) { @@ -868,8 +910,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public AppAttemptsInfo getAppAttempts(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) { + initForReadableEndpoints(); - init(); ApplicationId id = WebAppUtils.parseApplicationId(recordFactory, appId); RMApp app = rm.getRMContext().getRMApps().get(id); if (app == null) { @@ -895,7 +937,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest req, @Context HttpServletResponse res, @PathParam(RMWSConsts.APPID) String appId, @PathParam(RMWSConsts.APPATTEMPTID) String appAttemptId) { - init(res); + initForReadableEndpoints(res); return super.getAppAttempt(req, res, appId, appAttemptId); } @@ -908,7 +950,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletResponse res, @PathParam(RMWSConsts.APPID) String appId, @PathParam(RMWSConsts.APPATTEMPTID) String appAttemptId) { - init(res); + initForReadableEndpoints(res); return super.getContainers(req, res, appId, appAttemptId); } @@ -922,7 +964,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @PathParam(RMWSConsts.APPID) String appId, @PathParam(RMWSConsts.APPATTEMPTID) String appAttemptId, @PathParam("containerid") String containerId) { - init(res); + initForReadableEndpoints(res); return super.getContainer(req, res, appId, appAttemptId, containerId); } @@ -933,7 +975,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public AppState getAppState(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException { - init(); + initForReadableEndpoints(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); String userName = ""; if (callerUGI != null) { @@ -969,18 +1012,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException, YarnException, InterruptedException, IOException { - - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - String msg = "Unable to obtain user name, user not authenticated"; - throw new AuthorizationException(msg); - } - - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); String userName = callerUGI.getUserName(); RMApp app = null; @@ -1019,7 +1052,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public NodeToLabelsInfo getNodeToLabels(@Context HttpServletRequest hsr) throws IOException { - init(); + initForReadableEndpoints(); NodeToLabelsInfo ntl = new NodeToLabelsInfo(); HashMap ntlMap = ntl.getNodeToLabels(); @@ -1041,7 +1074,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public LabelsToNodesInfo getLabelsToNodes( @QueryParam(RMWSConsts.LABELS) Set labels) throws IOException { - init(); + initForReadableEndpoints(); LabelsToNodesInfo lts = new LabelsToNodesInfo(); Map ltsMap = lts.getLabelsToNodes(); @@ -1073,6 +1106,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { public Response replaceLabelsOnNodes( final NodeToLabelsEntryList newNodeToLabels, @Context HttpServletRequest hsr) throws IOException { + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + initForWritableEndpoints(callerUGI, false); + Map> nodeIdToLabels = new HashMap>(); @@ -1094,6 +1130,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @QueryParam("labels") Set newNodeLabelsName, @Context HttpServletRequest hsr, @PathParam("nodeId") String nodeId) throws Exception { + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + initForWritableEndpoints(callerUGI, false); + NodeId nid = ConverterUtils.toNodeIdWithDefaultPort(nodeId); Map> newLabelsForNode = new HashMap>(); @@ -1106,7 +1145,6 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { private Response replaceLabelsOnNode( Map> newLabelsForNode, HttpServletRequest hsr, String operation) throws IOException { - init(); NodeLabelsUtils.verifyCentralizedNodeLabelConfEnabled("replaceLabelsOnNode", isCentralizedNodeLabelConfiguration); @@ -1140,7 +1178,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public NodeLabelsInfo getClusterNodeLabels(@Context HttpServletRequest hsr) throws IOException { - init(); + initForReadableEndpoints(); List nodeLabels = rm.getRMContext().getNodeLabelManager().getClusterNodeLabels(); @@ -1156,14 +1194,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public Response addToClusterNodeLabels(final NodeLabelsInfo newNodeLabels, @Context HttpServletRequest hsr) throws Exception { - init(); - UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - String msg = "Unable to obtain user name, user not authenticated for" - + " post to .../add-node-labels"; - throw new AuthorizationException(msg); - } + initForWritableEndpoints(callerUGI, false); + if (!rm.getRMContext().getNodeLabelManager().checkAccess(callerUGI)) { String msg = "User " + callerUGI.getShortUserName() + " not authorized" + " for post to .../add-node-labels "; @@ -1189,14 +1222,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { public Response removeFromCluserNodeLabels( @QueryParam(RMWSConsts.LABELS) Set oldNodeLabels, @Context HttpServletRequest hsr) throws Exception { - init(); - UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - String msg = "Unable to obtain user name, user not authenticated for" - + " post to .../remove-node-labels"; - throw new AuthorizationException(msg); - } + initForWritableEndpoints(callerUGI, false); + if (!rm.getRMContext().getNodeLabelManager().checkAccess(callerUGI)) { String msg = "User " + callerUGI.getShortUserName() + " not authorized" + " for post to .../remove-node-labels "; @@ -1220,7 +1248,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public NodeLabelsInfo getLabelsOnNode(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.NODEID) String nodeId) throws IOException { - init(); + initForReadableEndpoints(); NodeId nid = ConverterUtils.toNodeIdWithDefaultPort(nodeId); List labels = new ArrayList( @@ -1290,7 +1318,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public AppPriority getAppPriority(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException { - init(); + initForReadableEndpoints(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); String userName = "UNKNOWN-USER"; if (callerUGI != null) { @@ -1322,23 +1351,13 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException, YarnException, InterruptedException, IOException { - init(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + initForWritableEndpoints(callerUGI, false); + if (targetPriority == null) { throw new YarnException("Target Priority cannot be null"); } - UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, user not authenticated"); - } - - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - return Response.status(Status.FORBIDDEN) - .entity("The default static user cannot carry out this operation.") - .build(); - } - String userName = callerUGI.getUserName(); RMApp app = null; try { @@ -1407,7 +1426,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public AppQueue getAppQueue(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException { - init(); + initForReadableEndpoints(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); String userName = "UNKNOWN-USER"; if (callerUGI != null) { @@ -1440,17 +1460,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException, YarnException, InterruptedException, IOException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - String msg = "Unable to obtain user name, user not authenticated"; - throw new AuthorizationException(msg); - } - - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); String userName = callerUGI.getUserName(); RMApp app = null; @@ -1561,16 +1572,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public Response createNewApplication(@Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, " + "user not authenticated"); - } - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); NewApplication appId = createNewApplication(); return Response.status(Status.OK).entity(appId).build(); @@ -1590,17 +1593,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, " + "user not authenticated"); - } - - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); ApplicationSubmissionContext appContext = RMWebAppUtil.createAppSubmissionContext(newApp, conf); @@ -1654,14 +1648,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { return appId; } - private UserGroupInformation createKerberosUserGroupInformation( - HttpServletRequest hsr) throws AuthorizationException, YarnException { - - UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - String msg = "Unable to obtain user name, user not authenticated"; - throw new AuthorizationException(msg); - } + private void createKerberosUserGroupInformation(HttpServletRequest hsr, + UserGroupInformation callerUGI) + throws AuthorizationException, YarnException { String authType = hsr.getAuthType(); if (!KerberosAuthenticationHandler.TYPE.equalsIgnoreCase(authType)) { @@ -1672,14 +1661,10 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { } if (hsr.getAttribute( DelegationTokenAuthenticationHandler.DELEGATION_TOKEN_UGI_ATTRIBUTE) != null) { - String msg = - "Delegation token operations cannot be carried out using delegation" - + " token authentication."; + String msg = "Delegation token operations cannot be carried out using " + + "delegation token authentication."; throw new YarnException(msg); } - - callerUGI.setAuthenticationMethod(AuthenticationMethod.KERBEROS); - return callerUGI; } @POST @@ -1692,10 +1677,12 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException, Exception { - init(); - UserGroupInformation callerUGI; + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + initForWritableEndpoints(callerUGI, false); + try { - callerUGI = createKerberosUserGroupInformation(hsr); + createKerberosUserGroupInformation(hsr, callerUGI); + callerUGI.setAuthenticationMethod(AuthenticationMethod.KERBEROS); } catch (YarnException ye) { return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build(); } @@ -1712,10 +1699,12 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { throws AuthorizationException, IOException, InterruptedException, Exception { - init(); - UserGroupInformation callerUGI; + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + initForWritableEndpoints(callerUGI, false); + try { - callerUGI = createKerberosUserGroupInformation(hsr); + createKerberosUserGroupInformation(hsr, callerUGI); + callerUGI.setAuthenticationMethod(AuthenticationMethod.KERBEROS); } catch (YarnException ye) { return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build(); } @@ -1827,10 +1816,12 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { throws AuthorizationException, IOException, InterruptedException, Exception { - init(); - UserGroupInformation callerUGI; + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); + initForWritableEndpoints(callerUGI, false); + try { - callerUGI = createKerberosUserGroupInformation(hsr); + createKerberosUserGroupInformation(hsr, callerUGI); + callerUGI.setAuthenticationMethod(AuthenticationMethod.KERBEROS); } catch (YarnException ye) { return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build(); } @@ -1904,16 +1895,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public Response createNewReservation(@Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, " + "user not authenticated"); - } - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); NewReservation reservationId = createNewReservation(); return Response.status(Status.OK).entity(reservationId).build(); @@ -1953,16 +1936,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, " + "user not authenticated"); - } - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); final ReservationSubmissionRequest reservation = createReservationSubmissionRequest(resContext); @@ -2051,16 +2026,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, " + "user not authenticated"); - } - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); final ReservationUpdateRequest reservation = createReservationUpdateRequest(resContext); @@ -2150,16 +2117,8 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr) throws AuthorizationException, IOException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, " + "user not authenticated"); - } - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - String msg = "The default static user cannot carry out this operation."; - return Response.status(Status.FORBIDDEN).entity(msg).build(); - } + initForWritableEndpoints(callerUGI, false); final ReservationDeleteRequest reservation = createReservationDeleteRequest(resContext); @@ -2207,7 +2166,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @QueryParam(RMWSConsts.END_TIME) @DefaultValue(DEFAULT_END_TIME) long endTime, @QueryParam(RMWSConsts.INCLUDE_RESOURCE) @DefaultValue(DEFAULT_INCLUDE_RESOURCE) boolean includeResourceAllocations, @Context HttpServletRequest hsr) throws Exception { - init(); + initForReadableEndpoints(); final ReservationListRequest request = ReservationListRequest.newInstance( queue, reservationId, startTime, endTime, includeResourceAllocations); @@ -2253,7 +2212,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { public AppTimeoutInfo getAppTimeout(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId, @PathParam(RMWSConsts.TYPE) String type) throws AuthorizationException { - init(); + initForReadableEndpoints(); RMApp app = validateAppTimeoutRequest(hsr, appId); ApplicationTimeoutType appTimeoutType = parseTimeoutType(type); @@ -2297,7 +2256,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Override public AppTimeoutsInfo getAppTimeouts(@Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException { - init(); + initForReadableEndpoints(); RMApp app = validateAppTimeoutRequest(hsr, appId); @@ -2355,19 +2314,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException, YarnException, InterruptedException, IOException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - if (callerUGI == null) { - throw new AuthorizationException( - "Unable to obtain user name, user not authenticated"); - } - - if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) { - return Response.status(Status.FORBIDDEN) - .entity("The default static user cannot carry out this operation.") - .build(); - } + initForWritableEndpoints(callerUGI, false); String userName = callerUGI.getUserName(); RMApp app = null; @@ -2480,16 +2429,9 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { public synchronized Response updateSchedulerConfiguration(SchedConfUpdateInfo mutationInfo, @Context HttpServletRequest hsr) throws AuthorizationException, InterruptedException { - init(); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); - ApplicationACLsManager aclsManager = rm.getApplicationACLsManager(); - if (aclsManager.areACLsEnabled()) { - if (callerUGI == null || !aclsManager.isAdmin(callerUGI)) { - String msg = "Only admins can carry out this operation."; - throw new ForbiddenException(msg); - } - } + initForWritableEndpoints(callerUGI, true); ResourceScheduler scheduler = rm.getResourceScheduler(); if (scheduler instanceof MutableConfScheduler && ((MutableConfScheduler) @@ -2541,7 +2483,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol { @QueryParam(RMWSConsts.QUEUE_ACL_TYPE) @DefaultValue("SUBMIT_APPLICATIONS") String queueAclType, @Context HttpServletRequest hsr) throws AuthorizationException { - init(); + initForReadableEndpoints(); // For the user who invokes this REST call, he/she should have admin access // to the queue. Otherwise we will reject the call. diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java b/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 9c4acc2e94e..0702d652a02 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java @@ -684,7 +684,7 @@ public class TestRMWebServices extends JerseyTestBase { ResourceManager mockRM = mock(ResourceManager.class); Configuration conf = new YarnConfiguration(); - HttpServletRequest mockHsr = mock(HttpServletRequest.class); + HttpServletRequest mockHsr = mockHttpServletRequestByUserName("non-admin"); ApplicationACLsManager aclsManager = new ApplicationACLsManager(conf); when(mockRM.getApplicationACLsManager()).thenReturn(aclsManager); RMWebServices webSvc = diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesHttpStaticUserPermissions.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesHttpStaticUserPermissions.java index 60c6f5e950c..cef32f4c2bf 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesHttpStaticUserPermissions.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesHttpStaticUserPermissions.java @@ -41,6 +41,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.MockRM; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ApplicationSubmissionContextInfo; +import org.codehaus.jettison.json.JSONObject; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -179,15 +180,20 @@ public class TestRMWebServicesHttpStaticUserPermissions { assertEquals(Status.FORBIDDEN.getStatusCode(), conn.getResponseCode()); InputStream errorStream = conn.getErrorStream(); String error = ""; - BufferedReader reader = - new BufferedReader(new InputStreamReader(errorStream, "UTF8")); + BufferedReader reader = new BufferedReader( + new InputStreamReader(errorStream, "UTF8")); for (String line; (line = reader.readLine()) != null;) { error += line; } reader.close(); errorStream.close(); + JSONObject errResponse = new JSONObject(error); + JSONObject remoteException = errResponse + .getJSONObject("RemoteException"); assertEquals( - "The default static user cannot carry out this operation.", error); + "java.lang.Exception: The default static user cannot carry out " + + "this operation.", + remoteException.getString("message")); } conn.disconnect(); }