loading

Resources

26Dec 2017

解釋 Hadoop Delegation Token 上篇

2017 年12 月07 日
作者:Xiao Chen、Yongjun Zhang
原文:Cloudrea
 
本篇部落格介紹在 Hadoop Distributed File System (HDFS) Hadoop Key Management Server (KMS) 的環境中 Hadoop Delegation Tokens 的概念,並提供一些基本程式碼和疑難排解的例子。值得注意的是,Hadoop 生態系統中有許多其他服務也會使用 delegation token,但是長話短說,我們只討論 HDFS KMS
 
 
本文假設讀者瞭解 Kerberos 驗證的基本概念,才能理解驗證流程;以及瞭解 HDFS 架構 HDFS Transparent Encryption 才能瞭解什麼是 HDFS KMS。讀者若對 HDFS Transparent Encryption 不感興趣,則本文中關於 KMS 的部份可以忽略。關於 Hadoop 一般授權與驗證的前一篇部落格文章請參閱這裡
 
 
Hadoop 安全功能的簡單介紹
Hadoop 初次導入時並沒有真正的驗證功能,意味著儲存在 Hadoop 的資料可能輕易被入侵。基於下列兩個根本目標,後來透過 2010 年的 HADOOP-4487 增加了安全功能:
  1. 避免未經授權存取儲存在 HDFS 的資料
  2. 在實現 1 號目標時不增加太多成本。
為了達成第一個目標,我們必須確保
  • 存取叢集的任何用戶端均經驗證,確保他們所宣稱的身份屬實。
  • 叢集的任何伺服器均經驗證,確實屬於該叢集。
 
為了這個目標,基本的驗證服務選擇採用 Kerberos。新增其他機制如 Delegation Token、Block Access Token、Trust 等可補足 Ker-beros。尤其是引進了 Delegation Token 來達成第二個目標 (請看下一小節瞭解其方法)。下方簡圖解說 HDFS 環境中如何使用 Kerberos 和 Delegation Token (其他服務情況相同):
 
Figure 1: Simplified Diagram of HDFS Authentication Mechanisms
圖 1HDFS 驗證機制的簡圖
 
 
 
在上述簡單的 HDFS 範例中,使用了若干驗證機制:
  • 最終使用者 (joe) 可以使用 Kerberos 與 HDFS NameNode 通訊
  • 最終使用者 (joe) 提交的所分發的任務可以使用 joe 的 Delega-tion Token 存取 HDFS NameNode。
本文接下來將專門討論這個主題
  • HDFS DataNodes 使用 Kerberos 與 HDFS NameNode 通訊
  • 最終使用者和所分發的任務可以使用 Block Access Token 存取 HDFS DataNodes。
 
我們會在本文末的使用 Token 的其他方法中簡短介紹上述一些機制。要閱讀 Hadoop 安全設計的更多細節,請參閱 HADOOP-4487的設計文件以及 Hadoop Security 架構簡報
 
 
什麼是 Delegation Token?
雖然理論上可以單獨使用 Kerberos 進行驗證,但是在諸如 Hadoop 這種分散式系統中使用時,它本身也有問題。比如每一個 MapRe-duce 工作,如果所有工作節點的任務必須使用委派的 TGT (Ticket Granting Ticket) 透過 Kerberos 進行驗證,則 Kerberos Key Distri-bution Center (KDC) 會很快變成瓶頸。下圖的紅線說明了上述問題:一個工作可能要進行數千個節點對節點的通訊,造成同樣龐大的 KDC 流量。事實上,它會不小心演變成對極大型叢集中的 KDC 進行分散式阻絕服務攻擊
 
 Figure 2: Simplified Diagram Showing The Authentication Scaling Problem in Hadoop 

2:簡圖顯示 Hadoop 的驗證擴展問題

 
 
於是引進了 Delegation Token 作為簡易型驗證方法來補足 Kerberos 驗證。Kerberos 是三方通訊協定;相反的,Delegation Token 驗證是兩方的驗證通訊協定。
 
