From 0b511e9c7e8de5c804afae31bab62b9b687ac23a Mon Sep 17 00:00:00 2001 From: Sunil G Date: Sat, 5 May 2018 10:26:35 +0530 Subject: [PATCH] YARN-8249 --- .../resourcemanager/webapp/RMWebServices.java | 214 ++++++--------------- .../resourcemanager/webapp/TestRMWebServices.java | 2 +- ...TestRMWebServicesHttpStaticUserPermissions.java | 11 +- 3 files changed, 66 insertions(+), 161 deletions(-) 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..0f467afbdd4 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 @@ -277,6 +277,32 @@ private void init() { response.setContentType(null); } + private void initForWritableEndpoints(UserGroupInformation callerUGI, + boolean doAclsCheck) 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 (doAclsCheck) { + 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 }) @@ -336,15 +362,8 @@ public SchedulerTypeInfo getSchedulerInfo() { @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) { @@ -969,18 +988,8 @@ public Response updateAppState(AppState targetState, @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; @@ -1073,6 +1082,9 @@ public LabelsToNodesInfo getLabelsToNodes( 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 +1106,9 @@ public Response replaceLabelsOnNode( @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>(); @@ -1156,14 +1171,9 @@ public NodeLabelsInfo getClusterNodeLabels(@Context HttpServletRequest hsr) @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 +1199,9 @@ public Response addToClusterNodeLabels(final NodeLabelsInfo newNodeLabels, 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 "; @@ -1322,22 +1327,12 @@ public Response updateApplicationPriority(AppPriority targetPriority, @Context HttpServletRequest hsr, @PathParam(RMWSConsts.APPID) String appId) throws AuthorizationException, YarnException, InterruptedException, IOException { - init(); 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(); - } + initForWritableEndpoints(callerUGI, false); String userName = callerUGI.getUserName(); RMApp app = null; @@ -1440,17 +1435,8 @@ public Response updateAppQueue(AppQueue targetQueue, @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 +1547,8 @@ private boolean isStaticUser(UserGroupInformation callerUGI) { @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 +1568,8 @@ public Response submitApplication(ApplicationSubmissionContextInfo newApp, @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 +1623,9 @@ private NewApplication createNewApplication() { 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 +1636,10 @@ private UserGroupInformation createKerberosUserGroupInformation( } 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 +1652,11 @@ public Response postDelegationToken(DelegationToken tokenData, @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 +1673,11 @@ public Response postDelegationTokenExpiration(@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(); } @@ -1828,9 +1790,10 @@ public Response cancelDelegationToken(@Context HttpServletRequest hsr) Exception { init(); - UserGroupInformation callerUGI; + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); 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 +1867,8 @@ public CancelDelegationTokenResponse run() @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 +1908,8 @@ public Response submitReservation(ReservationSubmissionRequestInfo resContext, @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 +1998,8 @@ public Response updateReservation(ReservationUpdateRequestInfo resContext, @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 +2089,8 @@ public Response deleteReservation(ReservationDeleteRequestInfo resContext, @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); @@ -2355,19 +2286,9 @@ public Response updateApplicationTimeout(AppTimeoutInfo appTimeout, @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 +2401,9 @@ protected ContainerReport getContainerReport( 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) 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 void testDumpingSchedulerLogs() throws Exception { 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..cf6717697e9 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 @@ -177,17 +177,8 @@ public void testWebServiceAccess() throws Exception { fail("Request " + entry.getKey() + "succeeded but should have failed"); } catch (IOException e) { assertEquals(Status.FORBIDDEN.getStatusCode(), conn.getResponseCode()); - InputStream errorStream = conn.getErrorStream(); - String error = ""; - BufferedReader reader = - new BufferedReader(new InputStreamReader(errorStream, "UTF8")); - for (String line; (line = reader.readLine()) != null;) { - error += line; - } - reader.close(); - errorStream.close(); assertEquals( - "The default static user cannot carry out this operation.", error); + "java.lang.Exception: The default static user cannot carry out this operation.", e.getMessage()); } conn.disconnect(); } -- 2.14.3 (Apple Git-98)