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