元数据权限授权管理框架:Apache Sentry 集成HDFS测试使用(三)

本文已使用CDH集成了sentry未使用kerberos

Sentry的Hadoop ACL Sync

HDFS-Sentry插件允许您为特定的HDFS目录配置Sentry特权与HDFS ACL的同步。

这些客户端中,HDFS的client比较特殊;因为已经在hive中设置了sentry权限,hive本身就是访问hdfs文件,为什么还要在hdfs层再做权限控制呢?这是因为除了hive可以直接访问hdfs的文件之外,还有Map-Reduce程序,pig,spark等可以访问hdfs,所以只是在hive层面去做是不够的;
在cloudera中可以通过配置hdfs的Enable Sentry Synchronization选项来实现hive权限直接下放;比如你在hive中配置了bd这个用户可以访问sentry_test这个表;那么用bd这个用户在命令行中就可以访问/user/hive/warehouse/sentry_test目录;但是不能访问同级的其他目录以及上级目录。
Hdfs在这里的权限控制是在首先是走sentry的权限控制,如果Sentry中没有配置,才是走文件的权限控制。

内部架构

核心就是规则引擎以及Metadata Store;记录格式有两种,一种policy file记录授权内容,另外一种是通过命令方式进行授权;前者记录在策略文件中,保存形式是hdfs的一个文件;后者则是记录在数据库中,保存在关系型数据库中(通常和hive的metadata保存在一个MySQL实例中)。

HDFS-Sentry插件允许您为特定的HDFS目录配置Sentry特权与HDFS ACL的同步。
Sentry和HDFS权限的集成会自动使HDFS ACL与Sentry配置的特权保持同步。此功能提供了在Hive,Impala和其他组件(如MapReduce,Spark和Pig)之间共享数据的最简单方法,同时通过Sentry仅用一组规则设置该数据的权限。它保持了Hive和Impala在表上设置视图权限的能力,而访问Hive和Impala之外的数据(例如,从HDFS读取文件)则需要表权限。现在,Hent Metastore中定义的表中一部分或全部文件的HDFS权限将由Sentry控制。

三部分组成:
An HDFS NameNode plugin HDFS NameNode插件
A Sentry-Hive Metastore plugin Sentry-Hive Metastore插件
A Sentry Service plugin Sentry Service插件

启用同步后,Sentry会将数据库和表的权限转换为对HDFS中基础文件的相应HDFS ACL。例如,如果将一个用户组分配给对特定表具有SELECT权限的Sentry角色,则该用户组还将对该表中的HDFS文件具有读取权限。当您在HDFS中列出这些文件时,此权限将列为HDFS ACL。或者,如果将一个用户组分配给对数据库具有SELECT权限的Sentry角色,则该用户组还将对该数据库中的HDFS文件具有读取权限。当您在HDFS中列出这些文件时,这些权限也将列为HDFS ACL。

Sentry特权到HDFS ACL的映射如下:

  • SELECT特权->对文件的读取访问权限。
  • INSERT特权->对文件的写访问权。
  • ALL特权->对文件的读写访问权限。

修改路径

编辑“ Sentry同步路径前缀”属性,以列出应在其中强制执行Sentry权限的HDFS路径前缀。可以指定多个HDFS路径前缀。默认情况下,此属性指向 /用户/配置单元/仓库并 且必须始终为非空。如果您为Hive仓库使用非默认位置,请确保将其添加到路径前缀列表中。位于此处列出的HDFS区域之外的表和数据库不会发生HDFS特权同步。
重要说明: Sentry将仅管理存储Hive对象的路径。如果“ Sentry同步路径前缀”下列出了某个路径,但是那里没有Hive对象,则Sentry将不会管理该路径的权限。

在这里插入图片描述

在liunx上创建用户 tes

扫描二维码关注公众号,回复: 11427937 查看本文章

在这里插入图片描述

创建用户组 test

在这里插入图片描述

