Kerberos 身份驗證在 ChunJun 中的落地實踐

數棧DTinsight發表於2022-12-16

,在古希臘神話故事中,指的是一隻三頭犬守護在地獄之門外,禁止任何人類闖入地獄之中。

那麼在現實中,Kerberos 指的是什麼呢?

一、Kerberos 介紹

01 Kerberos 是什麼

根據百度詞條釋義,Kerberos 是一種 ,用來在非安全網路中,對個人通訊以安全的手段進行身份認證。Kerberos 旨在透過金鑰加密技術為 應用程式提供身份驗證,主要用在域環境下的身份驗證。

在此之前,通常只有伺服器的運維管理人員在配置 Active Directory 之類的東西時才會接觸到 Kerberos,但隨著大資料的流行,整個 Hadoop 生態圈在安全方面對於 Kerberos 愈發依賴,同時由於 Kerberos 認證必須入侵式改造程式碼的特點,使得越來越多的大資料開發同學開始接觸到 Kerberos。

02 Kerberos 解決了什麼問題

目前用於 的驗證主要面臨兩個問題:首先是人工記憶的密碼混亂且易遺忘,一些比較簡單的密碼又容易被攻擊;其次是技術錯覺,在計算機上的輸入密碼時顯示的是一串星號,大家誤以為很安全,實際上計算機透過網路傳送密碼基本是傳送 “明文” 密碼,大部分密碼都處於 “裸奔” 狀態。

Kerberos 的出現很好的解決了這個問題,它減少了每個使用者使用整個網路時必須記住的密碼數量 —— 只需記住 Kerberos 密碼,同時 Kerberos 結合了加密和訊息完整性來確保敏感的身份驗證資料不會在網路上透明地傳送。透過提供安全的身份驗證機制,Kerberos 為終端使用者和管理員提供了明顯的好處。

03 Kerberos 基本概念

是 Kerberos 世界的使用者名稱,用於標識身份,每個使用者都會有一個 principal,如果 principal 失效或者不正確,那麼這個使用者將無法訪問任何資源。principal 主要由三部分構成:primary,instance (可選) 和 realm。

file

● primary

主體,每個 principal 都會有的組成部分,代表使用者名稱(username)或服務名(service name)。

● instance

用於服務主體以及用來建立用於管理的特殊主體。instance 用於服務主體時的一般會用於區分同一服務在不同伺服器上的服務例項,因此與 primary 組成的 principal 一般用於 server 端,如:NameNode,HiverServer2,Presto Coordinator 等。

 用來建立用於管理的特殊主體時,一般來區分同一個使用者的不同身份,如區分擔任管理員角色的 a 使用者與擔任研發的 a 使用者。

● realm

realm 是認證管理域名,用來建立認證的邊界,只有在同屬於一個認證服務的邊界內,這個認證服務才有權利認證一個使用者、主機或者服務。每個域都會有一個與之對應的 kdc 服務用於提供域內的所有服務的認證服務。

● keytab

"密碼本",包含了多個 principal 與密碼的檔案,使用者可以利用該檔案進行身份認證。

● ticket cache

客戶端與 KDC 互動完成後,包含身份認證資訊的檔案,短期有效,需要不斷 renew。

file

04 Kerberos 的認證簡介

file

參與 Kerberos 認證過程中的角色:

  1. 訪問服務的 Client;

  2. 提供服務的 Server;

  3. DC 是 Domain Controller 的縮寫,即域控制器;AD 是 Active Directory 的縮寫,即活動目錄。DC 中有一個特殊使用者叫做 krbtgt,它是一個無法登入的賬戶,是在建立域時系統自動建立的,在整個 Kerberos 認證中會多次用到它的 Hash 值去做驗證。

  4. KDC(Key Distribution Center)金鑰分發中心。在 KDC 中又分為兩個部分:Authentication Service (AS,身份驗證服務) 和 Ticket Granting Service (TGS)

  5. AD 會維護一個 Account Database (賬戶資料庫), 它儲存了域中所有使用者的密碼 Hash 和白名單,只有賬戶密碼都在白名單中的 Client 才能申請到 TGT。

