hive-3. 权限

1,928 阅读15分钟

1.hive的三种权限模型介绍

1.1 Hive默认授权(Default Hive Authorization (Legacy Mode))

设计目的并不是为了防止恶意用户访问(操作)未经授权的数据,帮助用户避免一些意料之外的操作行为,另外授权机制并不完善,在很多指令方面都没有进行授权确认,比如授权指令Grant。

这种权限机制可以实现用户协同办公时,经过授权可以具有和owner等同级别的权限,例如DDL操作(create table,drop table等),使用这样机制控制,必需要在应用层对grant语句进行过滤,才可以开放给用户。

1.2 基于存储的授权(Storage Based Authorization in the Metastore Server)

用于Metastore Server API的授权,保护Metastore中的元数据不被恶意用户破坏。

基于存储的授权是基于hdfs的目录和文件的权限来进行控制的,不能做到提供细粒度的访问控制(列级别、行级别)

例如通过cli、mapreduce等方式是绕过hiveserver直接操作metastore,那么在hiveserver层面的授权是不能起到任何控制作用。这时开启基于存储的权限可以控制其他客户端访问hive数据的权限。

1.3基于SQL标准的Hive授权(SQL Standards Based Hive Authorization)

基于SQL标准的Hive授权,它完全兼容SQL的授权模型,不会给现在的用户带来向后兼容的问题,因此被推荐使用。 一旦用户开启这种更加安全的授权机制后,默认的授权机制就会失效。

基于SQL标准的Hive授权:

  1. 系统默认提供两种角色public和admin;
  • public角色是对应一些公用操作,所有的用户都具有该角色;(注:只发现default数据库的使用到角色,更多的操作权限没做更细的调查)
  • admin角色,全局的管理员角色,可以在hive-site.xml中指定哪些用户拥有该角色(目前配置的是hive超级用户作为admin的用户,可用配置多个); admin角色的特殊操作:
    • function的add,drop;
    • ALTER DATABASE,可以更改数据库的owner;
    • role的create、drop,grant to users;
      注:admin角色拥有的操作,其他用户都没有权限操作,同时也不能把这些操作授权给其他用户;
  1. database的创建者为database owner;
  2. 所有的DDL操作只有owner可执行,但不提供create权限授予其他用户;
  3. table的创建者为table owner;默认owner创建的表其他任何用户没有任何操作,需要授权给其他用户。
    • 授权表给角色 (all: select\insert\update\delete ) grant all on table test107_tab1 to role role_test;
    • 授权表给角色 grant select,insert,update,delete on table test107_tab1 to role role_test2;
    • 授权表给用户 (all: select\insert\update\delete ) grant all on table test107_tab1 to user user_test;
    • 授权表给用户 grant select,insert,update,delete on table test107_tab1 to user user_test2;

注: Authorization using Apache Ranger & Sentry

2.hive的三种权限模型的组合使用

2.1 Hive默认授权+基于存储的授权

这种方案由于Hive默认授权grant没有做限制,这种授权不是很安全。

2.2 基于SQL标准的Hive授权+基于存储的授权:

这两种方案在配置上有冲突,冲突如下:

  1. 基于SQL标准的Hive授权需要配置hive.server2.enable.doAs=false, doAs=false在HDFS是以hive用户(启动hiveserver2的用户)进行创建,这样只需要在元数据层面进行权限控制,元数据层面的权限控制是根据database和table的owner,role等进行权限控制,底层hdfs使用hive超级用户操作,也不会存在真实用户hdfs权限的问题;
  2. 基于存储的授权需要配置hive.server2.enable.doAs=true, doAs=true在HDFS上是以真实用户进行创建,目录或者文件的owner为真实用户,再配置HDFS的ACL使用就行控制用户对目录和文件的RWX操作。基于存储的权限控制就是根据目录和文件的权限,限制其他用户的访问和操作。

