在hdfs+mapred+impala+kerberos运行正常后,开始测试hive+kerberos。hive0.11之后开始支持kerberos的验证,hive主要有两种访问方式,一种方法是shell运行,即直接运行hive命令,另一种方法时启动hiveserver,然后通过jdbc或odbc进行验证,其中第二种方法可以通过hive0.11的beeline进行测试。
在使用hive shell运行时,主要遇到下面几个问题:
1.权限验证问题。
在hive操作hdfs数据的时候,权限是分为两层的,一个是hive层面的权限控制,主要是控制表的权限,一个是hdfs文件的权限控制,控制用户的读写操作。
表的相关权限主要是写在hive的元数据库中,主要是TBL_PRIVS表(控制表的权限)和DB_PRIVS 表(控制库的权限)。
在开启kerberos之后,传入hive的用户名是principal的全名,比如hdfs/gxxxx@KERBEROS_HADOOP,而hive权限表中的PRINCIPAL_NAME 字段是hdfs,会导致没有表的权限,虽然可以通过update表来更改相应的PRINCIPAL_NAME 的值,但是实际使用中缺乏可运维性。在hdfs层面,有一个user mapping的功能(由hadoop.security.auth_to_local参数控制),默认会把principal的全名进行map,转换为unix的用户名形式。
2.hook的问题。
由于hive有grant的bug,因此线上使用了hook来做用户验证,即执行grant语法是会判断当前用户是否是hdfs用户,如果不是则报错,主要的代码如下(老毕提供):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
import
java.util.HashSet;
import
org.apache.hadoop.hive.ql.parse.ASTNode;
import
org.apache.hadoop.hive.ql.parse.AbstractSemanticAnalyzerHook;
import
org.apache.hadoop.hive.ql.parse.HiveParser;
import
org.apache.hadoop.hive.ql.parse.HiveSemanticAnalyzerHookContext;
import
org.apache.hadoop.hive.ql.parse.SemanticException;
import
org.apache.hadoop.hive.ql.session.SessionState;
import
org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory;
public
class
AuthHook
extends
AbstractSemanticAnalyzerHook {
static
final
private
Log LOG = LogFactory.getLog(AuthHook.
class
.getName());
private
static
HashSet<String> adminlist =
new
HashSet<String>() {
{add(
"hdfs"
);}
};
private
static
String adminstr =
"hdfs"
;
@Override
public
ASTNode preAnalyze(HiveSemanticAnalyzerHookContext context,
ASTNode ast)
throws
SemanticException {
switch
(ast.getToken().getType()) {
case
HiveParser.TOK_CREATEDATABASE:
case
HiveParser.TOK_DROPDATABASE:
case
HiveParser.TOK_CREATEROLE:
case
HiveParser.TOK_DROPROLE:
case
HiveParser.TOK_GRANT:
case
HiveParser.TOK_REVOKE:
case
HiveParser.TOK_GRANT_ROLE:
case
HiveParser.TOK_REVOKE_ROLE:
String userName =
null
;
if
(SessionState.get() !=
null
&& SessionState.get().getAuthenticator() !=
null
) {
userName = SessionState.get().getAuthenticator().getUserName();
}
LOG.debug(
"authhook username = "
+userName);
if
(!adminlist.contains(userName.toLowerCase())) {
throw
new
SemanticException(
"User:"
+userName
+
" isn't ADMIN, please ask for "
+ adminstr +
"."
);
}
break
;
default
:
LOG.debug(
"AST type = "
+ast.getToken().getType());
break
;
}
return
ast;
}
}
|
其中获取当前传入的用户名是通过 SessionState.get().getAuthenticator().getUserName();
集成了kerberos之后,在实际使用中会报
FAILED: SemanticException User:hdfs/xxxxx@KERBEROS_HADOOP isn't ADMIN, please ask for hdfs.的错误。
这两个问题的解决,借鉴了点评的patch:
即把ql/src/java/org/apache/hadoop/hive/ql/security/HadoopDefaultAuthenticator.java
中的this.userName = ugi.getUserName();改为
this.userName = ShimLoader.getHadoopShims().getShortUserName(ugi);
本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1381334,如需转载请自行联系原作者