伴魚大數據權限系統的設計與實現

伴魚早期,整個大數據倉庫下的數據基本處於裸奔狀態,沒有做任何的權限校驗與審計,用戶可以對數據爲所欲爲,這個階段主要考慮效率優先。隨着業務的發展,數據安全的重要性愈發突顯,大數據權限系統因運而生,本文將向大家介紹伴魚大數據權限系統的設計與實現。

背景

數據訪問方式

在伴魚,離線數倉下的數據主要有以下幾種訪問方式:

數據訪問渠道

上述幾類訪問方式對應的訪問渠道主要有以下幾種:

設計目標

管控與效率兩者之間是天然對立的,我們需要做的是在這之間尋求一種平衡。就目前的形式來看,我們期望達到以下目標:

調研

權限管控主要體現在兩個方面:用戶認證(authentication)與權限認證(authorization)。

用戶認證

大數據各組件支持不同的用戶認證方式,這裏主要看下我們所關注的組件支持的認證方式。

  1. Hive

HiveServer2:用戶認證支持 Kerberos、SASL、NOSASL、LDAP、PAM 和 Custom 的方式。

  1. Presto

Presto 用戶認證支持 Kerberos、LDAP 和 Password File 的方式。

  1. Hadoop

Hadoop 各組件僅支持 Kerberos 的用戶認證方式。

可見統一基於 Kerberos 的方式,可以實現全鏈路的用戶認證。Kerberos 是一個集中式的用戶認證管理框架,具備較完備的用戶認證能力,但整體運維成本較高,這與我們的期望(儘可能少的引入新的組件)相悖,因此決定採用 LDAP 的方式(目前已具備實操、運維的經驗)。也就意味着我們只是在 Hadoop 組件之上進行用戶認證,Hadoop 的各組件依舊保持沒有任何的用戶認證,用戶可以在機器節點上僞裝任意用戶對集羣中的數據進行操控,而這類方式對於非開發人員具有一定的門檻,因此也符合我們的設計目標。

權限認證

  1. Hive

HiveServer2:支持基於 SQL 標準的授權,可用於細粒度(如:列)的訪問控制。權限認證採用了插件化的實現方式,目前開源實現方案有 Apache Ranger 和 Apache Sentry,兩者基本類似,我們選擇了 Apache Ranger。

  1. Presto、Hadoop

Presto 和 Hadoop 各組件權限認證同樣採用了插件化的實現方式,可以採用 Apache Ranger 方案實現。

系統設計

當前數據鏈路各組件的關係以及權限控制如下圖所示:

我們在 Hive 的 HiveServer2 和 Presto 的 Coordinator 組件上進行了用戶認證和授權,而在 HDFS 的 NameNode 組件只進行了授權。注意到,在授權流程中 Ranger Plugin 依賴了 Hadoop Group Mapping,而它又依賴了 LDAP,關於這些關係將在下文中闡述。

用戶認證

用戶認證即對請求中的用戶名、密碼進行校驗,邏輯相對簡單。只需對相應的組件進行簡單的配置即可,如下是 HiveServer2 組件配置示例:

<property>
  <name>hive.server2.authentication</name>
  <value>LDAP</value>
</property>
<property>
  <name>hive.server2.authentication.ldap.baseDN</name>
  <value>ou=People,dc=ipalfish,dc=com</value>
</property>
<property>
  <name>hive.server2.authentication.ldap.url</name>
  <value>ldap://*****:389</value>
</property>
<property>
  <name>hive.server2.authentication.ldap.userDNPattern</name>
  <value>cn=%s,ou=bigdata_user,ou=People,dc=ipalfish,dc=com</value>
</property>

權限認證

用戶和用戶組

用戶和用戶組是權限認證的基本對象,引入用戶組的目的是爲了提升效率。設想這麼一個場景:一批用戶需要同一批庫表的權限,最直接的想法是每一個用戶都申請一遍權限,從算法的角度看,時間複雜度是 O(N) 的。如果可以抽象出用戶組的概念,這批用戶加入同一個用戶組,同時保證組內的成員可以繼承組的所有權限,那麼就可以只爲用戶組申請一次權限即可,時間複雜度降到了 O(1)。

Ranger 中 User 對應用戶,Group 對應用戶組,一個用戶可以加入多個組,它實現了 User 繼承 Group 權限的特性。權限認證時判定一項策略是否通過,會判定用戶的 User 或用戶所屬的任意一個 Group 是否在策略中配置,如有則通過。這裏引申出一個問題,用戶所屬的 Groups 如何獲取?

查閱代碼,不難發現使用 Hadoop 的 Hadoop Groups Mapping 機制。下圖爲 ranger presto plugin 部分代碼片段:

private RangerPrestoAccessRequest createAccessRequest(RangerPrestoResource resource, SystemSecurityContext context, PrestoAccessType accessType) {
String userName = null;
Set<String> userGroups = null;
   if (useUgi) {
     UserGroupInformation ugi = UserGroupInformation.createRemoteUser(context.getIdentity().getUser());
     userName = ugi.getShortUserName();
     String[] groups = ugi != null ? ugi.getGroupNames() : null;
     if (groups != null && groups.length > 0) {
       userGroups = new HashSet<>(Arrays.asList(groups));
     }
   } else {
     userName = context.getIdentity().getUser();
     userGroups = context.getIdentity().getGroups();
   }
   RangerPrestoAccessRequest request = new RangerPrestoAccessRequest(
     resource,
     userName,
     userGroups,
     accessType
   );
   return request;
 }

