@Override public GetJobReportResponse getJobReport(GetJobReportRequest request) throws IOException { JobId jobId = request.getJobId(); // false is for retain compatibility Job job = verifyAndGetJob(jobId, JobACL.VIEW_JOB, false); GetJobReportResponse response = recordFactory.newRecordInstance(GetJobReportResponse.class); if (job != null) { response.setJobReport(job.getReport()); } else { response.setJobReport(null); } return response; }
@SuppressWarnings("unchecked") @Override public KillJobResponse killJob(KillJobRequest request) throws IOException { JobId jobId = request.getJobId(); UserGroupInformation callerUGI = UserGroupInformation.getCurrentUser(); String message = "Kill job " + jobId + " received from " + callerUGI + " at " + Server.getRemoteAddress(); LOG.info(message); verifyAndGetJob(jobId, JobACL.MODIFY_JOB, false); appContext.getEventHandler().handle( new JobDiagnosticsUpdateEvent(jobId, message)); appContext.getEventHandler().handle( new JobEvent(jobId, JobEventType.JOB_KILL)); KillJobResponse response = recordFactory.newRecordInstance(KillJobResponse.class); return response; }
@SuppressWarnings("unchecked") @Override public KillTaskResponse killTask(KillTaskRequest request) throws IOException { TaskId taskId = request.getTaskId(); UserGroupInformation callerUGI = UserGroupInformation.getCurrentUser(); String message = "Kill task " + taskId + " received from " + callerUGI + " at " + Server.getRemoteAddress(); LOG.info(message); verifyAndGetTask(taskId, JobACL.MODIFY_JOB); appContext.getEventHandler().handle( new TaskEvent(taskId, TaskEventType.T_KILL)); KillTaskResponse response = recordFactory.newRecordInstance(KillTaskResponse.class); return response; }
@SuppressWarnings("unchecked") @Override public KillTaskAttemptResponse killTaskAttempt( KillTaskAttemptRequest request) throws IOException { TaskAttemptId taskAttemptId = request.getTaskAttemptId(); UserGroupInformation callerUGI = UserGroupInformation.getCurrentUser(); String message = "Kill task attempt " + taskAttemptId + " received from " + callerUGI + " at " + Server.getRemoteAddress(); LOG.info(message); verifyAndGetAttempt(taskAttemptId, JobACL.MODIFY_JOB); appContext.getEventHandler().handle( new TaskAttemptDiagnosticsUpdateEvent(taskAttemptId, message)); appContext.getEventHandler().handle( new TaskAttemptEvent(taskAttemptId, TaskAttemptEventType.TA_KILL)); KillTaskAttemptResponse response = recordFactory.newRecordInstance(KillTaskAttemptResponse.class); return response; }
@SuppressWarnings("unchecked") @Override public FailTaskAttemptResponse failTaskAttempt( FailTaskAttemptRequest request) throws IOException { TaskAttemptId taskAttemptId = request.getTaskAttemptId(); UserGroupInformation callerUGI = UserGroupInformation.getCurrentUser(); String message = "Fail task attempt " + taskAttemptId + " received from " + callerUGI + " at " + Server.getRemoteAddress(); LOG.info(message); verifyAndGetAttempt(taskAttemptId, JobACL.MODIFY_JOB); appContext.getEventHandler().handle( new TaskAttemptDiagnosticsUpdateEvent(taskAttemptId, message)); appContext.getEventHandler().handle( new TaskAttemptEvent(taskAttemptId, TaskAttemptEventType.TA_FAILMSG)); FailTaskAttemptResponse response = recordFactory. newRecordInstance(FailTaskAttemptResponse.class); return response; }
@Override public GetTaskReportsResponse getTaskReports( GetTaskReportsRequest request) throws IOException { JobId jobId = request.getJobId(); TaskType taskType = request.getTaskType(); GetTaskReportsResponse response = recordFactory.newRecordInstance(GetTaskReportsResponse.class); Job job = verifyAndGetJob(jobId, JobACL.VIEW_JOB, true); Collection<Task> tasks = job.getTasks(taskType).values(); LOG.info("Getting task report for " + taskType + " " + jobId + ". Report-size will be " + tasks.size()); // Take lock to allow only one call, otherwise heap will blow up because // of counters in the report when there are multiple callers. synchronized (getTaskReportsLock) { for (Task task : tasks) { response.addTaskReport(task.getReport()); } } return response; }
/** * Test method 'job'. Should print message about error or set JobPage class for rendering */ @Test public void testGetJob() { when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(false); appController.job(); verify(appController.response()).setContentType(MimeType.TEXT); assertEquals( "Access denied: User user does not have permission to view job job_01_01", appController.getData()); when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(true); appController.getProperty().remove(AMParams.JOB_ID); appController.job(); assertEquals( "Access denied: User user does not have permission to view job job_01_01Bad Request: Missing job ID", appController.getData()); appController.getProperty().put(AMParams.JOB_ID, "job_01_01"); appController.job(); assertEquals(JobPage.class, appController.getClazz()); }
/** * Test method 'jobCounters'. Should print message about error or set CountersPage class for rendering */ @Test public void testGetJobCounters() { when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(false); appController.jobCounters(); verify(appController.response()).setContentType(MimeType.TEXT); assertEquals( "Access denied: User user does not have permission to view job job_01_01", appController.getData()); when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(true); appController.getProperty().remove(AMParams.JOB_ID); appController.jobCounters(); assertEquals( "Access denied: User user does not have permission to view job job_01_01Bad Request: Missing job ID", appController.getData()); appController.getProperty().put(AMParams.JOB_ID, "job_01_01"); appController.jobCounters(); assertEquals(CountersPage.class, appController.getClazz()); }
/** * Test method 'taskCounters'. Should print message about error or set CountersPage class for rendering */ @Test public void testGetTaskCounters() { when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(false); appController.taskCounters(); verify(appController.response()).setContentType(MimeType.TEXT); assertEquals( "Access denied: User user does not have permission to view job job_01_01", appController.getData()); when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(true); appController.getProperty().remove(AMParams.TASK_ID); appController.taskCounters(); assertEquals( "Access denied: User user does not have permission to view job job_01_01missing task ID", appController.getData()); appController.getProperty().put(AMParams.TASK_ID, "task_01_01_m01_01"); appController.taskCounters(); assertEquals(CountersPage.class, appController.getClazz()); }
/** * Construct the jobACLs from the configuration so that they can be kept in * the memory. If authorization is disabled on the JT, nothing is constructed * and an empty map is returned. * * @return JobACL to AccessControlList map. */ public Map<JobACL, AccessControlList> constructJobACLs(Configuration conf) { Map<JobACL, AccessControlList> acls = new HashMap<JobACL, AccessControlList>(); // Don't construct anything if authorization is disabled. if (!areACLsEnabled()) { return acls; } for (JobACL aclName : JobACL.values()) { String aclConfigName = aclName.getAclName(); String aclConfigured = conf.get(aclConfigName); if (aclConfigured == null) { // If ACLs are not configured at all, we grant no access to anyone. So // jobOwner and cluster administrator _only_ can do 'stuff' aclConfigured = " "; } acls.put(aclName, new AccessControlList(aclConfigured)); } return acls; }
/** * If authorization is enabled, checks whether the user (in the callerUGI) * is authorized to perform the operation specified by 'jobOperation' on * the job by checking if the user is jobOwner or part of job ACL for the * specific job operation. * <ul> * <li>The owner of the job can do any operation on the job</li> * <li>For all other users/groups job-acls are checked</li> * </ul> * @param callerUGI * @param jobOperation * @param jobOwner * @param jobACL */ public boolean checkAccess(UserGroupInformation callerUGI, JobACL jobOperation, String jobOwner, AccessControlList jobACL) { if (LOG.isDebugEnabled()) { LOG.debug("checkAccess job acls, jobOwner: " + jobOwner + " jobacl: " + jobOperation.toString() + " user: " + callerUGI.getShortUserName()); } String user = callerUGI.getShortUserName(); if (!areACLsEnabled()) { return true; } // Allow Job-owner for any operation on the job if (isMRAdmin(callerUGI) || user.equals(jobOwner) || jobACL.isUserAllowed(callerUGI)) { return true; } return false; }
@Test public void testClusterAdmins() { Map<JobACL, AccessControlList> tmpJobACLs = new HashMap<JobACL, AccessControlList>(); Configuration conf = new Configuration(); String jobOwner = "testuser"; conf.set(JobACL.VIEW_JOB.getAclName(), jobOwner); conf.set(JobACL.MODIFY_JOB.getAclName(), jobOwner); conf.setBoolean(MRConfig.MR_ACLS_ENABLED, true); String clusterAdmin = "testuser2"; conf.set(MRConfig.MR_ADMINS, clusterAdmin); JobACLsManager aclsManager = new JobACLsManager(conf); tmpJobACLs = aclsManager.constructJobACLs(conf); final Map<JobACL, AccessControlList> jobACLs = tmpJobACLs; UserGroupInformation callerUGI = UserGroupInformation.createUserForTesting( clusterAdmin, new String[] {}); // cluster admin should have access boolean val = aclsManager.checkAccess(callerUGI, JobACL.VIEW_JOB, jobOwner, jobACLs.get(JobACL.VIEW_JOB)); assertTrue("cluster admin should have view access", val); val = aclsManager.checkAccess(callerUGI, JobACL.MODIFY_JOB, jobOwner, jobACLs.get(JobACL.MODIFY_JOB)); assertTrue("cluster admin should have modify access", val); }
@Test public void testAclsOff() { Map<JobACL, AccessControlList> tmpJobACLs = new HashMap<JobACL, AccessControlList>(); Configuration conf = new Configuration(); String jobOwner = "testuser"; conf.set(JobACL.VIEW_JOB.getAclName(), jobOwner); conf.setBoolean(MRConfig.MR_ACLS_ENABLED, false); String noAdminUser = "testuser2"; JobACLsManager aclsManager = new JobACLsManager(conf); tmpJobACLs = aclsManager.constructJobACLs(conf); final Map<JobACL, AccessControlList> jobACLs = tmpJobACLs; UserGroupInformation callerUGI = UserGroupInformation.createUserForTesting( noAdminUser, new String[] {}); // acls off so anyone should have access boolean val = aclsManager.checkAccess(callerUGI, JobACL.VIEW_JOB, jobOwner, jobACLs.get(JobACL.VIEW_JOB)); assertTrue("acls off so anyone should have access", val); }
@Test public void testGroups() { Map<JobACL, AccessControlList> tmpJobACLs = new HashMap<JobACL, AccessControlList>(); Configuration conf = new Configuration(); String jobOwner = "testuser"; conf.set(JobACL.VIEW_JOB.getAclName(), jobOwner); conf.setBoolean(MRConfig.MR_ACLS_ENABLED, true); String user = "testuser2"; String adminGroup = "adminGroup"; conf.set(MRConfig.MR_ADMINS, " " + adminGroup); JobACLsManager aclsManager = new JobACLsManager(conf); tmpJobACLs = aclsManager.constructJobACLs(conf); final Map<JobACL, AccessControlList> jobACLs = tmpJobACLs; UserGroupInformation callerUGI = UserGroupInformation.createUserForTesting( user, new String[] {adminGroup}); // acls off so anyone should have access boolean val = aclsManager.checkAccess(callerUGI, JobACL.VIEW_JOB, jobOwner, jobACLs.get(JobACL.VIEW_JOB)); assertTrue("user in admin group should have access", val); }
/** * Test method 'taskCounters'. Should print message about error or set CountersPage class for rendering */ @Test public void testGetTaskCounters() { when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(false); appController.taskCounters(); verify(appController.response()).setContentType(MimeType.TEXT); assertEquals( "Access denied: User user does not have permission to view job job_01_01", appController.getData()); when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class))) .thenReturn(true); appController.getProperty().remove(AMParams.TASK_ID); appController.taskCounters(); assertEquals( "Access denied: User user does not have permission to view job job_01_01missing task ID", appController.getData()); appController.getProperty().put(AMParams.TASK_ID, taskId); appController.taskCounters(); assertEquals(CountersPage.class, appController.getClazz()); }
/** * check for job access. * @param job the job that is being accessed * @return True if the requesting user has permission to view the job */ boolean checkAccess(Job job) { String remoteUser = request().getRemoteUser(); UserGroupInformation callerUGI = null; if (remoteUser != null) { callerUGI = UserGroupInformation.createRemoteUser(remoteUser); } if (callerUGI != null && !job.checkAccess(callerUGI, JobACL.VIEW_JOB)) { return false; } return true; }