使用HUE查看角色权限
Hue权限总体上可以分为两类:一类是功能权限、一类是数据权限。
db1库与tes1库都有 t1这张表

在这里插入图片描述

test角色 对库db1只有查询的权限,给了test组
切换到用户tes,可以直接使用命令去查看hdfs上的数据

在这里插入图片描述
test角色 对库tes1只有insert插入的权限,给了test组
查看报错

在这里插入图片描述

Sentry API

(1)做组、角色、权限间的操作

含义
TSentryGroup
TSentryRole 角色
TSentryPrivilege 权限

(2)SentryPolicyServiceClient核心方法
参数

requestor  管理员

roleName   角色

groupName  用户组

db	     数据库名

table	     表

action       权限 ALL、CREATE、INSERT、REFRESH、SELECT

获取权限情况

Set<TSentryPrivilege> listAllPrivilegesByRoleName(requestor, roleName)
根据角色名获取拥有的权限

Set<TSentryRole> listRolesByGroupName(requestor, groupName)
根据组名获取拥有的权限

角色管理

client.listAllRoles(requestor)
列出所有角色

createRole(requestor, roleName)
创建角色

dropRoleIfExists(requestor, roleName)
删除角色

赋权

grantDatabasePrivilege(requestor, roleName, server, db, action.getAction())
给某角色赋某库的权限

grantTablePrivilege(requestor, roleName, server, db, table, action.getAction())
给某角色赋某表的权限

grantColumnPrivilege(requestor, roleName, server, db, table, column, action.getAction())
给某角色赋某列的权限

收权

revokeDatabasePrivilege(requestor, roleName, server, db, action.getAction())
回收某用户对于某库的权限

revokeTablePrivilege(requestor, roleName, server, db, table, action.getAction())
回收某用户对于某表的权限

revokeColumnPrivilege(requestor, roleName, server, db, table, column, action.getAction())
回收某用户对于某列的权限

关键

grantRoleToGroup(String requestorUserName, String groupName, String roleName)   
将角色赋值给用户组

java代码
在这里插入图片描述

InternalException.java


    public InternalException(String msg, Throwable cause) {
        super(msg, cause);
    }

    public InternalException(String msg) {
        super(msg);
    }
}

sentry-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-->

<!-- WARNING!!! This file is provided for documentation purposes ONLY!              -->
<!-- WARNING!!! You should copy to sentry-site.xml and make modification instead.   -->

<configuration>

    <property>
        <name>sentry.service.client.server.rpc-port</name>
        <value>8038</value>
    </property>

    <property>
        <name>sentry.service.client.server.rpc-addresses</name>
        <value>boss2</value>
    </property>

    <property>
        <name>sentry.service.client.server.rpc-connection-timeout</name>
        <value>200000</value>
    </property>

    <property>
        <name>sentry.service.server.principal</name>
        <value>sentry/_HOST@EXAMPLE.COM</value>
    </property>
    <!-- Properties required for setting the DB provider-->
    <property>
        <name>sentry.hive.provider.backend</name>
        <value>org.apache.sentry.provider.db.SimpleDBProviderBackend</value>
    </property>

    <property>
        <name>sentry.service.security.mode</name>
        <value>none</value>
    </property>

</configuration>

SentryClientTest.java


import org.apache.sentry.api.service.thrift.SentryPolicyServiceClient;
import org.apache.sentry.core.common.exception.SentryUserException;
import org.apache.sentry.service.thrift.SentryServiceClientFactory;
import org.junit.Test;
import org.apache.sentry.api.service.thrift.TSentryRole;

import java.util.Set;

public class SentryClientTest {

    // SentryConfig类需要的sentry配置文件路径视配置文件实际存放路径而定
    private static SentryConfig sentryConfig = new SentryConfig("D:\\big-date\\apache-sentry-2.1.0-src\\apache-sentry-2.1.0-src\\sentry-service\\sentry-service-server\\src\\test\\java\\org\\apache\\sentry\\api\\utils\\sentry-site.xml");

