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
This commit is contained in:
Siddharth Seth 2012-02-29 20:48:09 +00:00
parent 7ae04652a6
commit 3cbb9d20d0
6 changed files with 171 additions and 7 deletions

View File

@ -223,6 +223,9 @@ Release 0.23.2 - UNRELEASED
MAPREDUCE-3920. Revise yarn default port number selection MAPREDUCE-3920. Revise yarn default port number selection
(Dave Thompson via tgraves) (Dave Thompson via tgraves)
MAPREDUCE-3903. Add support for mapreduce admin users. (Thomas Graves via
sseth)
Release 0.23.1 - 2012-02-17 Release 0.23.1 - 2012-02-17
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -20,6 +20,8 @@
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.JobACL; import org.apache.hadoop.mapreduce.JobACL;
@ -31,9 +33,12 @@
@InterfaceAudience.Private @InterfaceAudience.Private
public class JobACLsManager { public class JobACLsManager {
static final Log LOG = LogFactory.getLog(JobACLsManager.class);
Configuration conf; Configuration conf;
private final AccessControlList adminAcl;
public JobACLsManager(Configuration conf) { public JobACLsManager(Configuration conf) {
adminAcl = new AccessControlList(conf.get(MRConfig.MR_ADMINS, " "));
this.conf = conf; this.conf = conf;
} }
@ -71,6 +76,18 @@ public Map<JobACL, AccessControlList> constructJobACLs(Configuration conf) {
return acls; 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) * If authorization is enabled, checks whether the user (in the callerUGI)
* is authorized to perform the operation specified by 'jobOperation' on * is authorized to perform the operation specified by 'jobOperation' on
@ -89,13 +106,18 @@ public Map<JobACL, AccessControlList> constructJobACLs(Configuration conf) {
public boolean checkAccess(UserGroupInformation callerUGI, public boolean checkAccess(UserGroupInformation callerUGI,
JobACL jobOperation, String jobOwner, AccessControlList jobACL) { 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(); String user = callerUGI.getShortUserName();
if (!areACLsEnabled()) { if (!areACLsEnabled()) {
return true; return true;
} }
// Allow Job-owner for any operation on the job // Allow Job-owner for any operation on the job
if (user.equals(jobOwner) if (isMRAdmin(callerUGI)
|| user.equals(jobOwner)
|| jobACL.isUserAllowed(callerUGI)) { || jobACL.isUserAllowed(callerUGI)) {
return true; return true;
} }

View File

@ -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<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 testClusterNoAdmins() {
Map<JobACL, AccessControlList> tmpJobACLs = new HashMap<JobACL, AccessControlList>();
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<JobACL, AccessControlList> 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<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);
}
}

View File

@ -192,7 +192,6 @@ public Job run() throws Exception {
throw RPCUtil.getRemoteException("Unknown job " + jobID); throw RPCUtil.getRemoteException("Unknown job " + jobID);
} }
JobACL operation = JobACL.VIEW_JOB; JobACL operation = JobACL.VIEW_JOB;
//TODO disable check access for now.
checkAccess(job, operation); checkAccess(job, operation);
return job; return job;
} }
@ -324,9 +323,7 @@ public GetDelegationTokenResponse getDelegationToken(
private void checkAccess(Job job, JobACL jobOperation) private void checkAccess(Job job, JobACL jobOperation)
throws YarnRemoteException { throws YarnRemoteException {
if (!UserGroupInformation.isSecurityEnabled()) {
return;
}
UserGroupInformation callerUGI; UserGroupInformation callerUGI;
try { try {
callerUGI = UserGroupInformation.getCurrentUser(); callerUGI = UserGroupInformation.getCurrentUser();

View File

@ -140,7 +140,7 @@ public class YarnConfiguration extends Configuration {
/** Are acls enabled.*/ /** Are acls enabled.*/
public static final String YARN_ACL_ENABLE = public static final String YARN_ACL_ENABLE =
YARN_PREFIX + "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.*/ /** ACL of who can be admin of YARN cluster.*/
public static final String YARN_ADMIN_ACL = public static final String YARN_ADMIN_ACL =

View File

@ -185,7 +185,7 @@ Hadoop MapReduce Next Generation - Cluster Setup
*-------------------------+-------------------------+------------------------+ *-------------------------+-------------------------+------------------------+
| <<<yarn.acl.enable>>> | | | | <<<yarn.acl.enable>>> | | |
| | <<<true>>> / <<<false>>> | | | | <<<true>>> / <<<false>>> | |
| | | Enable ACLs? Defaults to <true>. | | | | Enable ACLs? Defaults to <false>. |
*-------------------------+-------------------------+------------------------+ *-------------------------+-------------------------+------------------------+
| <<<yarn.admin.acl>>> | | | | <<<yarn.admin.acl>>> | | |
| | Admin ACL | | | | Admin ACL | |