001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.security;
019
020import java.io.IOException;
021import java.util.Collection;
022import java.util.HashSet;
023import java.util.Set;
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.hbase.AuthUtil;
026import org.apache.yetus.audience.InterfaceAudience;
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029
030/**
031 * Keeps lists of superusers and super groups loaded from HBase configuration, checks if certain
032 * user is regarded as superuser.
033 */
034@InterfaceAudience.Private
035public final class Superusers {
036  private static final Logger LOG = LoggerFactory.getLogger(Superusers.class);
037
038  /** Configuration key for superusers */
039  public static final String SUPERUSER_CONF_KEY = "hbase.superuser"; // Not getting a name
040
041  private static Set<String> superUsers;
042  private static Set<String> superGroups;
043  private static User systemUser;
044
045  private Superusers() {
046  }
047
048  /**
049   * Should be called only once to pre-load list of super users and super groups from Configuration.
050   * This operation is idempotent.
051   * @param conf configuration to load users from
052   * @throws IOException           if unable to initialize lists of superusers or super groups
053   * @throws IllegalStateException if current user is null
054   */
055  public static void initialize(Configuration conf) throws IOException {
056    superUsers = new HashSet<>();
057    superGroups = new HashSet<>();
058    systemUser = User.getCurrent();
059
060    if (systemUser == null) {
061      throw new IllegalStateException("Unable to obtain the current user, "
062        + "authorization checks for internal operations will not work correctly!");
063    }
064
065    String currentUser = systemUser.getShortName();
066    LOG.trace("Current user name is {}", currentUser);
067    superUsers.add(currentUser);
068
069    String[] superUserList = conf.getStrings(SUPERUSER_CONF_KEY, new String[0]);
070    for (String name : superUserList) {
071      if (AuthUtil.isGroupPrincipal(name)) {
072        // Let's keep the '@' for distinguishing from user.
073        superGroups.add(name);
074      } else {
075        superUsers.add(name);
076      }
077    }
078  }
079
080  /**
081   * Check if the current user is a super user
082   * @return true if current user is a super user (whether as user running process, declared as
083   *         individual superuser or member of supergroup), false otherwise.
084   * @param user to check
085   * @throws IllegalStateException if lists of superusers/super groups haven't been initialized
086   *                               properly
087   */
088  public static boolean isSuperUser(User user) {
089    if (superUsers == null) {
090      throw new IllegalStateException(
091        "Super users/super groups lists" + " have not been initialized properly.");
092    }
093    if (user == null) {
094      throw new IllegalArgumentException("Null user passed for super user check");
095    }
096    if (superUsers.contains(user.getShortName())) {
097      return true;
098    }
099    for (String group : user.getGroupNames()) {
100      if (superGroups.contains(AuthUtil.toGroupEntry(group))) {
101        return true;
102      }
103    }
104    return false;
105  }
106
107  /**
108   * Check if the current user is a super user
109   * @return true if current user is a super user, false otherwise.
110   * @param user to check
111   */
112  public static boolean isSuperUser(String user) {
113    return superUsers.contains(user) || superGroups.contains(user);
114  }
115
116  public static Collection<String> getSuperUsers() {
117    return superUsers;
118  }
119
120  public static Collection<String> getSuperGroups() {
121    return superGroups;
122  }
123
124  public static User getSystemUser() {
125    return systemUser;
126  }
127}