可以看出,使用了 org.apache.hadoop.security 包下的 UserGroupInformation 信息,這即是 Hadoop Groups Mapping 相關的實現代碼。Hadoop Groups Mapping 支持 LDAP 的方式獲取 User 和 Group 信息,我們也採用了這種方式,因此上文中提到的用戶認證流程和授權流程最終都將依賴 LDAP。

權限等級

一個數據表的不同的列具有不同的信息價值和數據敏感度,因此需要爲每一列都劃分一個權限等級,用戶申請權限是按照列的粒度進行申請。不同的權限等級對應着不同的權限審批流程,目前我們劃分了三種權限等級:P0、P1 和 P2,級別由高到低,P0 級別的列信息最敏感,因此擁有最長的審批流程。

權限策略

Ranger 的策略類型主要有兩種:Access 和 Mask。

注:所有在 Ranger Admin 配置的策略將由 Ranger Plugin 中的線程定期 Pull 至組件,並在運行時執行權限認證。

下圖展示了在權限系統申請庫 test 表 tb 下字段名爲 tid 的權限時對應的 Ranger 策略示例:

策略配置

以上從原理層面介紹了基於 Ranger 進行權限認證的幾個重要概念,通過修改相關組件的配置,即可使權限認證生效。本節將從平臺的角度看一下如何生成 Ranger 中的策略配置。

首先需要考慮權限策略初始化的問題。一張 Hive 表的權限策略必然是在表創建之後生成的,我們期望表創建時創建者能夠直接指定各列對應的權限等級,同時創建者作爲表的 Owner 直接擁有表所有列的全部權限。主要可以從兩個方向考慮:

  1. 同步創建

同步創建方案通過將建表邏輯和策略初始化邏輯包裝成一段程序,在建表成功後執行策略初始化。不幸的是,目前我們的建表渠道有多種方式,主要包括:

我們很難將所有渠道統一起來,即便最終建錶行爲可以收斂至建模平臺,但從系統邊界的角度考慮,建模和權限分屬兩個系統,權限策略的創建應當收斂至權限系統。

  1. 異步創建

異步化創建的方式需要藉助消息隊列,需要將所有的建表事件投遞至一個 Topic,權限系統後臺監聽此 Topic 消息,從而觸發策略的初始化。那麼如何捕捉全部的建表事件並投遞至一個消息隊列?這就需要藉助我們提供的「元數據中心」平臺,它統一管理了全部數據的元信息。我們的「元數據中心」平臺是在 Apache Atlas 基礎上搭建的。Apache Atlas 通過其提供的各類組件的 Atlas Hook 以此來捕捉元信息。以 Atlas Hive Hook 爲例,我們提交給 Hive 的建表信息包括附加的元信息都可以在此 Hook 中被捕捉,這些信息緊接着會被髮送至 Atlas Server 進行存儲,與此同時 Atlas Server 可以通過配置一個對外的 Topic 統一將這些消息發送至外部的監聽系統。通過這種機制,我們就達到異步初始化權限策略的目的。

值得一提的是,字段權限等級的修改有且僅能在元數據中心進行,等級的修改將影響到對應的權限策略。對於這一事件,將通過同樣的方式,被權限系統後臺監聽,並觸發相應的動作。

整個過程如下圖所示:

大數據權限系統主要劃分爲三部分:

權限整合

BI 系統可以說得上是一家公司使用最頻繁的一款數據產品,數據開發工程師、分析師在上面開發報表,產品、運營等業務方在上面查看報表。我們的 BI 系統是基於開源的 Metabase 搭建的,前文提到,Metabase 自身具備一套權限管控的機制,但實踐下來十分難用且由於沒有審批工單機制,往往需要人工線下確認,增加了溝通的成本。同時審批工作都由管理員完成,十分耗費個人的人力成本。基於此,我們決定在權限系統中整合 Metabase 相關的權限操作。

  1. 報表開發權限
    任意平臺用戶都具備報表的開發權限,但開發一個報表需要選擇一個對應的「數據源」,因此開發權限體現在對於「數據源」的權限控制上。我們在權限系統提供了「同步賬戶」的操作,用戶可以執行此操作,操作中的一個步驟就是創建數據源,使用的是其對應的用戶名和密碼,用戶開發報表時選擇自己的數據源即可,會爲該對象的 Metabase 賬戶授予此數據源的權限。

  2. 報表查看權限
    Metabase 報表權限是按照「分組」進行授權的,平臺用戶需加入某一個「分組」,然後爲此「分組」授予報表權限,用戶方可查看報表。因此「同步賬戶」時還會爲用戶或用戶組創建與之對應的「分組」,同時將其下所有成員的 Metabase 賬戶加入此「分組」。報表的權限申請提供了單獨的申請入口,用戶填入報表地址即可,工單進入不同的審批流程,審批完成則將自動爲其對應的「分組」授予權限。

Metabase 報表權限申請工單示例:

總結

本文闡述伴魚大數據權限系統的核心設計要點,目前 Presto、Hive、HDFS、Metabase 的權限都得到了收斂,工單化的申請流程極大的降低了授權申請的成本,自動化程度比較高,效果比較理想。

作者:李輝

原文:tech.ipalfish.com/blog/2021/10/07/data_access_control/

來源:伴魚技術博客

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/j_KBNn2XR0hFxS_-GBvhjw