diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt index 367d5994704..df425619a5d 100644 --- a/hadoop-mapreduce-project/CHANGES.txt +++ b/hadoop-mapreduce-project/CHANGES.txt @@ -146,6 +146,9 @@ Release 0.23.2 - UNRELEASED MAPREDUCE-3920. Revise yarn default port number selection (Dave Thompson via tgraves) + MAPREDUCE-3903. Add support for mapreduce admin users. (Thomas Graves via + sseth) + Release 0.23.1 - 2012-02-17 NEW FEATURES diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/JobACLsManager.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/JobACLsManager.java index e1ce1b9b7eb..37633ab504a 100644 --- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/JobACLsManager.java +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/JobACLsManager.java @@ -20,6 +20,8 @@ package org.apache.hadoop.mapred; import java.util.HashMap; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.mapreduce.JobACL; @@ -31,9 +33,12 @@ import org.apache.hadoop.security.authorize.AccessControlList; @InterfaceAudience.Private public class JobACLsManager { + static final Log LOG = LogFactory.getLog(JobACLsManager.class); Configuration conf; + private final AccessControlList adminAcl; public JobACLsManager(Configuration conf) { + adminAcl = new AccessControlList(conf.get(MRConfig.MR_ADMINS, " ")); this.conf = conf; } @@ -71,6 +76,18 @@ public class JobACLsManager { return acls; } + /** + * Is the calling user an admin for the mapreduce cluster + * i.e. member of mapreduce.cluster.administrators + * @return true, if user is an admin + */ + boolean isMRAdmin(UserGroupInformation callerUGI) { + if (adminAcl.isUserAllowed(callerUGI)) { + return true; + } + return false; + } + /** * If authorization is enabled, checks whether the user (in the callerUGI) * is authorized to perform the operation specified by 'jobOperation' on @@ -89,13 +106,18 @@ public class JobACLsManager { 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 (user.equals(jobOwner) + if (isMRAdmin(callerUGI) + || user.equals(jobOwner) || jobACL.isUserAllowed(callerUGI)) { return true; } diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapred/TestJobAclsManager.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapred/TestJobAclsManager.java new file mode 100644 index 00000000000..12eb1139f95 --- /dev/null +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapred/TestJobAclsManager.java @@ -0,0 +1,142 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.mapred; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.mapreduce.JobACL; +import org.apache.hadoop.mapreduce.MRConfig; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authorize.AccessControlList; +import org.junit.Test; + +/** + * Test the job acls manager + */ +public class TestJobAclsManager { + + @Test + public void testClusterAdmins() { + Map tmpJobACLs = new HashMap(); + 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 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 testClusterNoAdmins() { + Map tmpJobACLs = new HashMap(); + Configuration conf = new Configuration(); + String jobOwner = "testuser"; + conf.set(JobACL.VIEW_JOB.getAclName(), ""); + conf.setBoolean(MRConfig.MR_ACLS_ENABLED, true); + String noAdminUser = "testuser2"; + + JobACLsManager aclsManager = new JobACLsManager(conf); + tmpJobACLs = aclsManager.constructJobACLs(conf); + final Map jobACLs = tmpJobACLs; + + UserGroupInformation callerUGI = UserGroupInformation.createUserForTesting( + noAdminUser, new String[] {}); + // random user should not have access + boolean val = aclsManager.checkAccess(callerUGI, JobACL.VIEW_JOB, jobOwner, + jobACLs.get(JobACL.VIEW_JOB)); + assertFalse("random user should not have view access", val); + val = aclsManager.checkAccess(callerUGI, JobACL.MODIFY_JOB, jobOwner, + jobACLs.get(JobACL.MODIFY_JOB)); + assertFalse("random user should not have modify access", val); + + callerUGI = UserGroupInformation.createUserForTesting(jobOwner, + new String[] {}); + // Owner should have access + val = aclsManager.checkAccess(callerUGI, JobACL.VIEW_JOB, jobOwner, + jobACLs.get(JobACL.VIEW_JOB)); + assertTrue("owner should have view access", val); + val = aclsManager.checkAccess(callerUGI, JobACL.MODIFY_JOB, jobOwner, + jobACLs.get(JobACL.MODIFY_JOB)); + assertTrue("owner should have modify access", val); + } + + @Test + public void testAclsOff() { + Map tmpJobACLs = new HashMap(); + 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 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 tmpJobACLs = new HashMap(); + 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 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); + } +} diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java index ca933b4e104..2258bf90449 100644 --- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java @@ -192,7 +192,6 @@ public class HistoryClientService extends AbstractService { throw RPCUtil.getRemoteException("Unknown job " + jobID); } JobACL operation = JobACL.VIEW_JOB; - //TODO disable check access for now. checkAccess(job, operation); return job; } @@ -324,9 +323,7 @@ public class HistoryClientService extends AbstractService { private void checkAccess(Job job, JobACL jobOperation) throws YarnRemoteException { - if (!UserGroupInformation.isSecurityEnabled()) { - return; - } + UserGroupInformation callerUGI; try { callerUGI = UserGroupInformation.getCurrentUser(); diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index a831836f4b7..723a7ec67e2 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -140,7 +140,7 @@ public class YarnConfiguration extends Configuration { /** Are acls enabled.*/ public static final String YARN_ACL_ENABLE = YARN_PREFIX + "acl.enable"; - public static final boolean DEFAULT_YARN_ACL_ENABLE = true; + public static final boolean DEFAULT_YARN_ACL_ENABLE = false; /** ACL of who can be admin of YARN cluster.*/ public static final String YARN_ADMIN_ACL = diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ClusterSetup.apt.vm b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ClusterSetup.apt.vm index ab97dc5a8ee..abdbe894d9b 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ClusterSetup.apt.vm +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ClusterSetup.apt.vm @@ -185,7 +185,7 @@ Hadoop MapReduce Next Generation - Cluster Setup *-------------------------+-------------------------+------------------------+ | <<>> | | | | | <<>> / <<>> | | -| | | Enable ACLs? Defaults to . | +| | | Enable ACLs? Defaults to . | *-------------------------+-------------------------+------------------------+ | <<>> | | | | | Admin ACL | |