Hive数据仓库之权限管理

Hadoop/Hive自带权限控制

延续数据仓库之Hive快速入门 - 离线&实时数仓架构一文,本文将介绍一下Hadoop/Hive自带的权限控制,权限控制是大数据平台非常重要的一部分,关乎数据安全。

集群安全下需求:

  • 支持多组件,最好能支持当前大数据技术栈的主要组件,HDFS、HBASE、HIVE、 YARN、KAFKA等
  • 支持细粒度的权限控制,可以达到HIVE列,HDFS目录,HBASE列,YARN队列
  • 开源,社区活跃,按照现有的集群情况改动尽可能的小,而且要符合业界的趋势。

现有方案:

  • Hadoop、Hive本 身的权限控制
  • Kerberos安全认证
  • Apache Ranger权限管理方案

Hadoop权限:

  • Hadoop分布式文件系统实现了一个和POSIX系统类似的文件和目录的权限模型
  • 每个文件和目录有一个所有者(owner)和一个组(group)
  • 文件或目录对其所有者、同组的其他用户以及所有其他用户分别有着不同的权限
  • 文件或目录操作都传递路径名给NameNode,对路径做权限检查
  • 启动NameNode的用户是超级用户,能够通过所有的权限检查
  • 通过配置可以指定一组特定的用户为超级用户

Hive权限:

  • Hive可以基于文件存储级别的权限管理
  • Hive可以基于元数据的权限管理
  • User:是基于linux用户的user
  • Group:是linux层面上的用户组
  • Role:角色在Hive里面创建,给角色添加权限,把角色赋予给user
  • Hive中没有超级管理员,任何用户都可以进行Grant/Revoke操作
  • 开发实现自己的权限控制类,确保某个用户为超级用户

实操Hive的权限操作

首先添加一个系统用户:

[root@hadoop01 ~]# useradd hive

test这个表的查询权限赋予给hive这个用户:

0: jdbc:hive2://localhost:10000> grant select on table test to user hive;
No rows affected (0.12 seconds)
0: jdbc:hive2://localhost:10000> 

切换到hive用户:

[root@hadoop01 ~]# sudo su - hive

进入交互命令终端,可以正常执行查询语句:

[hive@hadoop01 ~]$ beeline -u jdbc:hive2://localhost:10000 -n hive
...

0: jdbc:hive2://localhost:10000> select user_name from test;
+------------+
| user_name  |
+------------+
| Tom        |
| Jerry      |
| Jim        |
| Angela     |
| Ann        |
| Bella      |
| Bonnie     |
| Caroline   |
+------------+
8 rows selected (0.075 seconds)
0: jdbc:hive2://localhost:10000> 

但是如果执行其他操作则会报错提示不支持该操作:

0: jdbc:hive2://localhost:10000> delete from test where user_id='f4914b91c5284b01832149776ca53c8d';
Error: Error while compiling statement: FAILED: SemanticException [Error 10294]: Attempt to do update or delete using transaction manager that does not support these operations. (state=42000,code=10294)
0: jdbc:hive2://localhost:10000> 

如此一来,我们就可以限制Hive中用户对于某些表的操作权限。但之前也提到了,Hive中没有超级管理员,任何用户都可以进行Grant/Revoke操作,这使得权限管理失去意义。为了解决这个问题,就需要我们开发实现自己的权限控制类,确保某个用户为超级用户。

首先创建一个空Maven项目,然后添加hive-exec依赖,完整的pom文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hive-security-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>3.1.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

实现自定义权限控制类:

package com.example.hive.security;

import com.google.common.base.Joiner;
import org.apache.hadoop.hive.ql.parse.*;
import org.apache.hadoop.hive.ql.session.SessionState;

/**
 * 自定义Hive的超级用户
 *
 * @author 01
 * @date 2020-11-09
 **/
public class HiveAdmin extends AbstractSemanticAnalyzerHook {

    /**
     * 定义超级用户,可以定义多个
     */
    private static final String[] ADMINS = {"root"};

    /**
     * 权限类型列表
     */
    private static final int[] TOKEN_TYPES = {
            HiveParser.TOK_CREATEDATABASE, HiveParser.TOK_DROPDATABASE,
            HiveParser.TOK_CREATEROLE, HiveParser.TOK_DROPROLE,
            HiveParser.TOK_GRANT, HiveParser.TOK_REVOKE,
            HiveParser.TOK_GRANT_ROLE, HiveParser.TOK_REVOKE_ROLE,
            HiveParser.TOK_CREATETABLE
    };

