今天hive user maillist上有人问show current roles命令问题:
I am trying to run ‘Show current roles’ on Apache hive 0.13.1 but getting following error,hive> SHOW CURRENT ROLES;Error in role operation show_current_role on role name null, error message Unkown role operation show_current_roleFAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTaskCan someone tell me whether this command is supported on apache Hive 0.13.1 or not. If it is supported the what could be the issue.Any pointer would be really helpful.
在我的印象中,这个命令应该不存在才对。。手动运行了一下,果然报错,仔细看日志,可以看到命令是可以完成parse和analyzer阶段的,运行的时候才会报错,按我的理解,如果sql不支持的话应该在parse阶段就会出错
14/11/20 11:22:55 INFO ql.Driver: Starting command: show current roles14/11/20 11:22:55 INFO log.PerfLogger: 14/11/20 11:22:55 INFO log.PerfLogger:14/11/20 11:22:55 INFO log.PerfLogger: Error in role operation show_current_role on role name null, error message Unkown role operation show_current_role14/11/20 11:22:55 ERROR exec.Task: Error in role operation show_current_role on role name null, error message Unkown role operation show_current_roleFAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask14/11/20 11:22:55 ERROR ql.Driver: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask14/11/20 11:22:55 DEBUG ql.Driver: Shutting down query show current roles
根据堆栈信息,show current roles命令是由DDLTask执行的,看其具体实现:
private int roleDDL(RoleDDLDesc roleDDLDesc) throws HiveException, IOException { if(SessionState.get().isAuthorizationModeV2()){ return roleDDLV2(roleDDLDesc); //如果是v2的验证方式,调用roleDDLV2 }....
在roleDDLV2中可以看到show current role命令的处理:
private int roleDDLV2(RoleDDLDesc roleDDLDesc) throws HiveException, IOException { HiveAuthorizer authorizer = SessionState.get().getAuthorizerV2(); RoleDDLDesc.RoleOperation operation = roleDDLDesc.getOperation(); //call the appropriate hive authorizer function switch(operation){... case SHOW_CURRENT_ROLE: ListroleNames = authorizer.getCurrentRoleNames(); writeListToFileAfterSort(roleNames, roleDDLDesc.getResFile()); break;...
即show current role这个语法在v2里面支持,那么什么时候SessionState.get().isAuthorizationModeV2()为true呢?来看看SessionState类,isAuthorizationModeV2调用getAuthorizationMode,getAuthorizationMode调用setupAuth:
public AuthorizationMode getAuthorizationMode(){ setupAuth(); //调用setupAuth类设置authorizer和authorizerV2 if(authorizer != null){ return AuthorizationMode.V1; }else if(authorizerV2 != null){ return AuthorizationMode.V2; } //should not happen - this should not get called before this.start() is called throw new AssertionError("Authorization plugins not initialized!"); } public boolean isAuthorizationModeV2(){ return getAuthorizationMode() == AuthorizationMode.V2; }
如果要让AuthorizationMode.V2成立,需要让authorizer为null,authorizerV2不为null才可以,设置
authorizer和authorizerV2是在setupAuth方法中实现的: private HiveAuthorizationProvider authorizer; private HiveAuthorizer authorizerV2;... private void setupAuth() { if (authenticator != null) { // auth has been initialized return; } try {... authorizer = HiveUtils.getAuthorizeProviderManager(conf, HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER, authenticator, true); //hive.security.authorization.manager 默认为org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider if (authorizer == null) { //authorizer的值为null时,才可以有机会返回v2 // if it was null, the new authorization plugin must be specified in // config HiveAuthorizerFactory authorizerFactory = HiveUtils.getAuthorizerFactory(conf, HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER); authorizerV2 = authorizerFactory.createHiveAuthorizer(new HiveMetastoreClientFactoryImpl(), conf, authenticator); authorizerV2.applyAuthorizationConfigPolicy(conf); // create the create table grants with new config createTableGrants = CreateTableAutomaticGrant.create(conf); }..
因为hive.security.authorization.manager默认为org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider,所以为authorizer为V1,要想设置为v2,需要让HiveUtils.getAuthorizeProviderManager返回null
HiveUtils.getAuthorizeProviderManager中可以获取设置的authorizer的具体实现类
public static HiveAuthorizationProvider getAuthorizeProviderManager( Configuration conf, HiveConf.ConfVars authorizationProviderConfKey, HiveAuthenticationProvider authenticator, boolean nullIfOtherClass) throws HiveException { String clsStr = HiveConf.getVar(conf, authorizationProviderConfKey); //由hive.security.authorization.manager的设置获取类名 HiveAuthorizationProvider ret = null; try { Class cls = null; if (clsStr == null || clsStr.trim().equals("")) { //如果为null或者设置为空,则实现类为DefaultHiveAuthorizationProvider cls = DefaultHiveAuthorizationProvider.class; } else { Class configClass = Class.forName(clsStr, true, JavaUtils.getClassLoader()); //否则为具体的实现的类 if(nullIfOtherClass && !HiveAuthorizationProvider.class.isAssignableFrom(configClass) ){ //配置的类和HiveAuthorizationProvider类没有关系时,返回null return null; } cls = (Class )configClass; } if (cls != null) { ret = ReflectionUtils.newInstance(cls, conf); } } catch (Exception e) { throw new HiveException(e); } ret.setAuthenticator(authenticator); return ret; }
如果要想返回v2,需要让设置的authorize相关类必须实现HiveAuthorizerFactory接口,且不能实现HiveAuthorizationProvider接口
反馈如下:
Refer to the org.apache.Hadoop.hive.ql.exec.DDLTask.roleDDL function, AuthorizationMode doesn't support SHOW CURRENT ROLES statementBut AuthorizationModeV2 supports this:private int roleDDLV2(RoleDDLDesc roleDDLDesc) throws HiveException, IOException {……. case SHOW_CURRENT_ROLE: ListroleNames = authorizer.getCurrentRoleNames(); writeListToFileAfterSort(roleNames, roleDDLDesc.getResFile()); break;But by default,hive uses AuthorizationMode (because the default value of hive.security.authorization.manager isorg.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider,which means AuthorizationMode )If you want to use AuthorizationModeV2,you must use another authorization classwhich implements theorg.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory interfacebut not the org.apache.hadoop.hive.ql.security.authorization.HiveAuthorizationProvider interface