All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tez.common.security.ACLManager Maven / Gradle / Ivy

There is a newer version: 0.10.4
Show newest version
/**
 * 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.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.tez.dag.api.TezConfiguration;
import org.apache.tez.dag.api.records.DAGProtos.ACLInfo;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;

/**
 * Class to manage ACLs for the Tez AM and DAGs and provides functionality to check whether
 * a user is authorized to take certain actions.
 */
@Private
public class ACLManager {
  public static final String WILDCARD_ACL_VALUE = "*";

  private final String dagUser;
  private final String amUser;
  private final Map> users;
  private final Map> groups;
  private final boolean aclsEnabled;

  public ACLManager(String amUser) {
    this(amUser, new Configuration(false));
  }

  public ACLManager(String amUser, Configuration conf) {
    this.amUser = amUser;
    this.dagUser = null;
    this.users = new HashMap>();
    this.groups = new HashMap>();
    aclsEnabled = conf.getBoolean(TezConfiguration.TEZ_AM_ACLS_ENABLED,
        TezConfiguration.TEZ_AM_ACLS_ENABLED_DEFAULT);
    if (!aclsEnabled) {
      return;
    }
    ACLConfigurationParser parser = new ACLConfigurationParser(conf);
    if (parser.getAllowedUsers() != null) {
      this.users.putAll(parser.getAllowedUsers());
    }
    if (parser.getAllowedGroups() != null) {
      this.groups.putAll(parser.getAllowedGroups());
    }
  }

  public ACLManager(ACLManager amACLManager, String dagUser, ACLInfo aclInfo) {
    this.amUser = amACLManager.amUser;
    this.dagUser = dagUser;
    this.users = amACLManager.users;
    this.groups = amACLManager.groups;
    this.aclsEnabled = amACLManager.aclsEnabled;
    if (!aclsEnabled) {
      return;
    }
    if (aclInfo.getUsersWithViewAccessCount() > 0) {
      this.users.put(ACLType.DAG_VIEW_ACL,
          Sets.newLinkedHashSet(aclInfo.getUsersWithViewAccessList()));
    }
    if (aclInfo.getUsersWithModifyAccessCount() > 0) {
      this.users.put(ACLType.DAG_MODIFY_ACL,
          Sets.newLinkedHashSet(aclInfo.getUsersWithModifyAccessList()));
    }
    if (aclInfo.getGroupsWithViewAccessCount() > 0) {
      this.groups.put(ACLType.DAG_VIEW_ACL,
          Sets.newLinkedHashSet(aclInfo.getGroupsWithViewAccessList()));
    }
    if (aclInfo.getGroupsWithModifyAccessCount() > 0) {
      this.groups.put(ACLType.DAG_MODIFY_ACL,
          Sets.newLinkedHashSet(aclInfo.getGroupsWithModifyAccessList()));
    }
  }

  public boolean isAclsEnabled() {
    return aclsEnabled;
  }

