探索Hive用户权限(二):HiveServer2安全访问Hive

目录

前言

一、提出问题:beeline登录后没有认证

二、hiveServer2的身份认证

1.自定义hiveServer2身份认证

2.测试一下

三、hive.server2.enable.doAs配置

总结


前言

我的上一篇文章探讨了用户及库表权限,文章最后也抛出一个安全隐患,即用beeline访问hiveserver2时仍然出现任意用户可以随意操作hive集群的情况。

本文目标是:用beeline访问可以进行身份认证,并且登录的用户有权限认证。以下是正文。

一、提出问题:beeline登录后没有认证

什么是HiveServer2?

官网解释:HiveServer2(HS2)是一个服务端接口,使远程客户端可以执行对Hive的查询并返回结果。目前基于Thrift RPC的实现是HiveServer的改进版本,并支持多客户端并发和身份验证。

据官网解释,hiveserver2是有身份验证的。beeline是HiveServer2的客户端,但我在上一篇文章设置了用户权限后,用beeline以下命令却能访问任意库表,这就引出了对hiveServer2身份认证的思考。

beeline -u jdbc:hive2://192.168.0.25:10000/default -n cln

 另外还要探究一个问题,进行hiveServe2身份认证后就可以以登录用户作为hive的执行用户吗?

二、hiveServer2的身份认证

HiveServer2身份认证对应的hive属性为hive.server2.authentication,该属性有6个参数,分别是:

  • NONE: 不进行身份验证检查-普通的SASL传输。任何登录者都拥有超级权限,可以对hive进行任意操作。
  • LDAP: 基于LDAP/AD身份认证。
  • KERBEROS: Kerberos/GSSAPI 认证。
  • CUSTOM: 自定义身份验证提供程序(与hive.server2.custom.authentication.class一起使用)
  • PAM: 可插拔认证模块。
  • NOSASL:  原始传输。需要任意一个用户名,不需要密码,不填写或者填写错误用户名会导致报错。

下面我们以CUSTOM认证来自定义认证逻辑:通过提前约定好的文件hive.server2.users.conf,对用户输入的用户和密码进行校验(代码参考网上的示例)。

1.自定义hiveServer2身份认证

package com.costome.hs2.auth;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.security.sasl.AuthenticationException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hive.service.auth.PasswdAuthenticationProvider;


public class CustomHiveServer2Auth implements PasswdAuthenticationProvider {
    public void Authenticate(String user, String password) throws AuthenticationException {
        boolean ok = false;
        String passMd5 = new MD5().md5(password);
        HiveConf hiveConf = new HiveConf();
        Configuration conf = new Configuration(hiveConf);
        String filePath = conf.get("hive.server2.custom.authentication.file");

        File file = new File(filePath);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
                String[] datas = tempString.split(",", -1);
                if(datas.length != 2) {
                    continue;
                }
                //ok
                if(datas[0].equals(user) && datas[1].equals(passMd5)) {
                    ok = true;
                    break;
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AuthenticationException("read auth config file error, [" + filePath + "] ..", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {}
            }
        }
        if(ok) {
            System.out.println("user [" + user + "] auth check ok .. ");
        } else {
            System.out.println("user [" + user + "] auth check fail .. ");
            throw new AuthenticationException("user [" + user + "] auth check fail .. ");
        }
    }

    //MD5加密
    static class MD5 {
        private MessageDigest digest;
        private char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        public MD5() {
            try {
                digest = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
        }

        public String md5(String str) {
            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);
        }
    }
}

上面项目如果是maven项目,下面是依赖的pom.xml(hive和hadoop的版本要与集群的匹配):

<?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>com.costome.hs2</groupId>
    <artifactId>auth</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-common</artifactId>
            <version>2.3.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>hadoop-annotations</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-common</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-yarn-api</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-yarn-common</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-yarn-server-common</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-yarn-server-resourcemanager</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>2.3.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>hadoop-auth</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-client</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-common</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-hdfs</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-mapreduce-client-core</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-yarn-api</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>hadoop-yarn-common</artifactId>
                    <groupId>org.apache.hadoop</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-client</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-server-resourcemanager</artifactId>
            <version>2.7.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

项目编译没问题后,执行以下操作:

    1)将上面的程序打包成HiveServer2Auth.jar,放到$HIVE_HOME/lib下,
    2)在hive-site.xml中设置以下参数:

<property>
<name>hive.server2.authentication</name>
<value>CUSTOM</value>
</property>
<property>
<name>hive.server2.custom.authentication.class</name>
<value>com.costome.hs2.auth.CustomHiveServer2Auth</value>
</property>
<property>
<name>hive.server2.custom.authentication.file</name>
<value>/export/hive/conf/hive.server2.users.conf</value>
</property>

    3)在件/export/hive/conf/新建文件hive.server2.users.conf,里面内容如下:   

cln,dcddb75469b4b4875094e14561e573d8(此md5值为00000通过上面md5方法算出的)

admin,dcddb75469b4b4875094e14561e573d8

    4)重启hiveserver2

2.测试一下

操作完成用beelline来测试下(测试时用beeline -u jdbcURL -n user指定用户的方式不行,只能通过下面这种方面才可以):

[hdfs@v0106-c0a8003a lib]$ beeline
beeline> !connect jdbc:hive2://192.168.0.25:10000/default
Connecting to jdbc:hive2://192.168.0.25:10000/default
Enter username for jdbc:hive2://192.168.0.25:10000/default: cln
Enter password for jdbc:hive2://192.168.0.25:10000/default: *****

0: jdbc:hive2://192.168.0.25:10000/default> select current_user();
+-------+--+
|  _c0  |
+-------+--+
| hdfs  |
+-------+--+

以上测试结果显示:

1)身份认证成功了吗?必须输入用户名(cln)密码(00000)登录且用户名或密码正确才可以操作hive,说明身份认证已经成功!(用户名和密码是从上面设置的hive.server2.users.conf文件中读取的)

2)登录用户是hive执行用户吗?通过select current_user()发现仍然是hdfs用户,说明没有成功

继续研究其他配置,发现了doAs

三、hive.server2.enable.doAs配置

hive.server2.enable.doAs设置为false,则会以起hiveServer2 daemon的admin user来执行语句,示例中为hdfs;设置为true,hiveServer2会以提交用户的身份去执行语句。

我们此doAs设置为true,在hive-site.xml中设置以下参数:

<property>
  <name>hive.server2.enable.doAs</name>
  <value>true</value> 
</property>

 重启hiveserver2,再测试:

省略beeline语句…………
0: jdbc:hive2://192.168.0.25:10000/default> select current_user();
+-------------+--+
|     _c0     |
+-------------+--+
| cln  |
+-------------+--+
1 row selected (1.868 seconds)

再次测试当前用户已经不再是超级用户hdfs,变成了登录用户,目标达到,实验成功!

基它思考:在测试时注意到hive.server2.proxy.user这个属性,效果与上面一样。执行命令:beeline -u"jdbc:hive2://192.168.0.25:10000/default;hive.server2.proxy.user=cln",也可以通过代理用户cln访问该用户有权限的表。这个属性做什么用,后面遇到再深入探讨吧。


总结

上面探讨hiveServer身份认证方式并以自定义方式为例做了测试。得出hiveServer2身份认证只是用作身份认证并不会以该身份/用户进行yarn提交,想要以登录用户作为hive的执行用户还要结合doAs配置完成。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值