但官方推荐这两种组合来做权限控制,但怎么解决这种冲突,官方并没有给出解决方案,需要用户自己有一种机制做到hdfs和元数据的权限一致。 如果结合使用的话

  1. 属性hive.server2.enable.doAs=true,同时开启基于存储的授权;
  2. 但基于SQL标准的Hive授权会出现在同一个数据库下协同用户授权表的操作和HDFS的权限不一致的问题。 例如:Sql 执行grant insert to user, 在元数据层面被授权用户是有权限进行insert的,但执行的时候HDFS出现没有W的权限。
  3. 两种方案组合使用需要改造hive,实现监控授权操作,修改HDFS的acl,使授权用户具有HDFS文件或目录的RWX相应权限。

2.3 单独使用基于SQL标准的Hive授权

  1. 属性hive.server2.enable.doAs=false,同时牺牲掉基于存储的授权,否则metastore会因为超级用户hive和真实用户不一致导致不能使用;
  2. 所有的DDL操作只有owner可执行,但不提供create权限授予其他用户。为了解决协同其他用户都可以在数据库中进行DDL的操作,可以参考default数据库所有用户都可以 做任何操作的原理,实现授权用户可以操作DDL。 default数据库权限共享原理:default数据库是把数据库的owner赋予了角色(public,系统自带角色),任何一个用户默认都拥有该角色进而可以做DDL操作。 实现非Owner用户做DDL操作的步骤:
-- 以admin角色的用户hive连接hiveesrver2:
  -- 1. 切换admin角色
set role admin;
  -- 2. 创建角色
create role database_role;   #database_role的命名确保全局唯一
  -- 3. 把数据库的owner 更改为角色database_role
alter database test107_db7 set owner role database_role;
  -- 4. 把角色授权给用户
grant database_role to user test107 with admin option;  -- test107是数据库的owner,把数据库的owner改为role后,需要把role授权给用户
                                                   -- with admin option 参数是让用户test107同样可以把role授权给其他用户;                  
-- 以test107用户连接hiveesrver2;
  -- 把database的owner 角色授权给其他用户;
set role database_role;
grant role database_role to user test108;  
  1. 创建external或者指定location的表 外部表比较特殊,需要先创建URI,并确保URI的owner和创建表的身份是一致的,而且创建成功还要把URI的owner的改成hive(超级用户)。建议:在应用层管理location的URI,把URI的管理作为资源在项目中进行管理。 创建外部表步骤:
  2. 创建URI目录,并确保目录的Owner与创建表的身份相同;
  3. 更改URI目录的owner为hive(超级用户),因为HDFS的文件和目录的owner都为owner才不会出现hdfs权限和元数据权限不一致的问题;
  4. 更改URI的权限为711,因为warehouse的权限也是711;

3.hive自身的权限问题总结及需要改造的地方

3.1 权限模型总结

  1. Hive默认授权比较原始,只能限制用户做错误的事情;
  2. 基于SQL标准的Hive授权 目前还算安全,前提是假设你不适用cli或mapreduce访问hive; 并不能和基于存储的权限进行组合使用,组合使用会出现hdfs权限和元数据权限不一致的问题; 只用table和view层面的授权,没有database和function级别的授权;
  3. 基于存储的授权,在metastore做权限控制,可以控制cli或者mapreduce的访问,但只能控制到table和database层面;

3.2 目前hive的三种权限模型都不是很完善,需要进行改造:

  1. show databases\show tables\没有做控制,任何用户都可以看到所有的database和table;
    • 更改show databases和show tables函数的过滤操作,根据role和owner进行过滤;
    • 目前没有database级别的授权,table级别的授权不依赖与database,依照现有的授权只用owner或具有owner角色的用户通过show databases才能看到数据库;
    • 用户没有owner的数据库或者owner角色,但在表级别可能是owner的用户,show databases没有任何记录;
  2. function 目前function和role类似,只有admin角色的全局管理员才可以创建,但和role不同的是,role可以grant给不同的用户,但function没有做任何权限控制,一旦创建成功后,所有用户都可以使用。
    • 增加function的授权(grant use_type on function f_name to user|role user_name|roloname);
    • show functions 进行权限过滤;
  3. 假如集成基于SQL标准的Hive授权和基于存储的授权两种权限;
    • 监听授权操作;
    • 匹配授权操作,对hdfs做acl授权;