  @VisibleForTesting
  boolean checkAccess(UserGroupInformation ugi, ACLType aclType) {

    if (!aclsEnabled) {
      return true;
    }

    String user = ugi.getShortUserName();
    if (amUser.equals(user)) {
      return true;
    }
    if (EnumSet.of(ACLType.DAG_MODIFY_ACL, ACLType.DAG_VIEW_ACL).contains(aclType)) {
      if (dagUser != null && dagUser.equals(user)) {
        return true;
      }
    }
    if (users != null && !users.isEmpty()) {
      Set set = users.get(aclType);
      if (set != null) {
        if (set.contains(WILDCARD_ACL_VALUE)) {
          return true;
        }
        if (set.contains(user)) {
          return true;
        }
      }
    }

    Collection userGroups = Arrays.asList(ugi.getGroupNames());
    if (userGroups != null && !userGroups.isEmpty()
        && groups != null && !groups.isEmpty()) {
      Set set = groups.get(aclType);
      if (set != null) {
        for (String userGrp : userGroups) {
          if (set.contains(userGrp)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  public boolean checkAMViewAccess(UserGroupInformation ugi) {
    return checkAccess(ugi, ACLType.AM_VIEW_ACL)
        || checkAccess(ugi, ACLType.YARN_ADMIN_ACL);
  }

  public boolean checkAMModifyAccess(UserGroupInformation ugi) {
    return checkAccess(ugi, ACLType.AM_MODIFY_ACL)
        || checkAccess(ugi, ACLType.YARN_ADMIN_ACL);
  }

  public boolean checkDAGViewAccess(UserGroupInformation ugi) {
    return checkAccess(ugi, ACLType.AM_VIEW_ACL)
        || checkAccess(ugi, ACLType.DAG_VIEW_ACL)
        || checkAccess(ugi, ACLType.YARN_ADMIN_ACL);
  }

  public boolean checkDAGModifyAccess(UserGroupInformation ugi) {
    return checkAccess(ugi, ACLType.AM_MODIFY_ACL)
        || checkAccess(ugi, ACLType.DAG_MODIFY_ACL)
        || checkAccess(ugi, ACLType.YARN_ADMIN_ACL);
  }

  public Map toYARNACls() {
    Map acls = new HashMap(2);
    if (!this.aclsEnabled) {
      acls.put(ApplicationAccessType.VIEW_APP, "*");
      acls.put(ApplicationAccessType.MODIFY_APP, "*");
      return acls;
    }
    acls.put(ApplicationAccessType.VIEW_APP, amUser);
    acls.put(ApplicationAccessType.MODIFY_APP, amUser);
    boolean viewAclsWildCard = false;
    boolean modifyAclsWildCard = false;
    if (users != null && !users.isEmpty()) {
      for (Entry> entry : users.entrySet()) {
        if (entry.getKey().equals(ACLType.AM_VIEW_ACL)) {
          if (entry.getValue().contains(WILDCARD_ACL_VALUE)) {
            acls.put(ApplicationAccessType.VIEW_APP, "*");
            viewAclsWildCard = true;
            continue;
          } else if (!entry.getValue().isEmpty()) {
            String aclsStr = acls.get(ApplicationAccessType.VIEW_APP);
            String commaSepList = toCommaSeparatedString(entry.getValue());
            if (!commaSepList.isEmpty()) {
              aclsStr += "," + commaSepList;
            }
            acls.put(ApplicationAccessType.VIEW_APP, aclsStr);
          }
        } else if (entry.getKey().equals(ACLType.AM_MODIFY_ACL)) {
          if (entry.getValue().contains(WILDCARD_ACL_VALUE)) {
            acls.put(ApplicationAccessType.MODIFY_APP, "*");
            modifyAclsWildCard = true;
            continue;
          } else if (!entry.getValue().isEmpty()) {
            String aclsStr = acls.get(ApplicationAccessType.MODIFY_APP);
            String commaSepList = toCommaSeparatedString(entry.getValue());
            if (!commaSepList.isEmpty()) {
              aclsStr += "," + commaSepList;
            }
            acls.put(ApplicationAccessType.MODIFY_APP, aclsStr);
          }
        }
      }
    }
    if (groups != null && !groups.isEmpty()) {
      for (Entry> entry : groups.entrySet()) {
        if (entry.getKey().equals(ACLType.AM_VIEW_ACL)
          && !viewAclsWildCard && !entry.getValue().isEmpty()) {
          // Append groups only if wild card not set
          String aclsStr = acls.containsKey(ApplicationAccessType.VIEW_APP) ?
              acls.get(ApplicationAccessType.VIEW_APP) : "";
          aclsStr += " " + toCommaSeparatedString(entry.getValue());
          acls.put(ApplicationAccessType.VIEW_APP, aclsStr);
        } else if (entry.getKey().equals(ACLType.AM_MODIFY_ACL)
            && !modifyAclsWildCard && !entry.getValue().isEmpty()) {
          // Append groups only if wild card not set
          String aclsStr = acls.containsKey(ApplicationAccessType.MODIFY_APP) ?
              acls.get(ApplicationAccessType.MODIFY_APP) : "";
          aclsStr += " " + toCommaSeparatedString(entry.getValue());
          acls.put(ApplicationAccessType.MODIFY_APP, aclsStr);
        }
      }
    }
    return acls;
  }

  public static String toCommaSeparatedString(Collection collection) {
    StringBuilder sb = new StringBuilder();
    boolean first = true;
    for (String s : collection) {
      if (!first) {
        sb.append(",");
      } else {
        first = false;
      }
      sb.append(s);
    }
    return sb.toString();
  }
}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy