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.File;
021import java.io.IOException;
022import java.net.InetAddress;
023
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.fs.CommonConfigurationKeys;
026import org.apache.hadoop.hbase.HBaseConfiguration;
027import org.apache.hadoop.hbase.HBaseTestingUtility;
028import org.apache.hadoop.hbase.http.ssl.KeyStoreTestUtil;
029import org.apache.hadoop.hdfs.DFSConfigKeys;
030import org.apache.hadoop.http.HttpConfig;
031import org.apache.hadoop.yarn.conf.YarnConfiguration;
032import org.apache.yetus.audience.InterfaceAudience;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035import org.apache.hbase.thirdparty.com.google.common.base.Strings;
036import org.apache.hadoop.security.UserGroupInformation;
037
038@InterfaceAudience.Private
039public class HBaseKerberosUtils {
040  private static final Logger LOG = LoggerFactory.getLogger(HBaseKerberosUtils.class);
041
042  public static final String KRB_PRINCIPAL = "hbase.regionserver.kerberos.principal";
043  public static final String MASTER_KRB_PRINCIPAL = "hbase.master.kerberos.principal";
044  public static final String KRB_KEYTAB_FILE = "hbase.regionserver.keytab.file";
045
046  public static boolean isKerberosPropertySetted() {
047    String krbPrincipal = System.getProperty(KRB_PRINCIPAL);
048    String krbKeytab = System.getProperty(KRB_KEYTAB_FILE);
049    if (Strings.isNullOrEmpty(krbPrincipal) || Strings.isNullOrEmpty(krbKeytab)) {
050      return false;
051    }
052    return true;
053  }
054
055  public static void setPrincipalForTesting(String principal) {
056    setSystemProperty(KRB_PRINCIPAL, principal);
057  }
058
059  public static void setKeytabFileForTesting(String keytabFile) {
060    setSystemProperty(KRB_KEYTAB_FILE, keytabFile);
061  }
062
063  public static void setSystemProperty(String propertyName, String propertyValue) {
064    System.setProperty(propertyName, propertyValue);
065  }
066
067  public static String getKeytabFileForTesting() {
068    return System.getProperty(KRB_KEYTAB_FILE);
069  }
070
071  public static String getPrincipalForTesting() {
072    return System.getProperty(KRB_PRINCIPAL);
073  }
074
075  public static Configuration getConfigurationWoPrincipal() {
076    Configuration conf = HBaseConfiguration.create();
077    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
078    conf.set(User.HBASE_SECURITY_CONF_KEY, "kerberos");
079    conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
080    return conf;
081  }
082
083  public static Configuration getSecuredConfiguration() {
084    Configuration conf = HBaseConfiguration.create();
085    setSecuredConfiguration(conf);
086    return conf;
087  }
088
089  /**
090   * Set up configuration for a secure HDFS+HBase cluster.
091   * @param conf configuration object.
092   * @param servicePrincipal service principal used by NN, HM and RS.
093   * @param spnegoPrincipal SPNEGO principal used by NN web UI.
094   */
095  public static void setSecuredConfiguration(Configuration conf,
096      String servicePrincipal, String spnegoPrincipal) {
097    setPrincipalForTesting(servicePrincipal);
098    setSecuredConfiguration(conf);
099    setSecuredHadoopConfiguration(conf, spnegoPrincipal);
100  }
101
102  public static void setSecuredConfiguration(Configuration conf) {
103    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
104    conf.set(User.HBASE_SECURITY_CONF_KEY, "kerberos");
105    conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
106    conf.set(KRB_KEYTAB_FILE, System.getProperty(KRB_KEYTAB_FILE));
107    conf.set(KRB_PRINCIPAL, System.getProperty(KRB_PRINCIPAL));
108    conf.set(MASTER_KRB_PRINCIPAL, System.getProperty(KRB_PRINCIPAL));
109  }
110
111  private static void setSecuredHadoopConfiguration(Configuration conf,
112      String spnegoServerPrincipal) {
113    // if we drop support for hadoop-2.4.0 and hadoop-2.4.1,
114    // the following key should be changed.
115    // 1) DFS_NAMENODE_USER_NAME_KEY -> DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY
116    // 2) DFS_DATANODE_USER_NAME_KEY -> DFS_DATANODE_KERBEROS_PRINCIPAL_KEY
117    String serverPrincipal = System.getProperty(KRB_PRINCIPAL);
118    String keytabFilePath = System.getProperty(KRB_KEYTAB_FILE);
119    // HDFS
120    conf.set(DFSConfigKeys.DFS_NAMENODE_USER_NAME_KEY, serverPrincipal);
121    conf.set(DFSConfigKeys.DFS_NAMENODE_KEYTAB_FILE_KEY, keytabFilePath);
122    conf.set(DFSConfigKeys.DFS_DATANODE_USER_NAME_KEY, serverPrincipal);
123    conf.set(DFSConfigKeys.DFS_DATANODE_KEYTAB_FILE_KEY, keytabFilePath);
124    conf.setBoolean(DFSConfigKeys.DFS_BLOCK_ACCESS_TOKEN_ENABLE_KEY, true);
125    // YARN
126    conf.set(YarnConfiguration.RM_PRINCIPAL, KRB_PRINCIPAL);
127    conf.set(YarnConfiguration.NM_PRINCIPAL, KRB_PRINCIPAL);
128
129    if (spnegoServerPrincipal != null) {
130      conf.set(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY,
131          spnegoServerPrincipal);
132    }
133
134    conf.setBoolean("ignore.secure.ports.for.testing", true);
135
136    UserGroupInformation.setConfiguration(conf);
137  }
138
139  /**
140   * Set up SSL configuration for HDFS NameNode and DataNode.
141   * @param utility a HBaseTestingUtility object.
142   * @param clazz the caller test class.
143   * @throws Exception if unable to set up SSL configuration
144   */
145  public static void setSSLConfiguration(HBaseTestingUtility utility, Class clazz)
146      throws Exception {
147    Configuration conf = utility.getConfiguration();
148    conf.set(DFSConfigKeys.DFS_HTTP_POLICY_KEY, HttpConfig.Policy.HTTPS_ONLY.name());
149    conf.set(DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_KEY, "localhost:0");
150    conf.set(DFSConfigKeys.DFS_DATANODE_HTTPS_ADDRESS_KEY, "localhost:0");
151
152    File keystoresDir = new File(utility.getDataTestDir("keystore").toUri().getPath());
153    keystoresDir.mkdirs();
154    String sslConfDir = KeyStoreTestUtil.getClasspathDir(clazz);
155    KeyStoreTestUtil.setupSSLConfig(keystoresDir.getAbsolutePath(), sslConfDir, conf, false);
156  }
157
158  public static UserGroupInformation loginAndReturnUGI(Configuration conf, String username)
159      throws IOException {
160    String hostname = InetAddress.getLocalHost().getHostName();
161    String keyTabFileConfKey = "hbase." + username + ".keytab.file";
162    String keyTabFileLocation = conf.get(keyTabFileConfKey);
163    String principalConfKey = "hbase." + username + ".kerberos.principal";
164    String principal = org.apache.hadoop.security.SecurityUtil
165        .getServerPrincipal(conf.get(principalConfKey), hostname);
166    if (keyTabFileLocation == null || principal == null) {
167      LOG.warn("Principal or key tab file null for : " + principalConfKey + ", "
168          + keyTabFileConfKey);
169    }
170    UserGroupInformation ugi =
171        UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keyTabFileLocation);
172    return ugi;
173  }
174}