4.生产使用模式

Hive默认授权+AuthHook限制grant、revoke命令

  1. hive-site.xml配置
<!-- ********************* hive 安全配置 start ********************* -->
    <property>
        <name>hive.security.authorization.enabled</name>
        <value>true</value>
        <final>true</final>
    </property>
    <property>
        <name>hive.metastore.execute.setugi</name>
        <value>true</value>
    </property>
    <property>
        <name>hive.metastore.authorization.storage.checks</name>
        <value>true</value>
        <final>true</final>
    </property>
    <property>
        <name>hive.security.authorization.createtable.owner.grants</name>
        <value>ALL</value>
        <final>true</final>
    </property>
    <property>
        <name>hive.users.in.admin.role</name>
        <value>hdfs</value>
    </property>
    <property>
        <name>hive.security.authorization.manager</name>
        <value>org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider</value>
    </property>
    <property>
        <name>hive.security.authenticator.manager</name>
        <value>org.apache.hadoop.hive.ql.security.HadoopDefaultAuthenticator</value>
    </property>
    <property>
        <name>hive.security.metastore.authorization.manager</name>
        <value>org.apache.hadoop.hive.ql.security.authorization.DefaultHiveMetastoreAuthorizationProvider</value>
    </property>
    <property>
        <name>hive.security.metastore.authenticator.manager</name>
        <value>org.apache.hadoop.hive.ql.security.HadoopDefaultMetastoreAuthenticator</value>
    </property>
    <!-- ********************* hive 安全配置 end ********************* -->
  1. 编写AuthHook.java
public class AuthHook extends AbstractSemanticAnalyzerHook {
    private static List<String> ADMIN_USERS = new ArrayList();
    @Override
    public ASTNode preAnalyze(HiveSemanticAnalyzerHookContext context, ASTNode ast) throws SemanticException {
        switch(ast.getToken().getType()) {
            case HiveParser.TOK_CREATEDATABASE:
            case HiveParser.TOK_CREATEROLE:
            case HiveParser.TOK_DROPDATABASE:
            case HiveParser.TOK_DROPROLE:
            case HiveParser.TOK_GRANT:
            case HiveParser.TOK_GRANT_ROLE:
            case HiveParser.TOK_REVOKE:
            case HiveParser.TOK_REVOKE_ROLE:
                String userName = null;
                if (SessionState.get() != null && SessionState.get().getAuthenticator() != null) {
                    userName = SessionState.getUserFromAuthenticator();
                }
                if (!ADMIN_USERS.contains(userName)) {
                    throw new SemanticException(userName + " can't use ADMIN options, except " + ADMIN_USERS + ".");
                }
            default:
                return ast;
        }
    }
}

5.metastore的认证和授权

5.1 Metastore服务介绍

metastore主要维护2种数据:

  • 数据库、表、分区等数据,算是DDL操作
  • 权限、角色类的数据,算是DCL操作 metastore通过开启thrift rpc服务,开启对上述2种数据的操作接口,接口即 ThriftHiveMetastore.Iface 内容见下图 第一种数据的操作如下:

image.png 第二种数据的操作如下:

image.png metastore对该接口的实现为:HMSHandler,它主要有以下属性:

  • ThreadLocal<RawStore> threadLocalMS RawStore主要用于和数据库打交道,存储上述2种相关数据,RawStore和当前线程进行绑定,默认实现是ObjectStore
  • List<MetaStorePreEventListener> preListeners 当上述2种数据将要发生变化的时候,都会首先调用上述MetaStorePreEventListener执行一些预处理操作,如验证一个用户是否有权限来执行该操作
  • List<MetaStoreEventListener> listeners 当上述第一种数据发生变化后,会调用上述MetaStoreEventListener执行一些处理

5.2 Metastore服务的认证和验权

由上述可以了解到,在metastore的数据发生修改之前可以进行验权操作,hive默认提供了一个AuthorizationPreEventListener实现了上述MetaStorePreEventListener接口执行一些验权操作

