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   * @return true if current user is a super user (whether as user running process, declared as
082   *         individual superuser or member of supergroup), false otherwise.
083   * @param user to check
084   * @throws IllegalStateException if lists of superusers/super groups haven't been initialized
085   *                               properly
086   */
087  public static boolean isSuperUser(User user) {
088    if (superUsers == null) {
089      throw new IllegalStateException(
090        "Super users/super groups lists" + " have not been initialized properly.");
091    }
092    if (user == null) {
093      throw new IllegalArgumentException("Null user passed for super user check");
094    }
095    if (superUsers.contains(user.getShortName())) {
096      return true;
097    }
098    for (String group : user.getGroupNames()) {
099      if (superGroups.contains(AuthUtil.toGroupEntry(group))) {
100        return true;
101      }
102    }
103    return false;
104  }
105
106  /**
107   * @return true if current user is a super user, false otherwise.
108   * @param user to check
109   */
110  public static boolean isSuperUser(String user) {
111    return superUsers.contains(user) || superGroups.contains(user);
112  }
113
114  public static Collection<String> getSuperUsers() {
115    return superUsers;
116  }
117
118  public static Collection<String> getSuperGroups() {
119    return superGroups;
120  }
121
122  public static User getSystemUser() {
123    return systemUser;
124  }
125}