    /**
     * 获取当前登录的用户名
     *
     * @return 用户名
     */
    private String getUserName() {
        boolean hasUserName = SessionState.get() != null &&
                SessionState.get().getAuthenticator().getUserName() != null;

        return hasUserName ? SessionState.get().getAuthenticator().getUserName() : null;
    }

    private boolean isInTokenTypes(int type) {
        for (int tokenType : TOKEN_TYPES) {
            if (tokenType == type) {
                return true;
            }
        }

        return false;
    }

    private boolean isAdmin(String userName) {
        for (String admin : ADMINS) {
            if (admin.equalsIgnoreCase(userName)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public ASTNode preAnalyze(HiveSemanticAnalyzerHookContext context, ASTNode ast) throws SemanticException {
        if (!isInTokenTypes(ast.getToken().getType())) {
            return ast;
        }

        String userName = getUserName();
        if (isAdmin(userName)) {
            return ast;
        }

        throw new SemanticException(userName +
                " is not Admin, except " +
                Joiner.on(",").join(ADMINS)
        );
    }
}

将代码打包,上传到服务器上:

[root@hadoop01 ~]# ls jars/
hive-security-test-1.0-SNAPSHOT.jar
[root@hadoop01 ~]# 

将其拷贝到Hive的lib目录下:

[root@hadoop01 ~]# cp jars/hive-security-test-1.0-SNAPSHOT.jar /usr/local/apache-hive-3.1.2-bin/lib/

在hive的hive-site.xml文件中,增加如下配置:

[root@hadoop01 ~]# vim /usr/local/apache-hive-3.1.2-bin/conf/hive-site.xml
<configuration>

    ...
    
    <property>
        <name>hive.users.in.admin.role</name>
        <value>root</value>
        <description>定义超级管理员,启动的时候会自动创建</description>
    </property>
    <property>
        <name>hive.security.authorization.enabled</name>
        <value>true</value>
        <description>开启权限</description>
    </property>
    <property>
        <name>hive.security.authorization.createtable.owner.grants</name>
        <value>ALL</value>
        <description>表的创建者对表拥有所有权限</description>
    </property>
    <property>
        <name>hive.security.authorization.task.factory</name>
        <value>org.apache.hadoop.hive.ql.parse.authorization.HiveAuthorizationTaskFactoryImpl</value>
        <description>进行权限控制的配置</description>
    </property>
    <property>
        <name>hive.semantic.analyzer.hook</name>
        <value>com.example.hive.security.HiveAdmin</value>
        <description>使用钩子程序,识别超级管理员,进行授权控制</description>
    </property>
</configuration>

重启Hive:

[root@hadoop01 ~]# jps
12401 ResourceManager
12898 RunJar
22338 Jps
12500 NodeManager
11948 NameNode
12204 SecondaryNameNode
12047 DataNode
[root@hadoop01 ~]# kill -15 12898
[root@hadoop01 ~]# nohup hiveserver2 -hiveconf hive.execution.engine=mr &

进入Hive中查看一下角色列表,看看配置是否生效:

[root@hadoop01 ~]# beeline -u jdbc:hive2://localhost:10000 -n root
...

0: jdbc:hive2://localhost:10000> set role admin;  # 将当前用户角色设置为admin
No rows affected (0.027 seconds)
0: jdbc:hive2://localhost:10000> show roles;  # 查看角色列表
+---------+
|  role   |
+---------+
| admin   |
| public  |
+---------+
2 rows selected (0.026 seconds)
0: jdbc:hive2://localhost:10000> 

测试授权操作:

0: jdbc:hive2://localhost:10000> use hive_test;
No rows affected (0.028 seconds)
0: jdbc:hive2://localhost:10000> grant select on table bucket_table to user hive;
No rows affected (0.146 seconds)
0: jdbc:hive2://localhost:10000> 

切换到hive用户:

[root@hadoop01 ~]# sudo su - hive

进入交互命令终端,此时执行grant语句就会报错,从报错提示可以看到该错误是从我们实现的Hook类里抛出来的:

[hive@hadoop01 ~]$ beeline -u jdbc:hive2://localhost:10000 -n hive
...

0: jdbc:hive2://localhost:10000> grant select on table partition_table to user hive;
Error: Error while compiling statement: FAILED: SemanticException hive is not Admin, except root (state=42000,code=40000)
0: jdbc:hive2://localhost:10000> 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容