Delegation Token 的運作方式如下:
  1. 用戶端一開始會透過 Kerberos 驗證每個伺服器,並從該伺服器取得一個 Delegation Token。
  2. 該用戶端使用 Delegation Token 而不是 Kerberos 進行該伺服器的後續驗證。
 
用戶端可以也經常把 Delegation Token 傳遞給其他服務 (例如 YARN),好讓其他服務 (例如映射器 mapper 和化簡器 reducer) 可以進行驗證,並代表用戶端執行工作。換言之,用戶端可以把憑證「委派」(delegate) 給這些服務。Delegation Token 有逾期時間且必須定期更新才能保持有效性。不過,他們不能無止境更新,它有最長使用壽命。在它逾期之前,Delegation Token 也可以取消。
 
使用 Delegation Token 便不需要分發 Kerberos TGT 或是 keytab,因為 TGT 或 keytab 若被入侵便能存取所有服務。另一方面,Delegation Token 與其相關的服務緊密連結且最終會逾期,萬一洩漏的話損失較少。再者,Delegation Token 讓憑證更新變得更簡便。因為所設計的更新方式,唯有更新者和服務會參與更新程序。Token 本身保持不變,所以已經使用 token 的各方均不需要更新。
 
為了顧及可用性,Delegation Token 由伺服器持續保存。HDFS NameNode 把 Delegation Token 保存在它的中繼資料 (即 fsimage 和編輯日誌)。KMS 以 ZNode 的形式把 Delegation Token 保存在 Apache ZooKeeper。這樣一來,即使伺服器重新啟動或容錯移轉時,Delegation Token 仍可使用。
 
伺服器和用戶端在處理 Delegation Token 時有不同的責任。下方兩個小節將說明其中細節。
 
 
伺服器端的 Delegation Token
伺服器 (即圖 2 的 HDFS NN 及 KMS) 負責:
  • 派發 Delegation Token,以及儲存它們供驗證使用。
  • 根據請求更新 Delegation Token。
  • 移除 Delegation Token,或因為用戶端取消之,或是因為 token 逾時。
  • 針對所儲存的 Delegation Token 去審核所提供的 Delegation Token,藉此驗證用戶端。
 
Hadoop 的 Delegation Token 之產生與審核按照 HMAC 機制。Delegation Token 以 hashmap 形式儲存在伺服器端,而公開資訊是金鑰,私密資訊是數值。
 

公開資訊以識別碼物件的形式用於token 識別。它包含:

種類

token 種類(HDFS_DELEGATION_TOKEN 或kms-dt)。token 也含有種類,與識別碼種類相符。

擁有者

擁有token 的使用者。

更新者

可以更新token 的使用者。

真實使用者

唯有擁有者是模擬使用者時才相關。若是該token 由模擬的使用者建立,便會識別出那位模擬的使用者。

 例如,當oozie 模擬使用者joe 時,擁有者會是joe 而真實使用者是oozie。

派發日期

派發token 的epoch 時間。

最長日期

直至token 可更新為止的時間。

順序號碼

識別token 的UUID。

主要金鑰ID

用來建立和檢驗token 的主要金鑰之ID。

表1:Token 識別碼(Delegation Token 的公開部份)

 
私密資訊則是由AbstractDelegationTokenSecretManager的DelegationTokenInformation 類別為代表,它對安全十分重要且包含下列欄位:
 
renewDate
預計更新token 的epoch 時間。
 若是小於目前時間,則表示token 已逾期。
password
作為Token 識別碼的HMAC 所計算出來的密碼,使用主要金鑰作為HMAC 金鑰。
 它用來驗證由用戶端提供給伺服器的Delegation Token。
trackingId
追蹤識別碼可以橫跨多個用戶端工作階段聯結一個token 的使用率。
 它是作為token 識別碼的MD5 進行運算。

