热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

hive任务提交的相关权限认证详析

最近在研究Hue,遇到一个问题,在HiveEditor写一个HQL,提交后会报权限错误,类似这样的Authorizationfailed:NoprivilegeSelectfoundforinputs{database:xxx,table:xxx,columnName:xxx}.Useshowgranttogetmoredetails.Hue的登录用户是hadoop,使用cli方

最近在研究Hue,遇到一个问题,在Hive Editor写一个HQL,提交后会报权限错误,类似这样的 Authorizationfailed:Noprivilege'Select'foundforinputs{database:xxx,table:xxx,columnName:xxx}.Useshowgranttogetmoredetails. Hue的登录用户是hadoop,使用cli方

最近在研究Hue,遇到一个问题,在Hive Editor写一个HQL,提交后会报权限错误,类似这样的

Authorization failed:No privilege 'Select' found for inputs {database:xxx, table:xxx, columnName:xxx}. Use show grant to get more details.

Hue的登录用户是hadoop,使用cli方式查询的时候,是没问题的,但是使用Hue连接HiveServer2的方式,就查询不了对应的表了,排除Hue的干扰,使用Beeline来连接HiveServer2,同样报权限的错误,堆栈信息如下图



wKiom1O1KT_jKAZdAAyGT2bPY6U498.jpg


根据堆栈信息大概梳理了下源码(只列出比较重要的代码),Hive提交SQL的权限验证流程如下

    Driver.compile(String command, boolean resetTaskIds){
      if (HiveConf.getBoolVar(conf,
          HiveConf.ConfVars.HIVE_AUTHORIZATION_ENABLED)) {
        try {
          perfLogger.PerfLogBegin(LOG, PerfLogger.DO_AUTHORIZATION);
          //进行权限校验
          doAuthorization(sem);
        }
     }
     Driver.doAuthorization(BaseSemanticAnalyzer sem){
        //判断op的操作类型为QUERY
        if (op.equals(HiveOperation.CREATETABLE_AS_SELECT)
              || op.equals(HiveOperation.QUERY)) {
            if (cols != null && cols.size() > 0) {
                //进行更具体的验证
                ss.getAuthorizer().authorize(tbl, null, cols,
                    op.getInputRequiredPrivileges(), null);
            }
         }
     }
     BitSetCheckedAuthorizationProvider.authorize(Table table, Partition part, List columns,Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv){
            //验证用户对DB和Table的权限
            authorizeUserDBAndTable(table, inputRequiredPriv, outputRequiredPriv,inputCheck,outputCheck)
            //验证用户对Table中column的权限
            for (String col : columns) {
                PrincipalPrivilegeSet partColumnPrivileges = hive_db
                      .get_privilege_set(HiveObjectType.COLUMN, table.getDbName(),table.getTableName(),partValues, col,this.getAuthenticator().getUserName(), this.getAuthenticator().getGroupNames());
                authorizePrivileges(partColumnPrivileges, inputRequiredPriv, inputCheck2,
                       outputRequiredPriv, outputCheck2);
            }
     }

Hive的权限验证首先会调用authorizeUserDBAndTable验证用户是否对访问的DB和Table有访问权限,对应到MetaStore的DB_PRIVS和TBL_PRIVS表,在进行验证的时候,会通过thrift与HiveMetaStore进程进行交互来获取MetaStore库中对应表的相关信息。如果用户对更大粒度的资源有访问权限,则会直接返回,不会再继续进行更细粒度的验证,也就是说如果用户对DB有相关的权限,则不会继续验证对Table和Column的访问权限。

查看了下DB_PRIVS表,hadoop用户对访问的数据库是有Select权限的,所以再传统CLI模式下访问是没有问题的。看上述代码也都是在预料之中,因为实际上CLI模式和HiveServer模式的权限验证是一套代码。决定remote debug下,进而发现this.getAuthenticator().getUserName()的值为hive,也即是启动HiveServer2的用户,而不是提交SQL的用户hadoop,顺藤摸瓜,找到了设置authenticator相关属性的代码

    SessionState.start(SessionState startSs) {
        //实例化默认的HadoopDefaultAuthenticator,方法内部,使用ReflectionUtils反射加载类的时候,进而调用了HadoopDefaultAuthenticator.setConf方法
        startSs.authenticator=HiveUtils.getAuthenticator(startSs.getConf(),HiveConf.ConfVars.HIVE_AUTHENTICATOR_MANAGER);
    }
    HadoopDefaultAuthenticator.setConf(Configuration conf){
        ugi = ShimLoader.getHadoopShims().getUGIForConf(conf);
    }
    HadoopShimsSecure.getUGIForConf(Configuration conf) throws IOException {
        return UserGroupInformation.getCurrentUser();
    }
    
UserGroupInformation.getCurrentUser() throws IOException {
    AccessControlContext cOntext= AccessController.getContext();
    Subject subject = Subject.getSubject(context);
    //HiveServer刚启动的时候,subject为空,调用getLoginUser
    if (subject == null || subject.getPrincipals(User.class).isEmpty()) {
      return getLoginUser();
    } else {
      return new UserGroupInformation(subject);
    }
  }
UserGroupInformation.getLoginUser() {
    if (loginUser == null) {
      try {
        Subject subject = new Subject();
        LoginContext login;
        if (isSecurityEnabled()) {
          login = newLoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
              subject, new HadoopConfiguration());
        } else {
          login = newLoginContext(HadoopConfiguration.SIMPLE_CONFIG_NAME, 
              subject, new HadoopConfiguration());
        }
        login.login();
        loginUser = new UserGroupInformation(subject);
        loginUser.setLogin(login);
        loginUser.setAuthenticationMethod(isSecurityEnabled() ?
                                          AuthenticationMethod.KERBEROS :
                                          AuthenticationMethod.SIMPLE);
        loginUser = new UserGroupInformation(login.getSubject());
        String fileLocation = System.getenv(HADOOP_TOKEN_FILE_LOCATION);
        if (fileLocation != null) {
          Credentials cred = Credentials.readTokenStorageFile(
              new File(fileLocation), conf);
          loginUser.addCredentials(cred);
        }
        loginUser.spawnAutoRenewalThreadForUserCreds();
      } catch (LoginException le) {
        LOG.debug("failure to login", le);
        throw new IOException("failure to login", le);
      }
      if (LOG.isDebugEnabled()) {
        LOG.debug("UGI loginUser:"+loginUser);
      }
    }
    return loginUser;
  }

