From 3cbb9d20d0bf9d4f28c64bd56c5b9c7dd70ed801 Mon Sep 17 00:00:00 2001 From: Siddharth Seth Date: Wed, 29 Feb 2012 20:48:09 +0000 Subject: [PATCH] MAPREDUCE-3903. Add support for mapreduce admin users. (Contributed by Thomas Graves) git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1295262 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-mapreduce-project/CHANGES.txt | 3 + .../apache/hadoop/mapred/JobACLsManager.java | 24 ++- .../hadoop/mapred/TestJobAclsManager.java | 142 ++++++++++++++++++ .../mapreduce/v2/hs/HistoryClientService.java | 5 +- .../hadoop/yarn/conf/YarnConfiguration.java | 2 +- .../src/site/apt/ClusterSetup.apt.vm | 2 +- 6 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/test/java/org/apache/hadoop/mapred/TestJobAclsManager.java diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt index 028f2328a81..6b286ea24c7 100644 --- a/hadoop-mapreduce-project/CHANGES.txt +++ b/hadoop-mapreduce-project/CHANGES.txt @@ -223,6 +223,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 INCOMPATIBLE CHANGES 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 @@ 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 @@ @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 Map constructJobACLs(Configuration conf) { 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 Map constructJobACLs(Configuration conf) { 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 Job run() throws Exception { 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 GetDelegationTokenResponse getDelegationToken( 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 | |