hive 权限管理
hive做为table的存储层,spark sql,mapreduce, Presto 等等通过 Hive's HCatalog API 访问元数据信息, 进而访问hdfs数据, 此时要对hdfs访问做权限控制(hdfs 默认已经处理),元数据访问需要做权限控制。 hive sql 执行引擎, hive的一个非常普遍的用法,主要针对sql的用户和BI工具
(1)hive 客户端用户 (官方建议抛弃) (2)ODBC/JDBC 和 HiveServer2 Api(Beeline CLI)
HiveServer2是一个服务,支持客户端不使用Hive脚本进行执行查询,HiveServer2继承了HiveServer1,HiveServer1已经过时!
HiveServer2其实就是一个远程客户端执行查询的和检索的一个服务接口,目前是基于Thrift RPC实现的,是HiveServer的提高版本,支持多客户端并发查询和认证,它被提供是为了更好的开放客户端API,例如JDBC和ODBC(言外之意就是远程的hive client执行查询都需要连接到HiveServer2之上) 针对上面的用例hive官方提供三种权限控制: 基于元数据存储、 基于sql标准、 默认的hive授权。选中方案 HiveServer2中基于SQL标准的授权为主,包含Metastore Server中基于存储的授权(Metastore Server中基于存储的授权可选),先上图:
Metastore
Metastore组件:它是元数据服务组件,hive元数据集中存放地。Metastore组件包括两个部分:metastore服务和后台数据的存储。后台数据存储的介质就是关系数据库,例如mysql数据库。Metastore服务是建立在后台数据存储介质之上,并且可以和hive服务进行交互的服务组件,默认情况下,metastore服务和hive服务是安装在一起的,运行在同一个进程当中。也可以把metastore服务从hive服务里剥离出来,metastore独立安装在一个集群里,hive远程调用metastore服务,这样就可以把元数据这一层放到防火墙之后,客户端访问hive服务,就可以连接到元数据这一层,从而提供了更好的管理性和安全保障。使用远程的metastore服务,可以让metastore服务和hive服务运行在不同的进程里,这样也保证了hive的稳定性,提升了hive服务的效率。
Hive中metastore(元数据存储)的三种方式:
1)内嵌Derby方式(默认方案) 2)Local方式 3)Remote方式
Local方式
以本地Mysql数据库为例,配置文件 hive-site.xml 中jdbc URL、驱动、用户名、密码等属性值配置如下:
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://eagle80:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
ps:需要把mysql的驱动包copy到目录 <HIVE_HOME>/lib 中
如果是第一次需要执行初始化命令:schematool -dbType mysql -initSchema
配置完成之后启动元数据服务,然后使用hive进入shell进行交互式查询。
Remote方式
客户端配置都在一个 hive-site.xml 中,属性值配置如下:
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://eagle80:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://eagle80:9083</value>
</property>
hive metastore 服务端启动命令:
hive --service metastore 启动元数据服务
三种部署方式区别总结:
- 内嵌模式使用的是内嵌的Derby数据库来存储元数据,也不需要额外起Metastore服务。这个是默认的,配置简单,但是一次只能一个客户端连接,适用于用来实验,不适用于生产环境。
- 本地元存储和远程元存储都采用外部数据库来存储元数据,目前支持的数据库有:MySQL、Postgres、Oracle、MS SQL Server.在这里我们使用MySQL。
- 本地元存储和远程元存储的区别是:本地元存储不需要单独起metastore服务,用的是跟hive在同一个进程里的metastore服务。远程元存储需要单独起metastore服务,然后每个客户端都在配置文件里配置连接到该metastore服务。远程元存储的metastore服务和hive运行在不同的进程里。
授权模式概述
1、旧的默认Hive授权(传统模式)
Hive旧默认授权(在Hive 2.0.0之前是默认授权)是早期版本的Hive中可用的授权模式。但是,此模式没有完整的访问控制模型,因此未解决许多安全漏洞。例如,未定义为用户授予权限所需的权限,并且任何用户都可以授予自己对表或数据库的访问权限。
此模型类似于基于SQL标准的授权模式,因为它提供基于grant / revoke语句的访问控制。但是,访问控制策略与基于SQL标准的授权不同,并且它们不兼容。
2、 Metastore Server中基于存储的授权
通过在Metastore Server中启用基于存储的授权, 会控制元数据对象(如数据库,表和分区)上的元数据访问,它会检查您是否拥有文件系统上相应目录的权限。
Metastore Server中基于存储的授权
<property>
<name>hive.security.metastore.authorization.manager</name>
<value>org.apache.hadoop.hive.ql.security.authorization.DefaultHiveMetastoreAuthorizationProvider</value>
</property>
<property>
<name>hive.security.metastore.authorization.auth.reads</name>
<value>true</value>
</property>
<property>
<name>hive.security.metastore.authenticator.manager</name>
<value>org.apache.hadoop.hive.ql.security.HadoopDefaultMetastoreAuthenticator</value>
</property>
<property>
<name>hive.metastore.pre.event.listeners</name>
<value> org.apache.hadoop.hive.ql.security.authorization.AuthorizationPreEventListener</value>
</property>
3、 HiveServer2中基于SQL标准的授权
尽管基于存储的授权可以在数据库,表和分区级别提供访问控制,但它无法控制更精细级别的授权,例如列和视图,因为文件系统提供的访问控制位于目录和文件级别。细粒度访问控制的先决条件是数据服务器,它只能提供用户需要访问的列和行。在文件系统访问的情况下,整个文件被提供给用户。HiveServer2满足这个条件,因为它有一个理解行和列的API(通过使用SQL),并且只能提供SQL查询所要求的列和行。
基于SQL标准的授权 (在Hive 0.13.0中引入) 可用于实现细粒度访问控制。它基于授权的SQL标准,并使用熟悉的grant / revoke语句来控制访问。需要通过HiveServer2配置启用它。
请注意,对于Hive命令行,禁用基于SQL标准的授权。这是因为在Hive中使用访问控制策略的Hive命令行无法进行安全访问控制,因为用户可以直接访问HDFS,因此他们可以轻松绕过基于SQL标准的授权检查,甚至完全禁用它。禁用此功能可避免给用户带来错误的安全感。
<property>
<name>hive.security.authorization.enabled</name>
<value>true</value>
<description>enable or disable the Hive client authorization</description>
</property>
<property>
<name>hive.security.authorization.createtable.owner.grants</name>
<value>ALL</value>
<description>
The privileges automatically granted to the owner whenever a table gets created.
An example like "select,drop" will grant select and drop privilege to the owner
of the table. Note that the default gives the creator of a table no access to the
table (but see HIVE-8067).
</description>
</property>
SQL Standards Based Authorization in HiveServer2默认提供两种角色:public和admin,所有用户默认属于角色public,而授权则必须是具有角色admin的用户才可以完成(普通用户仅可以将自己获得的权限授权给其它用户),因此我们必须添加至少一个用户拥有角色admin
<property>
<name>hive.users.in.admin.role</name>
<value>root</value>
<description>
Comma separated list of users who are in admin role for bootstrapping.
More users can be added in ADMIN role later.
</description>
</property>
<property>
<name>hive.semantic.analyzer.hook</name>
<value>com.sunlands.eagle.etl.AdminHive</value>
<description/>
</property>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value>
<description>
Setting this property to true will have HiveServer2 execute
Hive operations as the user making the calls to it.
</description>
</property>
<property>
<name>hive.metastore.authorization.storage.checks</name>
<value>true</value>
<description>
Should the metastore do authorization checks against the underlying storage (usually hdfs)
for operations like drop-partition (disallow the drop-partition if the user in
question doesn't have permissions to delete the corresponding directory
on the storage).
</description>
</property>
<property>
<name>hive.security.authorization.manager</name>
<value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdConfOnlyAuthorizerFactory</value>
<description>
The Hive client authorization manager class name. The user defined authorization class should implement
interface org.apache.hadoop.hive.ql.security.authorization.HiveAuthorizationProvider.
interface org.apache.hadoop.hive.ql.security.authorization.HiveAuthorizationProvider.
</description>
</property>
<property>
<name>hive.security.authenticator.manager</name>
<value>org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator</value>
<description>
hive client authenticator manager class name. The user defined authenticator should implement
interface org.apache.hadoop.hive.ql.security.HiveAuthenticationProvider.
</description>
</property>
<!-- HiveServer2中基于SQL标准的授权 与 Metastore Server中基于存储的授权 共有配置 -->
<property>
<name>hive.security.metastore.authorization.manager</name>
<value>org.apache.hadoop.hive.ql.security.authorization.StorageBasedAuthorizationProvider,org.apache.hadoop.hive.ql.security.authorization.MetaStoreAuthzAPIAuthorizerEmbedOnly</value>
</property>
超级权限
此时hive已经开启了权限管理的功能,但是所有的用户都拥有给自己甚至别人赋权的能力。为了安全起见(这种安全机制只是为了避免误操作)我们只需要一个超级管理员用户拥有给别人赋权的能力。所以接着我们写一个类用来控制用户的赋权权限。
package com.sunlands.eagle.etl
import org.apache.hadoop.hive.ql.parse.ASTNode;
import org.apache.hadoop.hive.ql.parse.AbstractSemanticAnalyzerHook;
import org.apache.hadoop.hive.ql.parse.HiveParser;
import org.apache.hadoop.hive.ql.parse.HiveSemanticAnalyzerHookContext;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.session.SessionState;
public class AdminHive extends AbstractSemanticAnalyzerHook {
private static String admin = "root";
@Override
public ASTNode preAnalyze(HiveSemanticAnalyzerHookContext context, ASTNode ast) throws SemanticException {
switch (ast.getToken().getType()) {
case HiveParser.TOK_CREATEDATABASE:
case HiveParser.TOK_DROPDATABASE:
case HiveParser.TOK_CREATEROLE:
case HiveParser.TOK_DROPROLE:
case HiveParser.TOK_GRANT:
case HiveParser.TOK_REVOKE:
case HiveParser.TOK_GRANT_ROLE:
case HiveParser.TOK_REVOKE_ROLE:
String userName = null;
if (SessionState.get() != null && SessionState.get().getAuthenticator() != null) {
userName = SessionState.get().getAuthenticator().getUserName();
}
if (!admin.equalsIgnoreCase(userName)) {
throw new SemanticException(userName + " can't use ADMIN options, except " + admin + ".");
}
break;
default: break;
}
return ast;
}
}
接着将该java文件编译、打包后放入hive的lib目录下并在hive-client的hive-site.xml添加属性
<!-- 配置超级管理员,需要自定义控制类继承这个 AbstractSemanticAnalyzerHook-->
<property>
<name>hive.semantic.analyzer.hook</name>
<value>com.sunlands.eagle.etl.AdminHive</value>
</property>
添加了配置文件以后,如果启动了Hive Server,必须关闭重启功能才能生效。至此,只有admin用户可以进行Grant/Revoke操作。
hive --service metastore & 重新启动元数据服务
hiveserver2 & 启动hiveserver2
权限控制具体用户
权限校验时是以提交SQL的用户身份进行的,而具体执行SQL时是以HiveServer2用户身份(可以简单理解为HiveServer2的进程启动用户)进行的,因此HiveServer2用户需要具有读取HDFS目录或文件的权限,根据应用场景不同,可能也需要写/执行权限。
SQL标准的授权自定义登录校验
HiveServer2提供了JDBC链接操作Hive的功能,非常实用,但如果在使用HiveServer2时候,不注意安全控制,将非常危险,因为任何人都可以作为超级用户来操作Hive及HDFS数据。比如:在配置HiveServer2的时候,hive.server2.authentication=NONE,表示没有用户认证。HiveServer2的安全策略有三种方案:
1)LDAP Authentication using OpenLDAP
2)Setting up Authentication with Pluggable Access Modules
3)Configuring Custom Authentic
我选择第三种自定义登录校验,配置如下
<property>
<name>hive.server2.authentication</name>
<value>CUSTOM</value>
<description>
Expects one of [nosasl, none, ldap, kerberos, pam, custom].
Client authentication types.
NONE: no authentication check
LDAP: LDAP/AD based authentication
KERBEROS: Kerberos/GSSAPI authentication
CUSTOM: Custom authentication provider
(Use with property hive.server2.custom.authentication.class)
PAM: Pluggable authentication module
NOSASL: Raw transport
</description>
</property>
package com.sunlands.eagle.etl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hive.service.auth.PasswdAuthenticationProvider;
import javax.security.sasl.AuthenticationException;
public class CustomHiveServer2Auth implements PasswdAuthenticationProvider,Configurable {
private static final Log LOG= LogFactory.getLog(CustomHiveServer2Auth.class);
private Configuration conf=null;
private static final String HIVE_JDBC_PASSWD_AUTH_PREFIX="hive.jdbc_passwd.auth.%s";
@Override
public void Authenticate(String username, String password) throws AuthenticationException {
LOG.info("user: "+username+" try login.");
String passwdMD5 = getConf().get(String.format(HIVE_JDBC_PASSWD_AUTH_PREFIX, username));
if(passwdMD5==null){
String message = "user's ACL configration is not found. user:"+username;
LOG.info(message);
throw new AuthenticationException(message);
}
String passMd5 = new MD5Utils().md5(password);
if(passwdMD5.equals(passMd5)) {
LOG.info("user "+username+" login system successfully.");
} else {
throw new AuthenticationException("user [" + username + "] auth check fail .. ");
}
}
@Override
public Configuration getConf() {
if(conf==null){
this.conf=new Configuration();
}
return conf;
}
@Override
public void setConf(Configuration arg0) {
this.conf=arg0;
}
}
package com.sunlands.eagle.etl;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
private MessageDigest digest;
private char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
public MD5Utils() {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public String md5(String str) {//MD5加密
byte[] btInput = str.getBytes();
digest.reset();
digest.update(btInput);
byte[] md = digest.digest();
int j = md.length;// 把密文转换成十六进制的字符串形式
char strChar[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
strChar[k++] = hexDigits[byte0 >>> 4 & 0xf];
strChar[k++] = hexDigits[byte0 & 0xf];
}
return new String(strChar);
}
接着将该java文件编译、打包后放入hive的lib目录下并在hive-site.xml添加属性
<!-- 配置自定义校验类-->
<property>
<name>hive.server2.custom.authentication.class</name>
<value>com.sunlands.eagle.etl.CustomHiveServer2Auth</value>
</property>
多个用户可以添加多个property,里面配置的即用户名密码了。
<property>
<name>hive.jdbc_passwd.auth.muchaofeng</name>
<value>e55d5a05d5a10299de7866360609d71c</value>
</property>
<property>
<name>hive.jdbc_passwd.auth.eagle</name>
<value>354a9c5058d586c045ade937f91edea7</value>
</property>
<property>
<name>hive.jdbc_passwd.auth.root</name>
<value>f2fdea0fadfd0599a92d5bdc397ca633</value>
</property>
添加了配置文件以后,重新启动HiveServer2,必须关闭重启功能才能生效。
hiveserver2 & 启动hiveserver2
元数据查询
描述hive元数据库中比较重要的一些表的作用,mysql元数据库hive中的表:
表名 |
作用 |
BUCKETING_COLS |
存储bucket字段信息,通过SD_ID与其他表关联 |
CDS |
一个字段CD_ID,与SDS表关联 |
COLUMNS_V2 |
存储字段信息,通过CD_ID与其他表关联 |
DATABASE_PARAMS |
空 |
DBS |
存储hive的database信息 |
DELETEME1410257703262 |
空 |
FUNCS |
空 |
FUNC_RU |
空 |
GLOBAL_PRIVS |
全局变量,与表无关 |
IDXS |
空 |
INDEX_PARAMS |
空 |
PARTITIONS |
分区记录,SD_ID, TBL_ID关联 |
PARTITION_KEYS |
存储分区字段,TBL_ID关联 |
PARTITION_KEY_VALS |
分区的值,通过PART_ID关联。与PARTITION_KEYS共用同一个字段INTEGER_IDX来标示不同的分区字段。 |
PARTITION_PARAMS |
存储某分区相关信息,包括文件数,文件大小,记录条数等。通过PART_ID关联 |
PART_COL_PRIVS |
空 |
PART_COL_STATS |
空 |
PART_PRIVS |
空 |
ROLES |
角色表,和GLOBAL_PRIVS配合,与表无关 |
SDS |
存储输入输出format等信息,包括表的format和分区的format。关联字段CD_ID,SERDE_ID |
SD_PARAMS |
空 |
SEQUENCE_TABLE |
存储sqeuence相关信息,与表无关 |
SERDES |
存储序列化反序列化使用的类 |
SERDE_PARAMS |
序列化反序列化相关信息,通过SERDE_ID关联 |
SKEWED_COL_NAMES |
空 |
SKEWED_COL_VALUE_LOC_MAP |
空 |
SKEWED_STRING_LIST |
空 |
SKEWED_STRING_LIST_VALUES |
空 |
SKEWED_VALUES |
空 |
SORT_COLS |
排序字段,通过SD_ID关联 |
TABLE_PARAMS |
表相关信息,是否外部表,通过TBL_ID关联 |
TAB_COL_STATS |
空 |
TBLS |
存储表信息,关联字段DB_ID,SD_ID, |
TBL_COL_PRIVS |
空 |
TBL_PRIVS |
表赋权限相关信息,通过TBL_ID关联 |
VERSION |
版本 |
VERSION_copy |
版本,通过VER_ID关联 |
登录mysql shell
mysql -u root -p
展示数据库
show databases;
使用数据库
use hive;
展示表
show tables;
查询角色与用户映射表
select * from ROLE_MAP;
Hive支持的权限控制如下表10-8所示。
操作 |
解释 |
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 |
允许用户查看可用的数据库 |
hive 授权命令
角色的创建。语法:
CREATE ROLE ROLE_NAME
创建一个role_test1角色,命令如下
hive> create rolerole_test1;
OK
Time taken: 0.106 seconds
2)删除角色。语法:DROP ROLE ROLE_NAME
删除role_test1角色,命令如下:
hive> DROP ROLE role_test1;
2 角色的授权和撤销
角色的授权(GRANT)就是给角色授予创建表、查询表等操作,撤销(REVOKE)反之。语法如下:
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
看下面的实例。
1)把role_test1角色授权给jayliu用户,命令如下:
hive> grant role role_test1 to user jayliu;
OK
Time taken: 0.102 seconds
2)查看jayliu用户被授权的角色,命令如下:
hive> SHOW ROLE GRANTuser jayliu;
OK
role name:role_test1
role name:role_test1
Time taken: 7.913 seconds,Fetched: 2 row(s)
3)取消jayliu用户的role_test1角色,操作命令如下:
hive> revoke rolerole_test1 from user jayliu;
整理:
1.hive-site.xml 中配置的超级管理员账户 启动hive就会创建 不授予任何权限的情况下只能用来管理角色,权限。
2.权限可以赋值给用户也可以给角色,角色可以赋值给用户。
3.SQL标准的授权只包含增删改查,不包含组
4.SQL标准的授权默认不做登录校验,需要自定义实现
5.SQL标准的授权需要自定义实现超级权限
拓展:
(1) hive.security.authorization.manager to org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdConfOnlyAuthorizerFactory。这将确保由hive-cli创建的任何表或视图都具有为所有者授予的默认权限。
(2)将org.apache.hadoop.hive.ql.security.authorization
.MetaStoreAuthzAPIAuthorizerEmbedOnly添加到hive.security.metastore.authorization.manager。(它需要以逗号分隔的列表,因此您可以将其与StorageBasedAuthorization参数一起添加,如果您还要启用它)。此设置不允许在远程Metastore中调用任何授权api调用。HiveServer2可以
配置为使用嵌入式Metastore,这将允许它调用Metastore授权api。Hive cli和任何其他远程Metastore用户在尝试进行授权api调用时将被拒绝授权。这会将授权api限制为特权HiveServer2进程。
(3)beeline -u jdbc:hive2://192.168.0.80:10000/default -n eagle -p [email protected]
或者 [[email protected] ~]$ beeline
beeline> !connect jdbc:hive2://192.168.0.80:10000/default muchaofeng muchaofeng