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