image.png 从上面可以看到,仅仅对DDL操作进行了验权,并没有对DCL操作进行验权,这也是一个比较奇怪的地方。即如果你能直连到metastore服务,就可以随意的进行授权操作。 接下来我们详细看看这个认证和授权的过程 涉及到2个接口:

  • HiveMetastoreAuthenticationProvider:认证提供者,用于用户的认证,一个HiveMetastoreAuthenticationProvider对象对应一个用户,该对象包含用户的userName和groups信息
  • HiveMetastoreAuthorizationProvider:授权提供者,用于用户的验权

5.2.1 Metastore服务的认证

HiveMetastoreAuthenticationProvider的默认实现是HadoopDefaultMetastoreAuthenticator,通过hadoop中的UserGroupInformation来获取当前用户名和组的信息,如下所示

image.png metastore的client端用户是如何被传递到这里的呢?

这就涉及到了metastore开启的thrift rpc服务了,metastore使用的是thrift的TThreadPoolServer来作为server。这种模式下,会启动一个线程池,每来一个客户端连接就取出一个线程来专门处理该连接,该连接就一直占用该线程了,这种方式就是传统的BIO方式,能够支持的并发量比较小。

metastore开启的rpc服务分成3种类型:

  • 使用sasl方式: 是一种安全的方式,使用kerberos认证用户的身份,这一部分内容比较多,可能之后再详细分析这一块。
  • setUgi方式: 是一种非安全的方式,即并没有对用户的身份进行合法性验证。当hive.metastore.execute.setugi=true时即采用这种模式。这种模式下如下操作:
    • client端会通过set_ugi方法来向服务器端传递用户的ugi信息
    • 服务器端将用户的ugi信息绑定到当前连接上
    • client端向服务器端发送操作数据的请求,服务器端取出连接中的ugi信息,使用ugi的doas方法来执行操作
    • client占用服务器端的一个线程,会创建出一个HiveMetastoreAuthenticationProvider对象,该对象在创建过程中要获取当前的ugi信息,即获取到上述ugi信息,并且把client的上述HiveMetastoreAuthenticationProvider对象绑定在该线程中,至此便可以得到client的用户信息。而groups信息则是通过hadoop默认的方式即获取本metastore服务所在的机器上,该用户所属的groups信息。
  • 其他: 就仅仅是将client的ip绑定到当前线程上,就没有所谓的用户信息了

上述的sasl也是通过ugi.doas方式来供后续获取用户信息的,但是sasl多了用户身份合法性的验证过程。而setUgi方式client端传过来什么用户就认为是什么用户,所以只有sasl方式才是安全的方式,其他2种是非安全方式。

5.2.3 Metastore服务的验权

上一部分我们获取到了用户信息,下面就是要验证用户是否有权限执行相关操作,验权接口就是HiveMetastoreAuthorizationProvider,实现类如下:

image.png

默认是DefaultHiveMetastoreAuthorizationProvider。

  • DefaultHiveMetastoreAuthorizationProvider: 根据userName和groups信息从数据库中获取权限信息来验证用户是否有权限
  • StorageBasedAuthorizationProvider: 判断一个用户是否对数据库、表等是否有权限依据该用户在HDFS上对这些文件是否有对应的权限

5.3 总结

总结如下:

  • metastore只做了DDL操作的相关认证,并没有做DCL操作的认证,一旦通过hive cli连接metastore,用户就可以随意进行赋权操作
  • 根据用户和用户所属的groups信息来获取权限,大数据系统中用户和groups关系的维护最好是自己统一维护,而不是借助默认的linux机器上用户和groups的关系,不然之后会有很多麻烦的。 画了一个默认情况下简单的示意图如下: image.png

6.HDFS层面的权限管理

Hive 底层数据都是存储在HDFS上的。 因此Hive的权限管理也分为HDFS 和Hive自身两个层面。

HDFS层面的权限管理: 因为由 Hive创建的表的数据文件及目录 这些文件目录存放在HDFS上,因此每个文件都有相应的HDFS 权限设置。 hive中有个配置项 hive.files.umask.value = 002
表示由hive 创建的文件的权限掩码是 002, (和777做减操作), 则hive 创建的表文件的权限为 775, 即

