天天看點

gitlab 将管理者權限移交給ldap賬戶_HDFS權限管理

概述

作為分布式檔案系統,HDFS實作了一套相容POSIX的檔案權限模型,包括粗粒度的POSIX UGO模型和細粒度的POSIX ACLs協定。

用戶端在每次進行檔案操作時,HDFS會從使用者身份認證、使用者組映射和資料通路鑒權三個環節進行驗證: 用戶端的操作請求會首先從本地系統擷取使用者名,然後服務端将使用者名比對上組資訊,最後檢視所通路的資料是否已經授權給該使用者。一旦這個流程中的某個環節出現異常,用戶端的操作請求便會失敗。

本文以Hadoop 3.1.1版本為例,介紹 HDFS 權限管理的相關内容以及權限配置設定的應用實踐。

使用者身份認證

使用者身份認證并不屬于HDFS的範疇,也就是說HDFS并不負責使用者身份的合法性檢查,它隻是會依賴相關系統來擷取使用者身份,進而用于後續的鑒權。而對于身份認證,完全取決于其采用的認證系統。目前HDFS有支援兩種使用者身份認證:簡單認證和kerberos認證。

簡單認證

基于用戶端程序所在的Linux/Unix系統的目前使用者名來進行認證。隻要使用者能正常登入作業系統就認證成功。這樣用戶端與NameNode互動時,會将使用者的登入賬号(與whoami指令輸出一緻)作為合法使用者名傳給Namenode。 這樣的認證機制存在惡意使用者可以僞造其他人的使用者名的風險,對資料安全造成極大的隐患,線上生産環境一般不會使用。

kerberos認證

kerberos是一個網絡認證協定,其使用密鑰加密技術為用戶端和服務端應用提供強認證功能。它有一個管理端(AdminServer)用于管理所有需要認證的賬号資訊,另外還有若幹的密鑰分發伺服器(KDC)用于提供認證和分發密鑰服務。 使用者從 Kerberos 管理者處擷取對應的 Kerberos 賬号名或者密鑰檔案,然後通過 kinit 等方式認證Kerberos,拿到TGT(ticket-granting-ticket)票據。用戶端會将TGT資訊傳輸到NN端,NN在擷取到認證資訊後,将principle首部截取出來作為用戶端的使用者名。例如使用 todd/[email protected]認證成功後, da作為principle的首部會作為該用戶端的使用者名使用。 使用Kerberos可以極大增強HDFS的安全性,特别是在多租戶的生産環境下。

使用者組映射

因為HDFS采用與Linux/Unix系統類似的檔案權限模型,也就是UGO模型,分成使用者、組和其他,是以在拿到使用者名後,NN會通過擷取該使用者所對應的組清單。HDFS中組的擷取是通過外部Group Mapping服務來擷取,目前社群對使用者到組的映射有主要有兩種實作方式:1)使用系統自帶的方案(即NameNode伺服器上的使用者組系統),2)使用三方服務如LDAP,通過參數hadoop.security.group.mapping來進行設定。下面重點講解下這兩種實作方式。

基于Linux/Unix系統的使用者群組實作

Linux/Unix 系統上的使用者和使用者組資訊存儲在/etc/passwd 和 /etc/group 檔案中。預設情況下,HDFS 會使用org.apache.hadoop.security.ShellBasedUnixGroupsMapping服務,其原理是在NN上調用Shell 指令groups來擷取使用者的組清單。 此方案的優點在于組映射服務十分穩定,不易受外部服務的影響。但是使用者和使用者組管理需要root權限,同時會在伺服器上生成大量的使用者組,後續管理,特别是自動化運維方面會有較大影響。

基于LDAP資料庫的使用者群組實作

OpenLDAP是一個開源LDAP的資料庫,可以通過phpLDAPadmin等管理工具或相關接口友善地添加使用者和修改使用者組。HDFS通過配置org.apache.hadoop.security.LdapGroupsMapping來使用 LDAP 服務,可以通過接口來直接擷取到某個使用者的組清單。使用LDAP的不足在于需要保障LDAP服務的可用性和性能。

資料授權(資料權限管理)

UGO權限管理
  • HDFS的檔案權限與Linux/Unix系統的UGO模型類似,我們使用FS Shell檢視目錄,可以看到如下内容:
drwxrwxrwt   - yarn   hadoop          0 2020-01-20 15:42 /app-logs
drwxr-xr-x   - yarn   hadoop          0 2020-01-20 15:40 /ats
drwxr-xr-x   - hdfs   hdfs            0 2020-01-20 15:40 /hdp
drwxr-xr-x   - mapred hdfs            0 2020-01-20 15:40 /mapred
drwxrwxrwx   - mapred hadoop          0 2020-01-20 15:40 /mr-history
drwxrwxrwx   - hdfs   hdfs            0 2020-01-20 15:41 /tmp
drwxr-xr-x   - hdfs   hdfs            0 2020-01-20 15:40 /user
drwxr-xr-x   - hdfs   hdfs            0 2020-01-20 15:40 /warehouse
           
  • 但是與傳統的POSIX模式相比,HDFS沒有setuid和setgid實作
  • 與Linux/Uninx類似,HDFS在目錄中也可以設定粘連位(Sticky bit)。 通過設定粘連位可以讓不同的使用者共享特定目錄的讀寫權限,而隻有子目錄的屬主才有删除權限。類似linux下/tmp目錄一般設定粘連位,hdfs也應該将/tmp目錄設定粘連位來共享讀寫而限制随便删除,通過hdfs dfs -chmod o+t /tmp設定後如下:
drwxrwxrwt   - hdfs      hdfs          0 2016-10-11 05:14 /tmp
           

/tmp下面的一些子目錄的權限如下:

drwxr-xr-x   - hdfs  hdfs          0 2020-02-12 15:47 /tmp/entity-file-history
drwxr-x---   - hive  hdfs          0 2020-02-14 22:30 /tmp/hive
drwxr-x---   - spark hdfs          0 2020-02-14 22:28 /tmp/spark
           
  • 與Linux/Unix類似,HDFS也提供了umask掩碼,用于設定在HDFS中預設建立的檔案和目錄權限位。為了配合使用者組的權限限制,建議将其設定成027。配置如下:
<property>
   
           

注意:這個umask配置是用戶端可以配置的,即用戶端自己主宰建立檔案或目錄的權限。

關于022和027的解釋:如果umask是022(預設值),那麼新檔案的模式就是644,新目錄的模式就是755,即umask擦除掉了group和other的寫權限。如果umask是027,那麼新檔案的模式就是650,新目錄的模式就是750,即umask擦除掉了group的寫權限,以及other的讀寫執行權限。

  • HDFS也有與linux/uinx系統root賬号類似的超級使用者。預設來說,隻有啟動Namenode程序的使用者才有超級使用者權限,也就是hdfs使用者。但很多操作實際上都需要超級使用者的權限(如fsck等),故HDFS也可以配置超級使用者組,除了部分操作(如hdfs dfsadmin -report指令)對使用者名有限制之外,所有在該使用者組裡面的使用者都可以以超級使用者權限來操作HDFS。開啟超級使用者組的參數如下:
<property>
    
           

注意:必須在NN節點上将使用者添加到superusergroup。

UGO 權限相關操作
  1. hadoop fs -chmod 750 /user/dw_dev/foo
  2. hadoop fs -chown dw_dev:hdfs /user/dw_dev/foo
  3. hadoop fs -chgrp hdfs /user/dw_dev/foo
ACLs權限管理

除了支援傳統的POSIX權限模型之外,HDFS還支援POSIX ACLs (Access Control Lists)。ACLs增強了傳統的權限模型,通過為特定的使用者或組設定不同的權限來控制對HDFS檔案的通路,即可以做到更加靈活和細粒度的權限控制:允許使用者為使用者群組的任意組合定義通路控制,而不是單個使用者(所有者)或單個組。

預設情況下對ACLs的支援是關閉的,可以通過設定dfs.namenode.acls.enabled為true來打開。

ACLs應用場景

HDFS使用UGO這種使用者組的權限管理模型可以滿足大多數場景的安全性要求,但對于一些複雜場景無法勝任,實際企業應用中存在如下問題:

對于一個目錄,可能會有兩種權限需求,一種是隻讀,一種是讀寫,但使用者組權限隻能設定為其中之一;
           
ACL規則定義

一條ACL規則由若幹ACL條目組成,每個條目指定一個使用者或使用者組的權限位。ACL條目由類型名,可選名稱和權限字元串組成,以:為分隔符。