05 Kerberos 詳細認證流程

1. Client with AS

客戶端(Client)向 AS(Authentication Service)傳送請求獲取 TGT(ticket grant ticket)

file

2. Client with TGS

客戶端(Client)向 TGS(Ticket Granting Service,)傳送請求獲取 ST(Service Ticke)

file

客戶端(Client)向服務端(Server)傳送認證請求進行認證,如果客戶端(Client)要求進行雙向認證,服務端(Server)額外傳送認證請求至客戶端(Client)進行認證。

file

3.Kerberos 與 JAAS 可插拔的認證模組

JAAS jdk 在 1.4 引入的一種可插拔的認證模組( Pluggable Authentication Module,PAM )的安全體系結構,這意味著可以透過改變模組,支援從一種安全協議元件無縫的切換到另一個協議元件。

同時這種體系架構定義的介面無需修改程式碼即可實現加入多種認證技術和授權機制,因為 JAAS API 定義了應用程式程式碼與實際驗證邏輯之間的抽象,這個抽象不用重新編譯現有的應用程式程式碼就可以作為登入模組的執行時替代。

這種實現方式是透過應用程式只呼叫 LoginContext 介面,而認證技術的實際提供程式則是基於 LoginModule 介面進行開發的,在執行時 LoginContext 透過讀取配置檔案確定使用哪些認證模組來對應用程式進行認證。

file

二、ChunJun 任務提交中的 Kerberos 認證

接下來我們來大家介紹下 ChunJun 任務提交中的 Kerberos 認證,我們可以參考 ChunJun 的 readme 文件中的 yarn session 部分:

file

01 Flink 提交流程中的 Kerberos

首先,我們需要啟動一個 yarn session 環境,進入 Flink 的 bin 目錄下執行 yarn-session 指令碼啟動 flink session 並使用 -t 引數上傳 ChunJun 的依賴包。

file

當我們執行 yarn-session 時,指令碼內部會呼叫 java 命令執行 FlinkYarnSessionCli 這個類的 main 方法。在 FlinkYarnSessionCli 的 main 方法中,首先需要安裝一個全過程的安全配置,然後獲得一個安裝後的上下文,並且在上下文中執行 run 方法。

file

在 run 方法中我們構建了一個 YarnClusterDescripter 物件,這個物件中封裝了 Flink 所依賴的配置檔案和 jar 包等。而後再呼叫 YarnClusterDescripter 物件的 DeploySessionClister 方法將任務提交到 yarn 叢集。至此完成了 Flink session 到 Yarn 的一個提交。

file

我們再回顧下整體的提交流程:

file

● Flink => HDFS

Flink 需要將配置檔案以及 session 所依賴的 jar 上傳至 HDFS,因此需要與 HDFS 進行通訊

● Flink => Yarn

Flink 需要向 Yarn 申請資源,因此需要與 Yarn 進行通訊

如果 Flink 配置了基於 zookeeper 的高可用,那麼 JobManager 需要在 Zookeeper 註冊 leader 節點,客戶端還需要從 Zookeeper 上的 leader 節點獲取 webMonitorUrl,因此需要與 Zookeeper 通訊

02 Flink SecurityUtils 作用於 Kerberos 認證

1.SecurityUtils.java

file

2.SecurityUtils#install 方法中首先透過 installModules 方法對 Flink 內部的安全模組進行了 install(其中包括 Hadoop、Jaas、Zookeeper 模組)

file

3.SecurityUtils#installContext 方法對安全上下文進行初始化(獲得 HadoopSecurityContext,其中包含這 hadoop 的認證憑證 ugi)

file

03 Flink Hadoop Kerberos 認證