十进制掩码    权限位(w.r.x)
777                111.111.111
002                000.000.010    进行或操作
/--------------------------------------------
775                111.111.101

这个配置项在0.90版中被替代了。 新的设置项(在hive-site.xml中配置为:

hive.warehouse.subdir.inherit.perms
Default Value: false
Added In: Hive 0.9.0 with HIVE-2504
Set this to true if table directories should inherit the permissions of the warehouse or database directory instead of being created with permissions derived from dfs umask. (This configuration property replaced hive.files.umask.value before Hive 0.9.0 was released.)

这段说明,如果设置inherit.perms为true,则子表的权限设置继承自warehouse目录的设置。就会使用hdfs的配置dfs.umask值来指定权限。

例如apps/hive/warehouse   权限为775drwxrwxr-x 则新建的table所在的文件夹也是775的权限
hive    hadoop    drwxrwxr-x    June 18, 2014 11:29 am

7. 数据库层面的权限管理

Hive支持的权限有Users,Groups,Roles hive中也有database,table等概念,因此对这些实体也都配置了权限设置。 hive的用户、组就是执行hive 客户端进程的用户以及他所在的linux上的组。(可以使用whoami 来看进程,也可以使用bash -c groups来看该用户所属的组) 可以使用grant命令对用户、组明确的授予对表、database上的具体权限。 例如Select, Update, ALL等。

一个角色可以包含组或者用户 By default, the Metastore uses the HadoopDefaultAuthenticator for determing user -> group mappings metastore默认会以metastore所在的机器根据用户名获取用户所属的组,而不是客户端的组。

Hive的权限支持全局权限(Global)、数据库、表、分区、列。

权限名称含义
ALL所有权限
ALTER允许修改元数据(modify metadata data of object)—表信息数据
UPDATE允许修改物理数据(modify physical data of object)—实际数据
CREATE允许进行Create操作
DROP允许进行DROP操作
INDEX允许建索引(目前还没有实现)
LOCK当出现并发的使用允许用户进行LOCK和UNLOCK操作
SELECT允许用户进行SELECT操作
SHOW_DATABASE允许用户查看可用的数据库
-- 创建角色
CREATE ROLE role_name
DROP ROLE role_name
-- 角色分配
GRANT ROLE role_name [, role_name] ...
TO principal_specification [, principal_specification] ...
REVOKE ROLE role_name [, role_name] ...
FROM principal_specification [, principal_specification] ...
principal_specification
  : USER USER
  ¦ GROUP GROUP
  ¦ ROLE ROLE
-- 查看权限
SHOW GRANT ROLE principal_specification
-- 例子:
CREATE ROLE youxi_role;
GRANT ROLE youxi_role TO USER fatkun;

-- 权限
GRANT
    priv_type [(column_list)]
      [, priv_type [(column_list)]] ...
    [ON object_type]
    TO principal_specification [, principal_specification] ...
    [WITH GRANT OPTION]
REVOKE
    priv_type [(column_list)]
      [, priv_type [(column_list)]] ...
    [ON object_type priv_level]
    FROM principal_specification [, principal_specification] ...
REVOKE ALL PRIVILEGES, GRANT OPTION
    FROM USER [, USER] ...
object_type:
    TABLE
  ¦ DATABASE
priv_level:
    db_name
  ¦ tbl_name
-- 例子:
GRANT ALL ON DATABASE DEFAULT TO USER fatkun;
GRANT ALL ON TABLE test TO GROUP kpi;
REVOKE ALL ON TABLE test FROM GROUP kpi;
GRANT ALL TO USER fatkun;
REVOKE ALL FROM fatkun;
-- 授权还是挺麻烦的。。你在哪一级别授权,只能在那个级别收回授权。

-- 查看权限
SHOW GRANT principal_specification
[ON object_type priv_level [(column_list)]]
-- 例子:
SHOW GRANT GROUP kpi ON TABLE test;