user::rw-
user:bruce:rwx                  #effective:r--
group::r-x                      #effective:r--
group:sales:rwx                 #effective:r--
mask::r--
other::r--
           

第一部分由固定的類型名構成,有user,group,other,mask,default等選項。mask條目會過濾掉所有命名的使用者和使用者組,以及未命名的使用者組權限。第二部分可以指定類型名稱,如使用者名,使用者組名等(other類型不需要名稱),這部分是可選項,若不指定特定的使用者名或使用者組,則表示隻對該檔案屬主或目錄的使用者組生效。第三部分就是權限位。 若該條規則應用到foo檔案,foo檔案的屬主有讀寫權限,foo檔案的使用者組有隻讀和執行權限(對于目錄),其他使用者也是隻讀權限;但bruce使用者的權限經過mask過濾後隻有隻讀權限,sales組也是隻讀權限。

user::rwx
group::r-x
other::r-x
default:user::rwx
default:user:bruce:rwx          #effective:r-x
default:group::r-x
default:group:sales:rwx         #effective:r-x
default:mask::r-x
default:other::r-x
           

default類型是一個特殊的類型,且隻應用在目錄上,用于在建立子目錄和檔案時為其應用該預設的ACL規則。權限複制發生在檔案産生之時,在這之後對父級目錄的ACL操作,不會影響子目錄已存在的ACL規則。 另外每個ACL規則都有mask條目,如果使用者在設定ACL時沒有顯式聲明,那麼系統會自動地添加一條mask規則。在含有ACL規則的檔案上通過chmod變更權限會改變mask值。因為mask要作為一個過濾器來更有效地限制所有的擴充ACL條目,如果僅僅改變組條目,這會導緻Other部分的ACL規則出現缺漏。

當設定了ACL規則之後,目錄或檔案的權限位後面會出現一個“+”号,如下:

drwxrwx---+  - hive hadoop          0 2020-02-13 03:12 /warehouse/tablespace/managed/hive
           

ACL相關操作

1.檢視目錄權限

hadoop fs -setfacl /user/dw_dev
           

2.為目錄添加通路權限

hadoop fs -setfacl -m user:public:r-x /user/dw_dev
           

3.為目錄添加可繼承的權限

hadoop fs -setfacl -m default:user:public:r-x,default:group:public:r-x,default:other::r-x /user/dw_dev
           

4.删除目錄權限

hdfs dfs -setfacl -b /user/dw_dev
           

5.删除特定權限,保留其他權限

hdfs dfs -setfacl -x user:public:r-x /user/dw_dev
           

資料鑒權(資料通路權限檢查)

以HDFS Client為例,來分析下HDFS鑒權的過程

gitlab 将管理者權限移交給ldap賬戶_HDFS權限管理

在hdfs client分析:hdfs dfs -ls一文中,我們已經知道client在建立出FileSystem對象後,就會去調用fs.listStatus方法去列取目錄資訊。listStatus底層是通過RPC調用到NameNode的listStatus方法,那麼ls的鑒權肯定就是在NameNode的listStatus方法中進行的了。

進入DistributedFileSystem.listStatus方法

//DistributedFileSystem.java
           

再進入listStatusInternal(p)

//DistributedFileSystem.java
           

再進入dfs.listPaths(src, HdfsFileStatus.EMPTY_NAME)

//DFSClient.java 
           

再進入listPaths(src, startAfter, false)

//DFSClient.java
           

namenode.getListing最終是調用到了NameNodeRPCServer端了

//NameNodeRpcServer.java
           

進入namesystem.getListing

DirectoryListing 
           

終于看到AccessControlException出現了,看來getListingInt

static 
           

先來看下fsd.getPermissionChecker()

FSPermissionChecker 
           

看到remoteUser資訊是從RPC連接配接中擷取到的。

接下來看鑒權的過程fsd.isPermissionEnabled()

在NameNodeServer端擷取到了remoteUGI後,就是和path的ugi資訊做比對了,很簡單,就不一步步的分析了。

參考文檔

HDFS Permissions Guide

Hadoop Groups Mapping

【Linux】了解setuid()、setgid()和sticky位 - puyangsky - 部落格園

Linux SetUID(SUID)檔案特殊權限用法詳解

Linux SetGID(SGID)檔案特殊權限用法詳解

Linux Stick BIT(SBIT)檔案特殊權限用法詳解

HDFS Extended ACLs

繼續閱讀