Kerberose安裝與CDH集成
文章目錄
1.Kerberose安裝
1.1. 軟件版本
- OS: CentOS 7.5
- CDH: 5.16.1
- JDK: 8u211
1.2. 集羣角色
node1.cluster -> master節點
node[2-5].cluster -> slave節點
1.3. 安裝JCE Policy File
很多Linux系統默認使用AES-256來加密tickets,例如CentOS/Red Hat,這需要在所有的集羣節點以及Hadoop使用者的主機上安裝 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy File。
但是在JDK 8.151之後,應經默認使用了Unlimited Strength的Policy文件,所以安裝了8.151之後的JDK的話,就可以省略這一步了。
1.4. 安裝Kerberos
注:本文所有操作均在root用戶下執行。
Kerberos是CDH之外的獨立基礎設施,需要自行安裝。
- 在Master節點上安裝krb5-server和openldap-clients
yum -y install krb5-server openldap-clients
- 在所有的節點上安裝krb5-workstation和krb5-libs
yum install -y krb5-workstation krb5-libs
1.5. 配置Kerberos
注:以下所有文件在修改前先cp一個bak備份文件
- /etc/krb5.conf
/etc/krb5.conf存在於每一個Kerberos節點上,所以在master節點上編輯好該文件後需要覆蓋到集羣上的所有節點上。
/etc/krb5.conf在每臺機器上已經有一份默認配置,需要修改的是與你的集羣相關的特定信息,主要是domain, kdc服務器和admin_server服務器的地址。 以下給出一份配置參考, 其中YOUR-DOMAIN
,YOUR-KDC-SERVER
,YOUR-MASTER-SERVER
需要根據集羣的情況確定,然後查找替換即可。
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = YOUR-DOMAIN
dns_lookup_realm = false
ticket_lifetime = 24h
dns_lookup_kdc = true
renew_lifetime = 7d
forwardable = true
rdns = false
udp_preference_limit = 0
#default_ccache_name = KEYRING:persistent:%{uid}
[realms]
YOUR-DOMAIN = {
kdc = YOUR-KDC-SERVER
admin_server = YOUR-MASTER-SERVER
}
[domain_realm]
.YOUR-DOMAIN = YOUR-DOMAIN
YOUR-DOMAIN = YOUR-DOMAIN
這份配置文件中有這些幾個重要的配置項需要重點關注一下:
default_realm:Kerberos默認的領域,當整個集羣只在一個域裏時,通常這個配置項的值就是當前域。如果有多個領域,可以在 [realms] 節添加其他域。
ticket_lifetime: 憑證生效的時限,一般爲24小時,即kinit之後,23小時內憑證都是有效的。
renew_lifetime: 憑證最長可以被延期的時限,一般爲一個禮拜。當憑證過期之後,對安全認證的服務的後續訪問則會失敗。
- /var/kerberos/krb5kdc/kdc.conf
該文件是KDC的配置文件,所以只存在於kdc服務器上,以下是一份配置參考:
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
YOUR-DOMAIN = {
master_key_type = aes256-cts
max_renewable_life = 7d 0h 0m 0s
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
# note that aes256 is ONLY supported in Active Directory in a domain / forrest operating at a 2008 or greater functional level.
# aes256 requires that you download and deploy the JCE Policy files for your JDK release level to provide
# strong java encryption extension levels like AES256. Make sure to match based on the encryption configured within AD for
# cross realm auth, note that RC4 = arcfour when comparing windows and linux enctypes
# 另:在JDK 8.151版本之後,已經默認使用unlimited的policy了,不必再去單獨下載安裝JCE了
supported_enctypes = aes256-cts:normal aes128-cts:normal arcfour-hmac:normal
default_principal_flags = +renewable, +forwardable
}
同樣的,YOUR-DOMAIN需要替換成集羣實際的domain。 對於這份配置文件,有一個項配置需要特別關注,因於它是CDH要求必須配置的,即max_renewable_life
。在CDH配置Kerberos時,有一項前置條件:
KDC必須配置爲允許renewable tickets with non-zerolifetime
當max_renewable_life配置爲一個非零值時即滿足了這個條件。
- /var/kerberos/krb5kdc/kadm5.acl
一般情況下,我們並不需要編輯這個文件,因爲它默認配置的一條規則是可以滿足一般需求的,即:
*/admin@YOUR-DOMAIN *
因爲這項配置的含義是:只要principal的名字的第二部分是admin,那麼該principal就擁有管理員權限。例如後面我們要建立的cloudera-scm/admin@YOUR-DOMAIN
這個principal,就擁有管理員權限,因爲它的名字以/admin結尾。
1.6. 創建數據庫
在master節點上,執行:
kdb5_util create -r YOUR-DOMAIN -s
該命令執行完成後,會在/var/kerberos/krb5kdc/ 目錄下生成principal數據庫文件。
如果遇到數據庫已經存在的提示,可以把 /var/kerberos/krb5kdc/ 目錄下的 principal 的相關文件都刪除掉。默認的數據庫名字都是 principal。可以使用 -d指定數據庫名字。
1.7. 啓動Kerberos服務
systemctl start krb5kdc
systemctl start kadmin
systemctl enable krb5kdc
systemctl enable kadmin
1.8. 驗證安裝
服務啓動之後,我們可以通過一組添加並查看principal的命令來驗證kerberos是否已經安裝成功:
# 列出Kerberos中的所有認證用戶,即principals
kadmin.local -q "list_principals"
# 添加認證用戶,需要輸入密碼
kadmin.local -q "addprinc test-user"
# 使用該用戶登錄,獲取身份認證,需要輸入密碼
kinit test-user
# 查看當前用戶的認證信息ticket
klist
# 更新ticket
kinit -R
# 銷燬當前的ticket
kdestroy
# 刪除認證用戶
kadmin.local -q "delprinc test-user"
2. 在CDH上啓用Kerberos
當Kerberos安裝好之後,我們就可以通過CDH的Cloudera Manager來啓用Kerberos了。簡單地說,這一過程其實是讓Cloudera Manager自動地爲所有的CDH上的服務生成相應的服務主體和憑證,同時,將所有服務的身份認證機制改爲kerberos(這需要修改所有服務上安全相關的配置項,會由CM自動完成),這樣,外圍客戶端(不管是CLI工具,如hdfs dfs xxxx這樣的命令,還是java clent libary等)再連接這些服務時,必須要通過kerberos客戶端工具表明身份並認證通過之後(例如kinit xxx這樣的CLI操作)才能訪問這些服務。
CM上有專門啓用Kerberos的嚮導配置,本文不再贅述,可以參考以下兩篇文章中的截圖:
3. 創建hdfs/hive等用戶主體
CM在enable kerberos的過程中生成的全部都是“服務主體(principal)”,沒有一個是“用戶主體(principal)”,服務主體(principal)一定都帶着主機名以標識這是哪個主機上的哪個服務,例如:
hive/node1.your-domain@your-domain
hdfs/node2.your-domain@your-domain
....
服務主體都是用來標識服務的,並不是用戶可以拿來做身份認證的。比如我使用beeline連接hive時就需要明確指明要訪問的service principal是哪個,就像下面這樣:
beeline -u "jdbc:hive2://node1.your-domain:10000/default;principal=hive/node1.your-domain@your-domain"
如果用戶試圖以這些service principal的身份進行認證,你也不知道它們的密碼的,因爲它們的密碼是隨機生成的。
所以一旦服務被kerberos保護起來以後,就要建立kerberos“用戶主體”,使用用戶主體來訪問服務。以hdfs服務爲例,它的默認超級用戶是hdfs,一旦啓用kerberos,就不會再以本地OS賬號的身份進行認證了,而是看kerberos的prinpical裏有沒有這個用戶,一個很簡單的驗證方法就是:這時即時你使用節點上的linux hdfs賬號執行hdfs dfs -ls /
這樣的命令一樣會因身份認證的問題而執行失敗的。所以,我們要做的是就是在kerberos這個層面上建出hdfs的用戶主體,任何用戶,只要獲取了hdfs的憑證,那麼它就會被hdfs服務認定爲hdfs用戶,進而放權進行操作。添加用戶憑證在前面也提到過,這裏列出hdfs/hive兩個主要用戶憑證的創建命令:
kadmin.local -q "addprinc hdfs@your-domain"
kadmin.local -q "addprinc hive@your-domain"
我們從建立hdfs和hive的用戶主體這個典型的案例可以很清晰地認識到kerberos本質:在一個認證體系裏,永遠有兩個參與方:服務和使用服務的用戶,在沒有引入kerberos時,以HDFS服務爲例,它以當前Linux用戶的身份進行身份認證(其實等於沒有什麼認證動作),然後基於HDFS文件系統的權限體系(即HDFS上的文件owner,group和rwx權限 )進行權限控制。而當引入kerberos時,其實是加了一個透明的身份認證層,即,首先,“用戶”的概念已經發生了變化,不再是任何linux賬號,而是通過kerberos的addprinc建立的用戶。即使絕大多數時候人們總是會在kerberos上建立與linux賬號同名的principal,但它們完全是兩種體系下的兩碼事了。但是對於服務端來說,一個用戶就是一個確定的,唯一的用戶,一旦通過了身份認證,那麼確定就是你了,你將獲得你本該擁有的一切權限。以HDFS服務的超級賬號hdfs爲例,它就是一個賬號,當我們是使用非kerberos的方式訪問HDFS服務時,它檢查的是當前linux賬號是不是hdfs, 如果是,那這個賬號就是hdfs賬號, 當我們是使用kerberos的方式訪問HDFS服務時,它檢查的是:這是不是kerberos principal數據庫中存在的名爲hdfs的用戶主體,如果是,那麼它通過的是kerberos認證,不管是哪種方式,一旦通過了身份認證,以hdfs用戶的身份訪問到了HDFS服務後,那麼後面的權限,各種配置是完全一樣,因爲這是同一個用戶(針對於服務的那個用戶)!
對於上述的描述,在hadoop文檔中有比較官方的解釋,但不太易於理解kerberos從中扮演的角色,所以僅供參考:
Hadoop supports two different modes of operation to determine the user’s identity, specified by the hadoop.security.authentication property:
- simple
In this mode of operation, the identity of a client process is determined by the host operating system. On Unix-like systems, the user name is the equivalent of `whoami`.
- kerberos
In Kerberized operation, the identity of a client process is determined by its Kerberos credentials. For example, in a Kerberized environment, a user may use the kinit utility to obtain a Kerberos ticket-granting-ticket (TGT) and use klist to determine their current principal. When mapping a Kerberos principal to an HDFS username, all components except for the primary are dropped. For example, a principal todd/[email protected] will act as the simple username todd on HDFS.
我們可以再引申地思考一下:kerberos這種認證方式和那種頁面上使用用戶命名+密碼的認證方式的差別是什麼呢?kerberos這種認證方式很像是這樣運作的:簡化所有服務對身份認證的要求(或者說服務本身就不想或不能做身份認證),當一個用戶說他是誰的時候,系統就直接認定他是那個人,不需要提供任何密碼或憑證,以一個系統的登錄界面做比喻的話,就是這個登入對話框上只需要輸入用戶名即可,沒有密碼驗證。那到底誰來確保這個用戶就是他聲稱的那個人呢?這時我們引入kerberos認證,在用戶訪問到登入頁面之前再攔截一層,這一層是通明的,用戶可以主動地通過kinit來表明自己的身份,只要kerberos認證他通過了,後面對接的就是那個登入頁面了。
3. 創建普通用戶主體
在linux上部署和運行程序會有一些默認的約定或稱之爲最佳實踐,比如:爲一個應用創建單獨的linux賬號,使用這個賬號部署和啓動應用。如果這個應用要訪問大數據集羣的資源,比如HDFS或Yarn,那它必須也要納入kerveros體系裏,說白了,就是也要爲這個應用在kerberos上建立對應的用戶憑證。
其實就具體操作上講,創建普通用戶主體和上面提到的創建hdfs/hive用戶主體是一樣的,區別只在於: 鑑於應用是基於集羣的,Hadoop/CDH明確要求:必須在集羣上的每個節點上創建這個賬號,同時在HDFS的/user目錄下創建同名文件夾,具體的要求是:
1. 確保羣集中的所有主機都有一個linux用戶帳戶並且該帳戶的名稱與用戶的主體名稱的第一個組成部分相同。例如,如果用戶的主體名稱是 [email protected],則每個框中應存在linux帳戶joe。
2. 爲每個用戶帳戶在 HDFS 上的 /user 下創建一個子目錄(例如 /user/joe)。將該目錄的所有者和組更改爲該用戶。
上述要求源自CDH官方文檔:https://www.cloudera.com/documentation/enterprise/5-3-x/topics/cm_sg_prep_for_users_s17.html
至於爲什麼必須要在所有節點上創建賬號,我還沒有找到特別準確的解釋,雖然像hdfs/yarn這樣的賬號都是這樣做的,這和他們本來就是集羣服務有關,而如果是一個只通過客戶端訪問集羣資源的應用賬戶來說,爲什麼必須要這樣呢?期待後續能找到答案。