表2:Delegation Token 資訊(Delegation Token 的私密部份)
 
 
請注意,表1 的主要金鑰ID,就是伺服器上的主要金鑰之ID。主要金鑰可用來產生每一個Delegation Token。它會按照設定好的時間間隔來回作業,絕不會離開伺服器。
 
伺服器也可以透過設定來指定更新間隔(預設是24 小時),這也是Delegation Token 的逾時時間。逾期的Delegation Token 不能進行驗證,然後伺服器有一道背景執行緒會從伺服器的token 儲存庫移除逾期的Delegation Token。
 
唯有Delegation Token 的更新者可以在逾期之前更新該token。成功更新後會延長Delegation Token 的逾期時間至另一個更新間隔,直至它的最長使用壽命結束(預設是7 天)。
附錄A的表格顯示組態名稱以及它們在HDFS 和KMS 的預設值。
 
 
用戶端的Delegation Token
用戶端負責:
  • 向伺服器請求新的Delegation Token。請求token 時可以指定更新者。
  • 更新Delegation Tokens (若用戶端指定本身為「更新者」,或是要求另一方(指定的「更新者) 更新Delegation Token。
  •  請求伺服器取消Delegation Token。
  • 交出一個Delegation Token 來驗證伺服器。
用戶端可看見的Token 類別之定義請參閱這裡。下表說明Token 中包含哪些內容。
識別碼
Token 識別碼,與伺服器端的公開資訊相符。
密碼
密碼,與伺服器端的密碼相符。
種類
Token 種類(例如HDFS_DELEGATION_TOKEN 或kms-dt),它與識別碼的種類相符。
服務
服務的名稱(例如HDFS 的是ha-hdfs:,而KMS 則是:)。
更新者
可以更新token 的使用者(例如yarn)。
 
表3:用戶端的Delegation Token
 
 
下個小節會說明如何使用Delegation Token 進行驗證。
 
以下是提交工作時之日誌記錄的片段範例。INFO 日誌記錄含有所有服務的token。在下列範例中,我們看到一個HDFS Delegation Token 以及一個KMS Delegation Token。
 

$ hadoop jar /opt/cloudera/parcels/CDH/jars/hadoop-mapreduce-examples-2.6.0-cdh5.13.0.jar pi 2 3

Number of Maps  = 2

Samples per Map = 3

Wrote input for Map #0

Wrote input for Map #1

Starting Job

17/10/22 20:50:03 INFO client.RMProxy: Connecting to ResourceManager at example.cloudera.com/172.31.113.88:8032

17/10/22 20:50:03 INFO hdfs.DFSClient: Created token for xiao: HDFS_DELEGATION_TOKEN owner=xiao@GCE.CLOUDERA.COM, renewer=yarn, realUser=, issueDate=1508730603423, maxDate=1509335403423, sequenceNumber=4, masterKeyId=39 on ha-hdfs:ns1

17/10/22 20:50:03 INFO security.TokenCache: Got dt for hdfs://ns1; Kind: HDFS_DELEGATION_TOKEN, Service: ha-hdfs:ns1, Ident: (token for xiao: HDFS_DELEGATION_TOKEN owner=xiao@GCE.CLOUDERA.COM, renewer=yarn, realUser=, issueDate=1508730603423, maxDate=1509335403423, sequenceNumber=4, masterKeyId=39)

17/10/22 20:50:03 INFO security.TokenCache: Got dt for hdfs://ns1; Kind: kms-dt, Service: 172.31.113.88:16000, Ident: (kms-dt owner=xiao, renewer=yarn, realUser=, issueDate=1508730603474, maxDate=1509335403474, sequenceNumber=7, masterKeyId=69)

 
對於想要編寫 Java 程式碼來進行驗證的讀者,可參考附錄 B 的程式碼範例。
 
 
範例:Delegation Token 的生命週期
現在我們已瞭解什麼是 Delegation Token,便來看看它在實務中如何運。下圖顯示執行一個典型應用程式的驗證流程範例,其中工作透過 YARN 提交,然後再分發給叢集中多個工作節點來執行。
 
 Figure 3: How Delegation Token is Used for Authentication In A Typical Job
 
3:典型工作的驗證如何運用 Delegation Token 
 
 
長話短說,Kerberos 驗證步驟及任務分發的詳細資料皆省卻。
圖中顯示一般的 5 個步驟:
  1.  用戶端要在叢集執行一個工作。它從 HDFS NameNode 取得 HDFS Delegation Token,以及從 KMS 取得 KMS Delegation Token
  2. 用戶端把工作提交至 YARN Resource Manager (RM),傳遞它剛取得的 Delegation Token 以及 ApplicationSubmissionContext
  3. YARN RM 會馬上更新 Delegation Token,藉此檢驗它的有效性。然後它啟動 ( Delegation Token 一起) 分發到叢集的工作節點的工作。
  4. 每個工作節點在存取 HDFS 資料時會使用 HDFS Delegation Token HDFS 進行驗證,當它們在加密區解密 HDFS 檔案時則使用 KMS Delegation Token KMS 進行驗證。
  5. 在完成工作後,RM 會取消該工作的 Delegation Token
 
注意:上述圖表並未繪出的一個步驟,就是 RM 也會追蹤每個 Delegation Token 的逾期時間,並在 Delegation Token 的逾期時間到達 90% 時進行更新。請注意,RM 會追蹤每一個 Delegation Token,而不是依 Token 種類進行追蹤。這樣,更新間隔各不相同的 token 全都可以正確更新。使用 Java ServiceLoader 可導入 Token 更新者類別,所以 RM 不需要留意 token 種類。讀者若有極大興趣者,可參閱
 
 
 
這個 InvalidToken 錯誤是什麼?
我們現在知道 Delegation Token 是什麼以及在執行典型工作時如何使用它們。但是這還不是全部!讓我們看看應用程式日誌記錄中一些與 Delegation Token 相關的典型錯誤訊息,並來探究它們到底有什麼意思。
 
 
Token 已逾期
有時候,應用程式的錯誤狀況是 AuthenticationException,內含一個 InvalidToken 異常狀況。該異常狀況的訊息表示「token 已逾期」。猜猜看發生這個錯誤的原因?
 

….

17/10/22 20:50:12 INFO mapreduce.Job: Job job_1508730362330_0002 failed with state FAILED due to: Application application_1508730362330_0002 failed 2 times due to AM Container for appattempt_1508730362330_0002_000002 exited with  exitCode: -1000

For more detailed output, check application tracking page:https://example.cloudera.com:8090/proxy/application_1508730362330_0002/Then, click on links to logs of each attempt.

Diagnostics: org.apache.hadoop.security.authentication.client.AuthenticationException: org.apache.hadoop.security.token.SecretManager$InvalidToken: token (kms-dt owner=xiao, renewer=yarn, realUser=, issueDate=1508730603474, maxDate=1509335403474, sequenceNumber=7, masterKeyId=69) is expired, current time: 2017-10-22 20:50:12,166-0700 expected renewal time: 2017-10-22 20:50:05,518-0700

….

Caused by: org.apache.hadoop.security.authentication.client.AuthenticationException: org.apache.hadoop.security.token.SecretManager$InvalidToken: token (kms-dt owner=xiao, renewer=yarn, realUser=, issueDate=1508730603474, maxDate=1509335403474, sequenceNumber=7, masterKeyId=69) is expired, current time: 2017-10-22 20:50:12,166-0700 expected renewal time: 2017-10-22 20:50:05,518-0700

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

at org.apache.hadoop.crypto.key.kms.KMSClientProvider.call(KMSClientProvider.java:535)

 
 
文章後續 詳見[ 解釋 Hadoop Delegation Token 下篇 ]

Back to list.
Prev
用改頭換面的方式部署 Cloudera EDH 叢集 - 第一部份
用改頭換面的方式部署 Cloudera EDH 叢集 - 第一部份
Next
解釋 Hadoop Delegation Token 下篇
解釋 Hadoop Delegation Token 下篇