1、前言
前段时间,在升级Hive版本(从Hive1.1.0升级至Hive2.3.6)的过程中,遇到了权限兼容问题。
(升级相关请移步Hive1.1.0升级至2.3.6 踩坑记录)
Hive1.1.0使用的是AuthorizerV1而Hive2.3.6默认是AuthorizerV2,两者相差极大。
其中AuthorizerV2的权限验证极为严格,如果曾经使用V1鉴权想要使用V2的,需要修改部分代码,这是我提交的patch,供参考HIVE-22830
2、权限认证
v1和v2的权限授权和查询,在SQL语法上是通用的,因此我们不需要对Hive授权相关的系统做代码上的修改。
v1权限认证
(org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider
):官方文档
总共有ALL | ALTER | UPDATE | CREATE | DROP | INDEX | LOCK | SELECT | SHOW_DATABASE
这几种权限类型。
相关Hive操作所需要的权限如下表:
v2权限认证
(org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory
):官方文档
总共有INSERT | SELECT | UPDATE | DELETE | ALL
这几种类型的权限。
相关Hive操作所需要的权限如下表:
Y代表需要有该权限
Y+G代表不仅需要有改权限,还必须是能给别人赋权的权限(“WITH GRANT OPTION”)
来说说两者在一些细节上的区别:
1、v2的ALL
权限在mysql中会分成INSERT | SELECT | UPDATE | DELETE
来保存,而v1则是直接存ALL
。
2、v1对库授权,则用户/角色对该库下的所有表都有相应的权限,而v2必须对表一一授权。
3、v1如果需要删库/表,只需要拥有对应的drop权限即可,而v2如果需要删库/表,必须是该库/表的owner,这个owner可以是用户或者角色。
3、源码解析(Hive3.1版本)
在Hive SQL执行全过程源码解析中,介绍了Driver.compile中权限认证的入口:
接下来着重看下v2权限认证的实现:
如何判断是用v1或v2进行认证?
if (ss.isAuthorizationModeV2())
-> public boolean isAuthorizationModeV2(){
return getAuthorizationMode() == AuthorizationMode.V2;
}
--> public AuthorizationMode getAuthorizationMode(){
setupAuth();
// 判断在初始化操作setupAuth()后,authorizer是否为null
// 优先判断是否为v1
if(authorizer != null){
return AuthorizationMode.V1;
}else if(authorizerV2 != null){
return AuthorizationMode.V2;
}
}
setupAuth():
/**
* Setup authentication and authorization plugins for this session.
*/
private void setupAuth() {
// 已经被初始化了,直接返回
if (authenticator != null) {
// auth has been initialized
return;
}
try {
// 通过获取hive.security.authenticator.manager参数来决定authenticator
authenticator = HiveUtils.getAuthenticator(sessionConf,
HiveConf.ConfVars.HIVE_AUTHENTICATOR_MANAGER);
authenticator.setSessionState(this);
// 获取hive.security.authorization.manager参数,为权限验证实现类名
// 决定了使用v1还是v2
// Hive1默认v1:(org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider)
// Hive2及以后默认v2:(org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory)
String clsStr = HiveConf.getVar(sessionConf, HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER);
// 使用反射尝试实例化权限认证类对象
// 生成HiveAuthorizationProvider对象,v1
authorizer = HiveUtils.getAuthorizeProviderManager(sessionConf,
clsStr, authenticator, true);
if (authorizer == null) {
// if it was null, the new (V2) authorization plugin must be specified in
// config
// 实现和v1大致相同,使用反射尝试实例化权限认证类对象
HiveAuthorizerFactory authorizerFactory = HiveUtils.getAuthorizerFactory(sessionConf,
HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER);
HiveAuthzSessionContext.Builder authzContextBuilder = new HiveAuthzSessionContext.Builder();
authzContextBuilder.setClientType(isHiveServerQuery() ? CLIENT_TYPE.HIVESERVER2
: CLIENT_TYPE.HIVECLI);
authzContextBuilder.setSessionString(getSessionId());
// 生成HiveAuthorizer对象,v2
authorizerV2 = authorizerFactory.createHiveAuthorizer(new HiveMetastoreClientFactoryImpl(),
sessionConf, authenticator, authzContextBuilder.build());
setAuthorizerV2Config();
}
// create the create table grants with new config
createTableGrants = CreateTableAutomaticGrant.create(sessionConf);
} catch (