HiveServer刚启动时第一次调用getLoginUser(),loginUser为空,接下来会创建LoginContext并调用其login方法,login方法最终会调用HadoopLoginModule的commit()方法。commit()方法的大致逻辑是这样的

1.如果使用了kerberos,则为kerberos登陆用户

2.如果kerberos用户为空并且没有开启security,则从系统环境变量中取HADOOP_USER_NAME的值

3.如果环境变量中没有设置HADOOP_USER_NAME,则使用系统用户,即启动HiveServer2进程的用户

后续使用的用户即为启动HiveServer2的用户,所以authenticator的UserName属性值即为hive。所以使用hive去查MetaStore的相关权限表的时候,查不到相关的信息,授权不通过。除非授予hive用户相关的权限。解决的办法要么为hive用户赋予相关的权限,可是这样,权限验证就失去了意义。更好的办法实现自己的hive.security.authenticator.manager来实现根据提交SQL的用户去进行权限验证。


推荐阅读
  • 深入浅出:Hadoop架构详解
    Hadoop作为大数据处理的核心技术,包含了一系列组件如HDFS(分布式文件系统)、YARN(资源管理框架)和MapReduce(并行计算模型)。本文将通过实例解析Hadoop的工作原理及其优势。 ... [详细]
  • 面对众多的数据分析工具,如何选择最适合自己的那一个?对于初学者而言,了解并掌握几种核心工具是快速入门的关键。本文将从数据处理的不同阶段出发,推荐三种广泛使用的数据分析工具。 ... [详细]
  • 本文介绍如何通过整合SparkSQL与Hive来构建高效的用户画像环境,提高数据处理速度和查询效率。 ... [详细]
  • 大数据SQL优化:全面解析数据倾斜解决方案
    本文深入探讨了大数据SQL优化中的数据倾斜问题,提供了多种解决策略和实际案例,旨在帮助读者理解和应对这一常见挑战。 ... [详细]
  • 本文介绍了多种Eclipse插件,包括XML Schema Infoset Model (XSD)、Graphical Editing Framework (GEF)、Eclipse Modeling Framework (EMF)等,涵盖了从Web开发到图形界面编辑的多个方面。 ... [详细]
  • 本文介绍了在解决Hive表中复杂数据结构平铺化问题后,如何通过创建视图来准确计算广告日志的曝光PV,特别是针对用户对应多个标签的情况。同时,详细探讨了UDF的使用方法及其在实际项目中的应用。 ... [详细]
  • 本文详细介绍了Oracle RMAN中的增量备份机制,重点解析了差异增量和累积增量备份的概念及其在不同Oracle版本中的实现。通过对比两种备份方式的特点,帮助读者选择合适的备份策略。 ... [详细]
  • StoredProcedure “存储过程名” 的TextHeader 中存在语法错误
    修改存储过程的时候出现StoredProcedure“存储过程名”的TextHeader中存在语法错误出现这样的问题的解决方法(本人修改已成功)在创建存 ... [详细]
  • 本文详细介绍了如何处理Oracle数据库中的ORA-00227错误,即控制文件中检测到损坏块的问题,并提供了具体的解决方案。 ... [详细]
  • 本文探讨了在SharePoint环境中使用BDC(Business Data Catalog)时遇到的问题及其解决策略,包括XML文件导入SSP后的不可见性问题以及与远程SQL Server 2005连接的难题。 ... [详细]
  • Hadoop集群搭建:实现SSH无密码登录
    本文介绍了如何在CentOS 7 64位操作系统环境下配置Hadoop集群中的SSH无密码登录,包括环境准备、用户创建、密钥生成及配置等步骤。 ... [详细]
  • 龙蜥社区开发者访谈:技术生涯的三次蜕变 | 第3期
    龙蜥社区的开发者们通过自己的实践和经验,推动着开源技术的发展。本期「龙蜥开发者说」聚焦于一位资深开发者的三次技术转型,分享他在龙蜥社区的成长故事。 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 如何在U8系统中连接服务器并获取数据
    本文介绍了如何在U8系统中通过不同的方法连接服务器并获取数据,包括使用MySQL客户端连接实例的方法,如非SSL连接和SSL连接,并提供了详细的步骤和注意事项。 ... [详细]
  • 本文详细介绍了 `org.apache.hadoop.hdfs.server.namenode.FSNamesystem.shouldUseDelegationTokens()` 方法的用途和实际应用场景,并提供了多个代码示例以帮助开发者更好地理解和使用该方法。 ... [详细]
author-avatar
山百惠0-0
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有