diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt index efbe0a3ed6..75f53fe51e 100644 --- a/hadoop-mapreduce-project/CHANGES.txt +++ b/hadoop-mapreduce-project/CHANGES.txt @@ -1792,6 +1792,9 @@ Release 0.23.0 - Unreleased MAPREDUCE-3264. mapreduce.job.user.name needs to be set automatically. (acmurthy via mahadev) + MAPREDUCE-3175. Add authorization to admin web-pages such as /stacks, /jmx + etc. (Jonathan Eagles via acmurthy) + Release 0.22.0 - Unreleased INCOMPATIBLE CHANGES diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AdminACLsManager.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AdminACLsManager.java new file mode 100644 index 0000000000..3a29450832 --- /dev/null +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AdminACLsManager.java @@ -0,0 +1,140 @@ +/** + * 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.yarn.security; + +import java.io.IOException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.authorize.AccessControlList; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.YarnException; + +public class AdminACLsManager { + + /** + * Log object for this class + */ + static Log LOG = LogFactory.getLog(AdminACLsManager.class); + + /** + * The current user at the time of object creation + */ + private final UserGroupInformation owner; + + /** + * Holds list of administrator users + */ + private final AccessControlList adminAcl; + + /** + * True if ACLs are enabled + * + * @see YarnConfiguration#YARN_ACL_ENABLE + * @see YarnConfiguration#DEFAULT_YARN_ACL_ENABLE + */ + private final boolean aclsEnabled; + + /** + * Constructs and initializes this AdminACLsManager + * + * @param conf configuration for this object to use + */ + public AdminACLsManager(Configuration conf) { + + this.adminAcl = new AccessControlList(conf.get( + YarnConfiguration.YARN_ADMIN_ACL, + YarnConfiguration.DEFAULT_YARN_ADMIN_ACL)); + try { + owner = UserGroupInformation.getCurrentUser(); + adminAcl.addUser(owner.getShortUserName()); + } catch (IOException e){ + LOG.warn("Could not add current user to admin:" + e); + throw new YarnException(e); + } + + aclsEnabled = conf.getBoolean(YarnConfiguration.YARN_ACL_ENABLE, + YarnConfiguration.DEFAULT_YARN_ACL_ENABLE); + } + + /** + * Returns the owner + * + * @return Current user at the time of object creation + */ + public UserGroupInformation getOwner() { + return owner; + } + + /** + * Returns whether ACLs are enabled + * + * @see YarnConfiguration#YARN_ACL_ENABLE + * @see YarnConfiguration#DEFAULT_YARN_ACL_ENABLE + * @return true if ACLs are enabled + */ + public boolean areACLsEnabled() { + return aclsEnabled; + } + + /** + * Returns the internal structure used to maintain administrator ACLs + * + * @return Structure used to maintain administrator access + */ + public AccessControlList getAdminAcl() { + return adminAcl; + } + + /** + * Returns whether the specified user/group is an administrator + * + * @param callerUGI user/group to to check + * @return true if the UserGroupInformation specified + * is a member of the access control list for administrators + */ + public boolean isAdmin(UserGroupInformation callerUGI) { + return adminAcl.isUserAllowed(callerUGI); + } + + /** + * Returns whether the specified user/group has administrator access + * + * @param callerUGI user/group to to check + * @return true if the UserGroupInformation specified + * is a member of the access control list for administrators + * and ACLs are enabled for this cluster + * + * @see #getAdminAcl + * @see #areACLsEnabled + */ + public boolean checkAccess(UserGroupInformation callerUGI) { + + // Any user may perform this operation if authorization is not enabled + if (!areACLsEnabled()) { + return true; + } + + // Administrators may perform any operation + return isAdmin(callerUGI); + } +} diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java index 9518e0f630..42e4ce4d7a 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java @@ -31,6 +31,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.http.HttpServer; +import org.apache.hadoop.yarn.security.AdminACLsManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -178,7 +179,7 @@ public void setup() { } HttpServer server = new HttpServer(name, bindAddress, port, findPort, conf, - webapp.getServePathSpecs()); + new AdminACLsManager(conf).getAdminAcl(), null, webapp.getServePathSpecs()); for(ServletStruct struct: servlets) { server.addServlet(struct.name, struct.spec, struct.clazz); } diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java index f04e7ec403..af77f84c55 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/ApplicationACLsManager.java @@ -32,7 +32,7 @@ import org.apache.hadoop.security.authorize.AccessControlList; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationAccessType; -import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.security.AdminACLsManager; @InterfaceAudience.Private public class ApplicationACLsManager { @@ -41,20 +41,17 @@ public class ApplicationACLsManager { .getLog(ApplicationACLsManager.class); private final Configuration conf; - private final AccessControlList adminAcl; + private final AdminACLsManager adminAclsManager; private final ConcurrentMap> applicationACLS = new ConcurrentHashMap>(); public ApplicationACLsManager(Configuration conf) { this.conf = conf; - this.adminAcl = new AccessControlList(conf.get( - YarnConfiguration.YARN_ADMIN_ACL, - YarnConfiguration.DEFAULT_YARN_ADMIN_ACL)); + this.adminAclsManager = new AdminACLsManager(conf); } public boolean areACLsEnabled() { - return conf.getBoolean(YarnConfiguration.YARN_ACL_ENABLE, - YarnConfiguration.DEFAULT_YARN_ACL_ENABLE); + return adminAclsManager.areACLsEnabled(); } public void addApplication(ApplicationId appId, @@ -107,7 +104,7 @@ public boolean checkAccess(UserGroupInformation callerUGI, .get(applicationId).get(applicationAccessType); // Allow application-owner for any type of access on the application - if (this.adminAcl.isUserAllowed(callerUGI) + if (this.adminAclsManager.isAdmin(callerUGI) || user.equals(applicationOwner) || applicationACL.isUserAllowed(callerUGI)) { return true;