    /**
     * 测试获取已有角色信息
     * @throws InternalException
     */
    @Test
    public void testListRoles() throws InternalException {
        SentryServiceClient client = null;
        try {
            client = new SentryServiceClient();
            // 这里为了测试方便,使用hive管理员作为请求用户,来获取所有角色信息
            //SentryPolicyServiceClient client = SentryServiceClientFactory.create(conf);
            //Set<TSentryRole> roles = client.listAllRoles("hive");
            //Set<TSentryRole> roles = client.get().listAllRoles("hive");
            //Set<TSentryRole> roles = client.get().listRolesByGroupName("hive","user1");
            Set<TSentryRole> roles = client.get().listAllRoles("hive");
            for (TSentryRole role : roles) {
                System.out.println(role);
            }
        } catch (InternalException | SentryUserException e) {
            e.printStackTrace();
        } finally {
            client.close();
        }
    }

    /**
     * 删除已有角色信息
     * @throws InternalException
     */
    @Test
    public void testDropRoleIfExists() throws InternalException {
        SentryServiceClient client = null;
        try {
            client = new SentryServiceClient();
            client.get().dropRoleIfExists("hive","dread");
        } catch (InternalException | SentryUserException e) {
            e.printStackTrace();
        } finally {
            client.close();
        }
    }


    /**
     * Wrapper around a SentryPolicyServiceClient.
     * TODO: When SENTRY-296 is resolved we can more easily cache connections instead of
     * opening a new connection for each request.
     */
    static class SentryServiceClient implements AutoCloseable {
        private final SentryPolicyServiceClient client_;

        /**
         * Creates and opens a new Sentry Service thrift client.
         */
        public SentryServiceClient() throws InternalException {
            client_ = createClient();
        }

        /**
         * Get the underlying SentryPolicyServiceClient.
         */
        public SentryPolicyServiceClient get() {
            return client_;
        }

        /**
         * Returns this client back to the connection pool. Can be called multiple times.
         */
        public void close() throws InternalException {
            try {
                client_.close();
            } catch (Exception e) {
                throw new InternalException("Error closing client: ", e);
            }
        }

        /**
         * Creates a new client to the SentryService.
         */
        private SentryPolicyServiceClient createClient() throws InternalException {
            SentryPolicyServiceClient client;
            try {
                sentryConfig.loadConfig();
                client = SentryServiceClientFactory.create(sentryConfig.getConfig());
            } catch (Exception e) {
                throw new InternalException("Error creating Sentry Service client: ", e);
            }
            return client;
        }
    }
}

SentryConfig


import org.apache.parquet.Strings;
import org.apache.hadoop.conf.Configuration;

import java.io.File;
import java.net.MalformedURLException;

public class SentryConfig {
    // Absolute path to the sentry-site.xml configuration file.
    private final String configFile_;

    // The Sentry configuration. Valid only after calling loadConfig().
    private final Configuration config_;

    public SentryConfig(String configFilePath) {
        configFile_ = configFilePath;
        config_ = new Configuration();
    }

    /**
     * Initializes the Sentry configuration.
     */
    public void loadConfig() {
        if (Strings.isNullOrEmpty(configFile_)) {
            throw new IllegalArgumentException("A valid path to a sentry-site.xml config " +
                    "file must be set using --sentry_config to enable authorization.");
        }

        File configFile = new File(configFile_);
        if (!configFile.exists()) {
            String configFilePath = "\"" + configFile_ + "\"";
            throw new RuntimeException("Sentry configuration file does not exist: " +
                    configFilePath);
        }

        if (!configFile.canRead()) {
            throw new RuntimeException("Cannot read Sentry configuration file: " +
                    configFile_);
        }

        // Load the config.
        try {
            config_.addResource(configFile.toURI().toURL());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Invalid Sentry config file path: " + configFile_, e);
        }
    }

    public Configuration getConfig() { return config_; }
    public String getConfigFile() { return configFile_; }
}


猜你喜欢

转载自blog.csdn.net/m0_43393325/article/details/107359139