/** * 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.tez.common.security; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.hadoop.classification.InterfaceAudience.Private; import org.apache.hadoop.classification.InterfaceAudience.Public; import org.apache.hadoop.conf.Configuration; import org.apache.tez.dag.api.TezConfiguration; import org.apache.tez.dag.api.TezConstants; import com.google.common.collect.ImmutableMap; /** * Access controls for the DAG */ @Public public class DAGAccessControls { private final Set<String> usersWithViewACLs; private final Set<String> usersWithModifyACLs; private final Set<String> groupsWithViewACLs; private final Set<String> groupsWithModifyACLs; public DAGAccessControls() { this.usersWithViewACLs = new HashSet<String>(); this.usersWithModifyACLs = new HashSet<String>(); this.groupsWithViewACLs = new HashSet<String>(); this.groupsWithModifyACLs = new HashSet<String>(); } /** * Helper API to support YARN and MapReduce format for specifying users and groups. * Format supports a comma-separated list of users and groups with the users and groups separated * by whitespace. e.g. "user1,user2 group1,group2" * If the value specified is "*", all users are allowed to do the operation. * @param viewACLsStr * @param modifyACLsStr */ public DAGAccessControls(String viewACLsStr, String modifyACLsStr) { final Configuration conf = new Configuration(false); conf.set(TezConstants.TEZ_DAG_VIEW_ACLS, (viewACLsStr != null ? viewACLsStr : "")); conf.set(TezConstants.TEZ_DAG_MODIFY_ACLS, (modifyACLsStr != null ? modifyACLsStr : "")); ACLConfigurationParser parser = new ACLConfigurationParser(conf, true); this.usersWithViewACLs = new HashSet<String>(); this.usersWithModifyACLs = new HashSet<String>(); this.groupsWithViewACLs = new HashSet<String>(); this.groupsWithModifyACLs = new HashSet<String>(); Map<ACLType, Set<String>> allowedUsers = parser.getAllowedUsers(); Map<ACLType, Set<String>> allowedGroups = parser.getAllowedGroups(); if (allowedUsers.containsKey(ACLType.DAG_VIEW_ACL)) { this.usersWithViewACLs.addAll(allowedUsers.get(ACLType.DAG_VIEW_ACL)); } if (allowedUsers.containsKey(ACLType.DAG_MODIFY_ACL)) { this.usersWithModifyACLs.addAll(allowedUsers.get(ACLType.DAG_MODIFY_ACL)); } if (allowedGroups.containsKey(ACLType.DAG_VIEW_ACL)) { this.groupsWithViewACLs.addAll(allowedGroups.get(ACLType.DAG_VIEW_ACL)); } if (allowedGroups.containsKey(ACLType.DAG_MODIFY_ACL)) { this.groupsWithModifyACLs.addAll(allowedGroups.get(ACLType.DAG_MODIFY_ACL)); } } /** * Sets the list of users with view permissions on the DAG. If all users are allowed, * pass in a single entry "*" * @param users Set of users with view permissions * @return this object for further chained method calls */ public synchronized DAGAccessControls setUsersWithViewACLs(Collection<String> users) { this.usersWithViewACLs.clear(); this.usersWithViewACLs.addAll(users); return this; } /** * Sets the list of users with modify permissions on the DAG. If all users are allowed, * pass in a single entry "*" * @param users Set of users with modify permissions * @return this object for further chained method calls */ public synchronized DAGAccessControls setUsersWithModifyACLs(Collection<String> users) { this.usersWithModifyACLs.clear(); this.usersWithModifyACLs.addAll(users); return this; } /** * Sets the list of groups with view permissions on the DAG. * @param groups Set of groups with view permissions * @return this object for further chained method calls */ public synchronized DAGAccessControls setGroupsWithViewACLs(Collection<String> groups) { this.groupsWithViewACLs.clear(); this.groupsWithViewACLs.addAll(groups); return this; } /** * Sets the list of groups with modify permissions on the DAG. * @param groups Set of groups with modify permissions * @return this object for further chained method calls */ public synchronized DAGAccessControls setGroupsWithModifyACLs(Collection<String> groups) { this.groupsWithModifyACLs.clear(); this.groupsWithModifyACLs.addAll(groups); return this; } @Private public synchronized Set<String> getUsersWithViewACLs() { return Collections.unmodifiableSet(usersWithViewACLs); } @Private public synchronized Set<String> getUsersWithModifyACLs() { return Collections.unmodifiableSet(usersWithModifyACLs); } @Private public synchronized Set<String> getGroupsWithViewACLs() { return Collections.unmodifiableSet(groupsWithViewACLs); } @Private public synchronized Set<String> getGroupsWithModifyACLs() { return Collections.unmodifiableSet(groupsWithModifyACLs); } /** * Merge the dag acls with the AM acls in the configuration object. The config object will contain * the updated acls. * @param conf The AM config. */ @Private public synchronized void mergeIntoAmAcls(Configuration conf) { ACLConfigurationParser parser = new ACLConfigurationParser(conf, false); parser.addAllowedGroups(ImmutableMap.of( ACLType.AM_VIEW_ACL, groupsWithViewACLs, ACLType.AM_MODIFY_ACL, groupsWithModifyACLs)); parser.addAllowedUsers(ImmutableMap.of( ACLType.AM_VIEW_ACL, usersWithViewACLs, ACLType.AM_MODIFY_ACL, usersWithModifyACLs)); Set<String> viewUsers = parser.getAllowedUsers().get(ACLType.AM_VIEW_ACL); Set<String> viewGroups = parser.getAllowedGroups().get(ACLType.AM_VIEW_ACL); if (viewUsers.contains(ACLManager.WILDCARD_ACL_VALUE)) { conf.set(TezConfiguration.TEZ_AM_VIEW_ACLS, ACLManager.WILDCARD_ACL_VALUE); } else { String userList = ACLManager.toCommaSeparatedString(viewUsers); String groupList = ACLManager.toCommaSeparatedString(viewGroups); conf.set(TezConfiguration.TEZ_AM_VIEW_ACLS, userList + " " + groupList); } Set<String> modifyUsers = parser.getAllowedUsers().get(ACLType.AM_MODIFY_ACL); Set<String> modifyGroups = parser.getAllowedGroups().get(ACLType.AM_MODIFY_ACL); if (modifyUsers.contains(ACLManager.WILDCARD_ACL_VALUE)) { conf.set(TezConfiguration.TEZ_AM_MODIFY_ACLS, ACLManager.WILDCARD_ACL_VALUE); } else { String userList = ACLManager.toCommaSeparatedString(modifyUsers); String groupList = ACLManager.toCommaSeparatedString(modifyGroups); conf.set(TezConfiguration.TEZ_AM_MODIFY_ACLS, userList + " " + groupList); } } }