Hadoop/Hive自帶權(quán)限控制
延續(xù)數(shù)據(jù)倉庫之Hive快速入門 - 離線&實時數(shù)倉架構(gòu)一文,本文將介紹一下Hadoop/Hive自帶的權(quán)限控制,權(quán)限控制是大數(shù)據(jù)平臺非常重要的一部分,關(guān)乎數(shù)據(jù)安全。
集群安全下需求:
- 支持多組件,最好能支持當前大數(shù)據(jù)技術(shù)棧的主要組件,HDFS、HBASE、HIVE、 YARN、KAFKA等
- 支持細粒度的權(quán)限控制,可以達到HIVE列,HDFS目錄,HBASE列,YARN隊列
- 開源,社區(qū)活躍,按照現(xiàn)有的集群情況改動盡可能的小,而且要符合業(yè)界的趨勢。
現(xiàn)有方案:
- Hadoop、Hive本 身的權(quán)限控制
- Kerberos安全認證
- Apache Ranger權(quán)限管理方案
Hadoop權(quán)限:
- Hadoop分布式文件系統(tǒng)實現(xiàn)了一個和POSIX系統(tǒng)類似的文件和目錄的權(quán)限模型
- 每個文件和目錄有一個所有者(owner)和一個組(group)
- 文件或目錄對其所有者、同組的其他用戶以及所有其他用戶分別有著不同的權(quán)限
- 文件或目錄操作都傳遞路徑名給NameNode,對路徑做權(quán)限檢查
- 啟動NameNode的用戶是超級用戶,能夠通過所有的權(quán)限檢查
- 通過配置可以指定一組特定的用戶為超級用戶
Hive權(quán)限:
- Hive可以基于文件存儲級別的權(quán)限管理
- Hive可以基于元數(shù)據(jù)的權(quán)限管理
- User:是基于linux用戶的user
- Group:是linux層面上的用戶組
- Role:角色在Hive里面創(chuàng)建,給角色添加權(quán)限,把角色賦予給user
- Hive中沒有超級管理員,任何用戶都可以進行Grant/Revoke操作
- 開發(fā)實現(xiàn)自己的權(quán)限控制類,確保某個用戶為超級用戶
實操Hive的權(quán)限操作
首先添加一個系統(tǒng)用戶:
[root@hadoop01 ~]# useradd hive
將test這個表的查詢權(quán)限賦予給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
進入交互命令終端,可以正常執(zhí)行查詢語句:
[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>
但是如果執(zhí)行其他操作則會報錯提示不支持該操作:
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中用戶對于某些表的操作權(quán)限。但之前也提到了,Hive中沒有超級管理員,任何用戶都可以進行Grant/Revoke操作,這使得權(quán)限管理失去意義。為了解決這個問題,就需要我們開發(fā)實現(xiàn)自己的權(quán)限控制類,確保某個用戶為超級用戶。
首先創(chuàng)建一個空Maven項目,然后添加hive-exec依賴,完整的pom文件內(nèi)容如下:
<?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>
實現(xiàn)自定義權(quán)限控制類:
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"};
/**
* 權(quán)限類型列表
*/
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)
);
}
}
將代碼打包,上傳到服務(wù)器上:
[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>定義超級管理員,啟動的時候會自動創(chuàng)建</description>
</property>
<property>
<name>hive.security.authorization.enabled</name>
<value>true</value>
<description>開啟權(quán)限</description>
</property>
<property>
<name>hive.security.authorization.createtable.owner.grants</name>
<value>ALL</value>
<description>表的創(chuàng)建者對表擁有所有權(quán)限</description>
</property>
<property>
<name>hive.security.authorization.task.factory</name>
<value>org.apache.hadoop.hive.ql.parse.authorization.HiveAuthorizationTaskFactoryImpl</value>
<description>進行權(quán)限控制的配置</description>
</property>
<property>
<name>hive.semantic.analyzer.hook</name>
<value>com.example.hive.security.HiveAdmin</value>
<description>使用鉤子程序,識別超級管理員,進行授權(quán)控制</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; # 將當前用戶角色設(shè)置為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>
測試授權(quán)操作:
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
進入交互命令終端,此時執(zhí)行grant語句就會報錯,從報錯提示可以看到該錯誤是從我們實現(xiàn)的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>