1. 程式人生 > >Apache Sentry實戰之旅(二)—— Sentry客戶端使用

Apache Sentry實戰之旅(二)—— Sentry客戶端使用

Apache Sentry雖然可以將HDFS、HiveImpala三個元件的許可權認證統一,但是隻能按照給組授予角色的方式來進行授權,不能直接授權給組中的使用者,顯得不太靈活。有時候為了相容已有大資料平臺的授權體系,比如只使用Sentry控制Impala服務的許可權,而不控制HiveHDFS服務的許可權,希望通過呼叫Sentry客戶端API的方式將已有的HiveHDFS服務的許可權資訊匯入到Sentry中,就需要通過呼叫Sentry API來達到這個目的。Sentry支援通過呼叫服務方式整合公司特定的資料許可權需求,提供了外調介面來動態獲得和更改許可權資訊,使我們可以同步其它大資料平臺的組織架構,複用已有的許可權模型,實現許可權資訊的統一。

環境

Impala版本:2.12.0-cdh5.16.1

Sentry版本:1.5.1-cdh5.16.1

JDK版本:jdk1.8.0_212

整合步驟

首先得確認Sentry服務端安裝好並已啟動,以下是整合步驟及測試用例。整個工程目錄如下:

1、加入maven依賴:

<dependency>
    <groupId>org.apache.sentry</groupId>
    <artifactId>sentry-provider-db</artifactId>
    <version>1.5.1-cdh5.16.1</version>
</dependency>

2、Sentry客戶端配置檔案——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>hadoop21-test1-rgtj5-tj1</value>
    </property>

    <property>
        <name>sentry.service.client.server.rpc-connection-timeout</name>
        <value>200000</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>

3、異常處理類——InternalException

public class InternalException extends Exception{

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

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

4、配置檔案載入類——SentryConfig

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_; }
}

5、測試類——SentryClientTest

public class SentryClientTest {

    // SentryConfig類需要的sentry配置檔案路徑視配置檔案實際存放路徑而定
    private static SentryConfig sentryConfig = new SentryConfig("/test/spring-boot-galaxy/bigdata-galaxy/src/test/scala/com/galaxy/bigdata/sentry/sentry-site-client.xml");

    /**
     * 測試獲取已有角色資訊
     * @throws InternalException
     */
    @Test
    public void testListRoles() throws InternalException {
        SentryServiceClient client = null;
        try {
            client = new SentryServiceClient();
            // 這裡為了測試方便,使用hadoop管理員作為請求使用者,來獲取所有角色資訊
            Set<TSentryRole> roles = client.get().listRoles("hadoop");
            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("hadoop","admin_role");
        } 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;
        }
    }
}

在該類中,定義了靜態內部類SentryServiceClient,它的主要職責是建立SentryPolicyServiceClient介面的物件,SentryPolicyServiceClient介面是Sentry與外部系統互動的視窗,它的主要方法定義如下:

可以看到,建立(create)、刪除(drop)、查詢(list)、授權(grant)和撤銷(revoke)這些與許可權有關的操作,都定義在該方法中,方法的定義一目瞭然,顧名就能思義。

6、執行SentryClientTest類,測試服務呼叫是否正常,相關操作是否成功。

參考資料

1、Impala-2.12.0-cdh5.16.1原始碼SentryPolicyService.java類中的實現。

2、測試程式碼地址:https://github.com/Viking-Bird/spring-boot-galaxy/tree/master/bigdata-galaxy/src/test/scala/com/galax