From d861d4dad6ac3aced5d74eb58c603fd03f007a1f Mon Sep 17 00:00:00 2001 From: Sunil G Date: Fri, 8 Sep 2017 18:38:07 +0530 Subject: [PATCH] YARN-7157 --- .../apache/hadoop/yarn/conf/YarnConfiguration.java | 8 ++++ .../hadoop/yarn/server/webapp/AppsBlock.java | 8 ++++ .../server/resourcemanager/ClientRMService.java | 48 ++++++++++++++++++++-- .../resourcemanager/TestClientRMService.java | 14 +++++-- 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index be63233..5504cf0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -3106,6 +3106,14 @@ public static boolean areNodeLabelsEnabled( public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS = NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "opts"; + /* + * Support to view apps for given user in secure cluster. + */ + public static final String DISPLAY_APPS_FOR_LOGGED_IN_USER = + RM_PREFIX + "display.per-user-apps"; + public static final boolean DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER = + false; + // 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 a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppsBlock.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppsBlock.java index d836e64..40529ab 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppsBlock.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppsBlock.java @@ -30,6 +30,8 @@ import java.security.PrivilegedExceptionAction; import java.util.Collection; import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.math.LongRange; @@ -112,6 +114,12 @@ protected void fetchData() throws YarnException, IOException, if (callerUGI == null) { appReports = appBaseProt.getApplications(request).getApplicationList(); } else { + // In case of secured UI, only show the apps which this user could see + // given feature is enabled. + Set users = new HashSet(); + users.add(callerUGI.getShortUserName()); + request.setUsers(users); + appReports = callerUGI .doAs(new PrivilegedExceptionAction>() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java index df38893..de22e70 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java @@ -142,6 +142,7 @@ import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; import org.apache.hadoop.yarn.ipc.RPCUtil; import org.apache.hadoop.yarn.ipc.YarnRPC; +import org.apache.hadoop.yarn.security.YarnAuthorizationProvider; import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; @@ -201,12 +202,15 @@ private final ApplicationACLsManager applicationsACLsManager; private final QueueACLsManager queueACLsManager; + private YarnAuthorizationProvider authorizer; // For Reservation APIs private Clock clock; private ReservationSystem reservationSystem; private ReservationInputValidator rValidator; + private boolean displayPerUserApps = false; + private static final EnumSet ACTIVE_APP_STATES = EnumSet.of( RMAppState.ACCEPTED, RMAppState.RUNNING); @@ -237,6 +241,7 @@ public ClientRMService(RMContext rmContext, YarnScheduler scheduler, @Override protected void serviceInit(Configuration conf) throws Exception { clientBindAddress = getBindAddress(conf); + authorizer = YarnAuthorizationProvider.getInstance(conf); super.serviceInit(conf); } @@ -264,7 +269,11 @@ protected void serviceStart() throws Exception { } refreshServiceAcls(conf, RMPolicyProvider.getInstance()); } - + + this.displayPerUserApps = conf.getBoolean( + YarnConfiguration.DISPLAY_APPS_FOR_LOGGED_IN_USER, + YarnConfiguration.DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER); + this.server.start(); clientBindAddress = conf.updateConnectAddr(YarnConfiguration.RM_BIND_HOST, YarnConfiguration.RM_ADDRESS, @@ -861,9 +870,10 @@ public void remove() { } } - if (users != null && !users.isEmpty() && - !users.contains(application.getUser())) { - continue; + if (users != null && !users.isEmpty()) { + if (checkAppViewPermissionForUsers(callerUGI, users, application)) { + continue; + } } if (start != null && !start.containsLong(application.getStartTime())) { @@ -908,6 +918,32 @@ public void remove() { return response; } + private boolean checkAppViewPermissionForUsers(UserGroupInformation callerUGI, + Set users, RMApp application) { + if (this.displayPerUserApps && !users.contains(application.getUser()) + && !authorizer.isAdmin(callerUGI)) { + boolean noViewAccess = true; + for (String user : users) { + // If any one user in the client user list has access to view + // this app, then set noViewAccess to false so that the app wont be + // skipped. + if (applicationsACLsManager.checkAccess(callerUGI, + ApplicationAccessType.VIEW_APP, user, + application.getApplicationId())) { + noViewAccess = false; + } + } + if (noViewAccess) { + return true; + } + } else if (!this.displayPerUserApps + && !users.contains(application.getUser())) { + // retain old behavior when displayPerUserApps is off from config. + return true; + } + return false; + } + private Set getLowerCasedAppTypes(GetApplicationsRequest request) { Set applicationTypes = new HashSet<>(); if (request.getApplicationTypes() != null && !request.getApplicationTypes() @@ -1766,4 +1802,8 @@ private RMApp verifyUserAccessForRMApp(ApplicationId applicationId, return application; } + @VisibleForTesting + public void setDisplayPerUserApps(boolean displayPerUserApps) { + this.displayPerUserApps = displayPerUserApps; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java index ea733a4..6fa3ade 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java @@ -1054,9 +1054,12 @@ public void handle(Event event) {} for (int i = 0; i < appIds.length; i++) { ApplicationId appId = appIds[i]; when(mockAclsManager.checkAccess(UserGroupInformation.getCurrentUser(), - ApplicationAccessType.VIEW_APP, null, appId)).thenReturn(true); - SubmitApplicationRequest submitRequest = mockSubmitAppRequest( - appId, appNames[i], queues[i % queues.length], + ApplicationAccessType.VIEW_APP, null, appId)).thenReturn(true); +// when(mockAclsManager.checkAccess( +// UserGroupInformation.createUserForTesting("dr.who", new String[]{}), +// ApplicationAccessType.VIEW_APP, null, appId)).thenReturn(true); + SubmitApplicationRequest submitRequest = mockSubmitAppRequest(appId, + appNames[i], queues[i % queues.length], new HashSet(tags.subList(0, i + 1))); rmService.submitApplication(submitRequest); submitTimeMillis[i] = System.currentTimeMillis(); @@ -1118,6 +1121,11 @@ public void handle(Event event) {} assertEquals("Incorrect number of applications for user", 3, rmService.getApplications(request).getApplicationList().size()); + rmService.setDisplayPerUserApps(true); + assertEquals("Incorrect number of applications for user", 6, + rmService.getApplications(request).getApplicationList().size()); + rmService.setDisplayPerUserApps(false); + // Check tags request = GetApplicationsRequest.newInstance( ApplicationsRequestScope.ALL, null, null, null, null, null, null, -- 2.10.1 (Apple Git-78)