伴魚大數(shù)據(jù)權(quán)限系統(tǒng)的設(shè)計與實現(xiàn)

-? ? ?前言? ? -
伴魚早期,整個大數(shù)據(jù)倉庫下的數(shù)據(jù)基本處于裸奔狀態(tài),沒有做任何的權(quán)限校驗與審計,用戶可以對數(shù)據(jù)為所欲為,這個階段主要考慮效率優(yōu)先。隨著業(yè)務(wù)的發(fā)展,數(shù)據(jù)安全的重要性愈發(fā)突顯,大數(shù)據(jù)權(quán)限系統(tǒng)因運而生,本文將向大家介紹伴魚大數(shù)據(jù)權(quán)限系統(tǒng)的設(shè)計與實現(xiàn)。

-? ? ?背景? ? -
數(shù)據(jù)訪問方式
在伴魚,離線數(shù)倉下的數(shù)據(jù)主要有以下幾種訪問方式:
Hive:有兩種方式,一是 Hive CLI,一個逐漸被淘汰的工具,但目前仍然在各種腳本中被使用。Hive CLI 是一個胖客戶端,官方推薦使用 Beeline CLI(HiveServer2 JDBC Client)替代它,并建議在生產(chǎn)環(huán)境中使用其遠程模式(輕客戶端模式)。另一個是 HiveServer2 JDBC API。
Presto:Presto JDBC API。
Hadoop:HDFS CLI。
Flink:HDFS Client API。
數(shù)據(jù)訪問渠道
上述幾類訪問方式對應(yīng)的訪問渠道主要有以下幾種:
集群節(jié)點上安裝的各類客戶端工具。
Metabase(BI 平臺):Metabase 可以配置各種「數(shù)據(jù)源」,數(shù)據(jù)報表開發(fā)時必須選擇一個對應(yīng)的「數(shù)據(jù)源」。目前我們主要使用兩類數(shù)據(jù)源:Hive 數(shù)據(jù)源(使用 HiveServer2 JDBC API 的方式)以及 Presto 數(shù)據(jù)源(使用 Presto JDBC API 的方式)。而對于開發(fā)之后的報表,Metabase 內(nèi)部實現(xiàn)了一套自己的授權(quán)方式。
離線開發(fā)平臺(DolphinScheduler,簡稱 DS):DS 同樣抽象了數(shù)據(jù)源的概念,目前主要使用的 Hive 數(shù)據(jù)源(使用 HiveServer2 JDBC API 的方式)。此外,DS 也支持 Shell 腳本類型的工作流節(jié)點,使用此類方式腳本中基本是采用 CLI 的訪問方式,本質(zhì)上要求 DS worker 節(jié)點提前安裝好各類客戶端工具。
實時開發(fā)平臺:與具體的實時任務(wù)相關(guān),主要體現(xiàn)在與 Hive 集成的任務(wù)。
設(shè)計目標
管控與效率兩者之間是天然對立的,我們需要做的是在這之間尋求一種平衡。就目前的形式來看,我們期望達到以下目標:
盡量收緊非數(shù)倉團隊的各類權(quán)限:此為核心目標。非數(shù)倉團隊訪問數(shù)據(jù)主要通過是通過 Metabase,目前針對不同的數(shù)據(jù)庫(如:Hive)都基本是使用同一個數(shù)據(jù)源,該數(shù)據(jù)源配置的擁有最高權(quán)限,導致各方都可以查看任何數(shù)據(jù)。
逐漸規(guī)范化數(shù)倉團隊數(shù)據(jù)訪問方式:逐步替換 Hive CLI 方式至 Beeline CLI。
統(tǒng)一整合權(quán)限系統(tǒng)與各相關(guān)系統(tǒng)的權(quán)限操作:在大數(shù)據(jù)權(quán)限系統(tǒng)平臺即可完成各類授權(quán)的操作。
調(diào)研
權(quán)限管控主要體現(xiàn)在兩個方面:用戶認證(authentication)與權(quán)限認證(authorization)。
用戶認證
大數(shù)據(jù)各組件支持不同的用戶認證方式,這里主要看下我們所關(guān)注的組件支持的認證方式。
Hive
HiveServer2:用戶認證支持 Kerberos、SASL、NOSASL、LDAP、PAM 和 Custom 的方式。
Presto
Presto 用戶認證支持 Kerberos、LDAP 和 Password File 的方式。
Hadoop
Hadoop 各組件僅支持 Kerberos 的用戶認證方式。
可見統(tǒng)一基于 Kerberos 的方式,可以實現(xiàn)全鏈路的用戶認證。Kerberos 是一個集中式的用戶認證管理框架,具備較完備的用戶認證能力,但整體運維成本較高,這與我們的期望(盡可能少的引入新的組件)相悖,因此決定采用 LDAP 的方式(目前已具備實操、運維的經(jīng)驗)。也就意味著我們只是在 Hadoop 組件之上進行用戶認證,Hadoop 的各組件依舊保持沒有任何的用戶認證,用戶可以在機器節(jié)點上偽裝任意用戶對集群中的數(shù)據(jù)進行操控,而這類方式對于非開發(fā)人員具有一定的門檻,因此也符合我們的設(shè)計目標。
權(quán)限認證
Hive
HiveServer2:支持基于 SQL 標準的授權(quán),可用于細粒度(如:列)的訪問控制。權(quán)限認證采用了插件化的實現(xiàn)方式,目前開源實現(xiàn)方案有 Apache Ranger 和 Apache Sentry,兩者基本類似,我們選擇了 Apache Ranger。
Presto、Hadoop
Presto 和 Hadoop 各組件權(quán)限認證同樣采用了插件化的實現(xiàn)方式,可以采用 Apache Ranger 方案實現(xiàn)。
系統(tǒng)設(shè)計
當前數(shù)據(jù)鏈路各組件的關(guān)系以及權(quán)限控制如下圖所示:

我們在 Hive 的 HiveServer2 和 Presto 的 Coordinator 組件上進行了用戶認證和授權(quán),而在 HDFS 的 NameNode 組件只進行了授權(quán)。注意到,在授權(quán)流程中 Ranger Plugin 依賴了 Hadoop Group Mapping,而它又依賴了 LDAP,關(guān)于這些關(guān)系將在下文中闡述。
用戶認證
用戶認證即對請求中的用戶名、密碼進行校驗,邏輯相對簡單。只需對相應(yīng)的組件進行簡單的配置即可,如下是 HiveServer2 組件配置示例:
hive.server2.authentication LDAP hive.server2.authentication.ldap.baseDN ou=People,dc=ipalfish,dc=com hive.server2.authentication.ldap.url ldap://*****:389 hive.server2.authentication.ldap.userDNPattern cn=%s,ou=bigdata_user,ou=People,dc=ipalfish,dc=com

-? ? ?權(quán)限認證? ? -
用戶和用戶組
用戶和用戶組是權(quán)限認證的基本對象,引入用戶組的目的是為了提升效率。設(shè)想這么一個場景:一批用戶需要同一批庫表的權(quán)限,最直接的想法是每一個用戶都申請一遍權(quán)限,從算法的角度看,時間復雜度是 O(N) 的。如果可以抽象出用戶組的概念,這批用戶加入同一個用戶組,同時保證組內(nèi)的成員可以繼承組的所有權(quán)限,那么就可以只為用戶組申請一次權(quán)限即可,時間復雜度降到了 O(1)。
Ranger 中 User 對應(yīng)用戶,Group 對應(yīng)用戶組,一個用戶可以加入多個組,它實現(xiàn)了 User 繼承 Group 權(quán)限的特性。權(quán)限認證時判定一項策略是否通過,會判定用戶的 User 或用戶所屬的任意一個 Group 是否在策略中配置,如有則通過。這里引申出一個問題,用戶所屬的 Groups 如何獲?。?/span>
查閱代碼,不難發(fā)現(xiàn)使用 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 相關(guān)的實現(xiàn)代碼。Hadoop Groups Mapping 支持 LDAP 的方式獲取 User 和 Group 信息,我們也采用了這種方式,因此上文中提到的用戶認證流程和授權(quán)流程最終都將依賴 LDAP。
權(quán)限等級
一個數(shù)據(jù)表的不同的列具有不同的信息價值和數(shù)據(jù)敏感度,因此需要為每一列都劃分一個權(quán)限等級,用戶申請權(quán)限是按照列的粒度進行申請。不同的權(quán)限等級對應(yīng)著不同的權(quán)限審批流程,目前我們劃分了三種權(quán)限等級:P0、P1 和 P2,級別由高到低,P0 級別的列信息最敏感,因此擁有最長的審批流程。
權(quán)限策略
Ranger 的策略類型主要有兩種:Access 和 Mask。
Access:正向策略。如一個數(shù)據(jù)表有三個字段,我們可以為每一字段創(chuàng)建一條 Access 策略,將申請了權(quán)限的用戶或組配置進策略即可。乍一看,這種策略即可滿足我們的需求,不過考慮這么一個場景:一個擁有 50 個字段的數(shù)據(jù)表,某一個用戶申請其中 40 個字段的權(quán)限(另外一些字段的權(quán)限等級可能屬于 P0 級別)。當想要查看表數(shù)據(jù)時,一般的寫法是「SELECT * FROM Table」,這種形式的語句在權(quán)限認證環(huán)節(jié)要求具備全部字段的權(quán)限,否則將會返回權(quán)限不足的錯誤,而我們期望是對于未授權(quán)的字段可以使用特殊的脫敏標識符打標,這就需要借助到 Ranger 提供的另一種 Mask 策略。
Mask:補充策略。該策略用于保護敏感數(shù)據(jù),對數(shù)據(jù)進行脫敏。Mask 策略是建立在 Access 策略之上的,即使用 Mask 策略優(yōu)先得具備列的 Access 策略。因此當用戶申請權(quán)限時,我們可以為用戶授予數(shù)據(jù)表全部字段的 Access 策略(只需一個策略,策略中的 column 配置成通配符 * )的權(quán)限,同時為每一個字段生成 Mask 策略,對于沒有申請權(quán)限的字段,將 User 或 Group 配置進策略即可。
注:所有在 Ranger Admin 配置的策略將由 Ranger Plugin 中的線程定期 Pull 至組件,并在運行時執(zhí)行權(quán)限認證。
下圖展示了在權(quán)限系統(tǒng)申請庫 test 表 tb 下字段名為 tid 的權(quán)限時對應(yīng)的 Ranger 策略示例:
權(quán)限申請工單