$Flink_HOME/conf/Flink-conf.yaml

security.Kerberos.login.use-ticket-cache: 是否從你的 Kerberos ticket 快取中讀取

security.Kerberos.login.keytab: 包含使用者憑證的 Kerberos keytab 檔案的絕對路徑。

security.Kerberos.login.principal: 與 keytab 相關的 Kerberos principal 名稱。

security.Kerberos.krb5-conf.path:指定 krb5.conf 檔案的本地位置。如果定義了,這個 conf 將被掛載到 Kubernetes、Yarn 和 Mesos 的 JobManager 和 TaskManager 容器 / 桶上。注意:需要在容器內部可訪問到定義的 KDC 的地址。

security.Kerberos.login.contexts: 用逗號分隔的登入上下文列表,以提供 Kerberos 憑證(例如, Client,KafkaClient 用於 ZooKeeper 認證和 Kafka 認證的憑證)。

zookeeper.sasl.service-name: 預設為 "zookeeper"。如果 ZooKeeper quorum 配置了一個不同的服務名稱,那麼可以在這裡提供。

zookeeper.sasl.login-context-name: 預設為 "Client"。該值需要與 "security.Kerberos.login.contexts" 中配置的值之一相匹配。

file

04 ChunJun 提交流程中的 Kerberos

執行  提交任務,ChunJun-Yarn-session.sh 實際上只是對任務的指令碼路徑進行了檢查校驗,然後再執行 submit.sh 指令碼啟動任務提交程式。

file

Launcher 的 main 方法中主要對不同的任務執行模式進行區分並交給各個模式具體的任務提交類去提交任務。

file

YarnSessionClusterClientHelper 將任務的配置以及依賴的 jar 進行組裝獲得 YarnClusterDescriptor 物件。再將任務提交到對應的 Flink session 上。

file

三、ChunJun Connector 中的 Kerberos 認證

接下來為大家介紹 中的 Kerberos 認證 。

01ChunJun 外掛中的 Kerberos

以 ChunJun HDFS Connector 為例:

外掛在 openInputFormat 方法中會對任務的目標資料來源 HDFS 是否開啟了 Kerberos 進行判斷,如果開啟了 Kerberos,則會根據配置的認證檔案進行認證並獲取認證後的 ugi,ugi 可以認為是之後外掛與 HDFS 通訊的使用者憑證,裡面儲存著使用者的認證資訊.

file

02 如何進行 Kerberos 認證

● OpenInputFormat 方法

OpenInputFormat 方法是 Flink 對運算元的每個例項進行初始化是都會執行的方法,ChunJun 的 BaseRichInputFormat 也實現了該方法,我們開發外掛也都會去實現該方法。

對於每個運算元例項來說,Kerberos 認證只會進行一次(不包括認證過期後的重新整理),因此 Kerberos 認證的程式碼應該在該方法中實現.

file

● 開發 hadoop 生態中的資料來源元件

一般而言, 生態中的資料來源元件如:HDFS、HBase、Hive 等都是用 ugi(UserGroupInformation) 進行 Kerberos 認證。

ChunJun 內部也提供了相關的工具類用於獲取登入後的 ugi:com.dtstack.ChunJun.util.FileSystemUtil#getUGI

● 開發 Zookeeper、Kafka 等元件

這類元件開啟 Kerberos 認證後,使用者需要在外掛端配置 jaas.conf 檔案,再透過各個元件提供的引數配置項配置元件所選用的 jaas.conf 的 entry,即可完成 Kerberos 配置。

03 如何排查 Kerberos 認證問題

$Flink_HOME/conf/Flink-conf.yaml

#jvm 啟動引數中增加 “-Dsun.security.krb5.debug=true”

env.java.opts:用於配置啟動所有 Flink 程式的 JVM 引數

env.java.opts.jobmanager:用來配置啟動 JobManager 的 JVM 引數

env.java.opts.taskmanager:用來配置啟動 TaskManager 的 JVM 引數