Access Policy

Mask Policy


-? ? ?策略成本? ? -
以上從原理層面介紹了基于 Ranger 進行權(quán)限認證的幾個重要概念,通過修改相關(guān)組件的配置,即可使權(quán)限認證生效。本節(jié)將從平臺的角度看一下如何生成 Ranger 中的策略配置。
首先需要考慮權(quán)限策略初始化的問題。一張 Hive 表的權(quán)限策略必然是在表創(chuàng)建之后生成的,我們期望表創(chuàng)建時創(chuàng)建者能夠直接指定各列對應(yīng)的權(quán)限等級,同時創(chuàng)建者作為表的 Owner 直接擁有表所有列的全部權(quán)限。主要可以從兩個方向考慮:
同步創(chuàng)建
同步創(chuàng)建方案通過將建表邏輯和策略初始化邏輯包裝成一段程序,在建表成功后執(zhí)行策略初始化。不幸的是,目前我們的建表渠道有多種方式,主要包括:
數(shù)據(jù)建模平臺:數(shù)據(jù)建模平臺約束了建表規(guī)范,同時收集了表的附加元信息,如表字段的權(quán)限等級,這些元信息將通過 API 傳遞至 Hive。可見,數(shù)據(jù)建模平臺本質(zhì)上是對建表操作的封裝和約束,可以實現(xiàn)同步初始化策略的目的。
CLI:指代 Beeline。由于并未完全約束用戶在建模平臺建表,開發(fā)人員可以直接在自己腳本中通過 CLI 直接建表,這種情況下表的元信息是缺失的。
我們很難將所有渠道統(tǒng)一起來,即便最終建表行為可以收斂至建模平臺,但從系統(tǒng)邊界的角度考慮,建模和權(quán)限分屬兩個系統(tǒng),權(quán)限策略的創(chuàng)建應(yīng)當收斂至權(quán)限系統(tǒng)。
異步創(chuàng)建
異步化創(chuàng)建的方式需要借助消息隊列,需要將所有的建表事件投遞至一個 Topic,權(quán)限系統(tǒng)后臺監(jiān)聽此 Topic 消息,從而觸發(fā)策略的初始化。那么如何捕捉全部的建表事件并投遞至一個消息隊列?這就需要借助我們提供的「元數(shù)據(jù)中心」平臺,它統(tǒng)一管理了全部數(shù)據(jù)的元信息。我們的「元數(shù)據(jù)中心」平臺是在 Apache Atlas 基礎(chǔ)上搭建的。Apache Atlas 通過其提供的各類組件的 Atlas Hook 以此來捕捉元信息。以 Atlas Hive Hook 為例,我們提交給 Hive 的建表信息包括附加的元信息都可以在此 Hook 中被捕捉,這些信息緊接著會被發(fā)送至 Atlas Server 進行存儲,與此同時 Atlas Server 可以通過配置一個對外的 Topic 統(tǒng)一將這些消息發(fā)送至外部的監(jiān)聽系統(tǒng)。通過這種機制,我們就達到異步初始化權(quán)限策略的目的。
值得一提的是,字段權(quán)限等級的修改有且僅能在元數(shù)據(jù)中心進行,等級的修改將影響到對應(yīng)的權(quán)限策略。對于這一事件,將通過同樣的方式,被權(quán)限系統(tǒng)后臺監(jiān)聽,并觸發(fā)相應(yīng)的動作。
整個過程如下圖所示:

大數(shù)據(jù)權(quán)限系統(tǒng)主要劃分為三部分:
Workflow State Machine:工作流狀態(tài)機,負責各級工單狀態(tài)流轉(zhuǎn)。
EventListener:負責監(jiān)聽元信息變更事件。
Deployment:負責將策略部署至 Ranger。同時,由于涉及到權(quán)限整合還有和 Metabase 的交互,將在下文闡述。
權(quán)限整合
BI 系統(tǒng)可以說得上是一家公司使用最頻繁的一款數(shù)據(jù)產(chǎn)品,數(shù)據(jù)開發(fā)工程師、分析師在上面開發(fā)報表,產(chǎn)品、運營等業(yè)務(wù)方在上面查看報表。我們的 BI 系統(tǒng)是基于開源的 Metabase 搭建的,前文提到,Metabase 自身具備一套權(quán)限管控的機制,但實踐下來十分難用且由于沒有審批工單機制,往往需要人工線下確認,增加了溝通的成本。同時審批工作都由管理員完成,十分耗費個人的人力成本?;诖耍覀儧Q定在權(quán)限系統(tǒng)中整合 Metabase 相關(guān)的權(quán)限操作。
報表開發(fā)權(quán)限
任意平臺用戶都具備報表的開發(fā)權(quán)限,但開發(fā)一個報表需要選擇一個對應(yīng)的「數(shù)據(jù)源」,因此開發(fā)權(quán)限體現(xiàn)在對于「數(shù)據(jù)源」的權(quán)限控制上。我們在權(quán)限系統(tǒng)提供了「同步賬戶」的操作,用戶可以執(zhí)行此操作,操作中的一個步驟就是創(chuàng)建數(shù)據(jù)源,使用的是其對應(yīng)的用戶名和密碼,用戶開發(fā)報表時選擇自己的數(shù)據(jù)源即可,會為該對象的 Metabase 賬戶授予此數(shù)據(jù)源的權(quán)限。報表查看權(quán)限
Metabase 報表權(quán)限是按照「分組」進行授權(quán)的,平臺用戶需加入某一個「分組」,然后為此「分組」授予報表權(quán)限,用戶方可查看報表。因此「同步賬戶」時還會為用戶或用戶組創(chuàng)建與之對應(yīng)的「分組」,同時將其下所有成員的 Metabase 賬戶加入此「分組」。報表的權(quán)限申請?zhí)峁┝藛为毜纳暾埲肟?,用戶填入報表地址即可,工單進入不同的審批流程,審批完成則將自動為其對應(yīng)的「分組」授予權(quán)限。
Metabase 報表權(quán)限申請工單示例:


-? ? ?總結(jié)? ? -
本文闡述伴魚大數(shù)據(jù)權(quán)限系統(tǒng)的核心設(shè)計要點,目前 Presto、Hive、HDFS、Metabase的權(quán)限都得到了收斂,工單化的申請流程極大的降低了授權(quán)申請的成本,自動化程度比較高,效果比較理想。
作者:李輝
來源:tech.ipalfish.com/blog/2021/10/07/data_access_control/