env.java.opts.historyserver:用來配置啟動 HistoryServer 的 JVM 引數

env.java.opts.client:用來配置啟動 Flink Client 的 JVM 引數

04 Kerberos 認證常見問題

1.javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]

此訊息表明一個操作嘗試要求以 Kerberos 的 user/host@realm 身份認證的操作,但 票 據 cache 中沒有用於 user/host@realm 的票 據 。

使用者環境引用的策略 / 票證快取檔案丟失、不可讀(許可權)、損壞或無效票證續簽壽命設定為零

票證授予票證(TGT)不存在,因為服務 A 需要將命令作為服務 B 執行,但尚未正確配置為允許模擬服務 B

票證更新尚未執行 / 未成功。這可能是由於 CDH 5.3 之前的 HBASE 或 CDH5.2 之前的 Hive / Sentry 缺陷引起的

該使用者的憑據尚未在 KDC 中生成

執行了手動步驟,例如 hadoop fs -ls,但是使用者從未透過 Kerberos 身份驗證

Oracle JDK 6 Update 26 或更早版本無法讀取由 MIT Kerberos 1.8.1 或更高版本建立的 Kerberos 憑證快取記憶體。

某些版本的 Oracle JDK 8 可能會遇到此問題

2.javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Fail to create credential. (63) - No service creds)]

由 JDK 缺陷引起

票證訊息對於 UDP 協議而言太大

主機未正確對映到 Kerberos 領域

3.Found unsupported keytype(18)

確保正確安裝了與 JDK 相匹配的無限強度策略檔案的正確版本

確保對策略檔案(位於 jdk 目錄中,例如 /usr/java/jdk1.7.0_67-cloudera/jre/lib/security/)的許可權能夠被所有使用者讀取。

確保檔案已部署到叢集軟體正在使用的 jdk 中

有關詳細資訊,使用以下的(連結以匹配關鍵字型別號 18 在該例項中)將其加密型別 

4.GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7) - UNKNOWN_SERVER)

hostname 或要訪問的 URL 與 keytab 中列出的主機之間發生主機名不匹配。造成這種情況的原因多種多樣,包括但不限於:

多網路卡(NIC)伺服器,以使來自主機的資料包的 IP 地址與透過主機解析返回的 IP 不匹配

負載平衡器和後續的主機名解析問題

DNS 和主機名解析問題 / 不一致

反向 DNS(必需)主機名解析問題 / 不一致

在 krb5.conf 中主機正在對映到引數 [domain_realm] 的錯誤域,這或者是透過其他的 krb5.conf 配置,或者是透過 KDC 配置。預設引數情況下,除非使用 [domain_realm] 等進行顯式配置,否則主機名(例如:“ crash.EXAMPLE.com ”)將對映到域 “ EXAMPLE.com ” 。請參見 MIT Kerberos 文件:[domain_realm]

如果嘗試在 Cloudera Manager 中執行 “Generate Credentials” 步驟(在更高版本中重新命名為 “ Generate Missing Credentials ”)時發生此錯誤,則可能是由於匯入到 Cloudera Manager 資料庫中的管理員帳戶詳細資訊不再與主機匹配,例如 Cloudera Manager 伺服器的主機名在上一次匯入後隨後更改了。

影片回放 & PPT 獲取

  • 影片回看:

  • 課件獲取:

關注公眾號 “ChunJun”,後臺私信 “課件” 獲得直播課件

想了解或諮詢更多有關袋鼠雲大資料產品、行業解決方案、客戶案例的朋友,瀏覽袋鼠雲官網:

同時,歡迎對大資料開源專案有興趣的同學加入「袋鼠雲開源框架釘釘技術 qun」,交流最新開源技術資訊,qun 號碼:30537511,專案地址:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69995740/viewspace-2928395/,如需轉載,請註明出處,否則將追究法律責任。

相關文章