RMDelegationTokenSecretManager 深度解析
一、核心原理
1.1 架構概述
+---------------------------------------------------------------------+
| RMDelegationTokenSecretManager |
+---------------------------------------------------------------------+
| 繼承: AbstractDelegationTokenSecretManager<RMDelegationTokenIdentifier>
| 實(shí)現: Recoverable (支持RM HA故障恢復) |
+---------------------------------------------------------------------+
| 核心職責: |
| 1. 生成/驗證 delegation token密碼 |
| 2. 管理密鑰生命周期 (密鑰滾動(dòng)) |
| 3. 令牌續期與撤銷(xiāo) |
| 4. 狀態(tài)持久化 (ZooKeeper/LevelDB) |
+---------------------------------------------------------------------+
1.2 密碼生成機制
Delegation Token的密碼基于HMAC-SHA256算法生成:
// AbstractDelegationTokenSecretManager.createPassword()
byte[] password = createPassword(identifier.getBytes(), currentKey.getKey());
生成過(guò)程:
- 令牌標識符序列化 →
identifier.getBytes()
- 使用當前Master Key的SecretKey進(jìn)行HMAC-SHA256簽名
- 生成256位(32字節)密碼
1.3 密鑰滾動(dòng)機制 (Key Rolling)
時(shí)間線(xiàn): [Key1活躍期] ----→ [Key1過(guò)期但保留用于驗證舊token] ----→ [Key1銷(xiāo)毀]
↓
[Key2成為新Key]
密鑰狀態(tài):
| 狀態(tài) | 說(shuō)明 |
currentKey | 當前用于生成新token的主密鑰 |
allKeys | 緩存所有密鑰(包含歷史密鑰用于驗證) |
expiryDate | 密鑰過(guò)期時(shí)間 = 創(chuàng )建時(shí)間 + keyUpdateInterval + tokenMaxLifetime |
滾動(dòng)觸發(fā) (通過(guò) ExpiredTokenRemover 線(xiàn)程):
// 每 keyUpdateInterval 毫秒觸發(fā)一次
if (lastMasterKeyUpdate + keyUpdateInterval < now) {
rollMasterKey(); // 滾動(dòng)到新密鑰
}
1.4 令牌生命周期
創(chuàng )建 ──→ 續期 ──→ 續期 ──→ ... ──→ 過(guò)期/撤銷(xiāo)
│ │ │
│ │ └──────── 每次續期: now + tokenRenewInterval
│ │
│ └─ 初始renewDate: now + tokenRenewInterval
│
└─ 最大生命周期: tokenMaxLifetime
關(guān)鍵約束:
tokenMaxLifetime: 令牌最大生存期 (默認7天)
tokenRenewInterval: 令牌續期間隔 (默認24小時(shí))
keyUpdateInterval: 密鑰更新間隔 (默認1天)
1.5 線(xiàn)程安全設計
使用 ReentrantReadWriteLock 保護所有狀態(tài):
private final ReentrantReadWriteLock apiLock = new ReentrantReadWriteLock(true);
// 讀操作: retrievePassword, verifyToken
apiLock.readLock().lock();
// 寫(xiě)操作: createPassword, renewToken, cancelToken
apiLock.writeLock().lock();
1.6 故障恢復 (HA支持)
實(shí)現 Recoverable 接口,RM重啟時(shí)恢復狀態(tài):
public void recover(RMState rmState) {
// 1. 恢復MasterKey
for (DelegationKey dtKey : rmState.getRMDTSecretManagerState().getMasterKeyState()) {
addKey(dtKey);
}
// 2. 恢復Token
for (Map.Entry<RMDelegationTokenIdentifier, Long> entry : rmDelegationTokens.entrySet()) {
addPersistedDelegationToken(entry.getKey(), entry.getValue());
}
}
二、核心流程圖
2.1 令牌創(chuàng )建流程
Client RM
│ │
│ getDelegationToken() │
│ ───────────────────────────────────────────────────→ │
│ │
│ 1. 創(chuàng )建RMDelegationTokenIdentifier │
│ 2. 生成序列號、設置issueDate/maxDate │
│ 3. 使用currentKey生成密碼 │
│ 4. 存儲到currentTokens │
│ 5. 持久化到StateStore │
│ │
│ Token(RMDelegationTokenIdentifier, password) │
←─────────────────────────────────────────────────────── │
2.2 令牌驗證流程
Client RM
│ │
│ RPC with Token │
│ ──────────────────────────────────→ │
│ │
│ 1. 解碼Token Identifier │
│ 2. 從currentTokens查找 │
│ 3. 驗證renewDate未過(guò)期 │
│ 4. 驗證密碼(使用masterKey重新計算比對) │
│ │
│ 允許/拒絕訪(fǎng)問(wèn) │
←─────────────────────────────────→ │
2.3 令牌續期流程
Client RM
│ │
│ renewDelegationToken() │
│ ───────────────────────────────────────────────────→ │
│ │
│ 1. 驗證token未過(guò)期 (maxDate) │
│ 2. 驗證renewer匹配 │
│ 3. 驗證密碼正確 │
│ 4. 計算新續期時(shí)間 = min(maxDate, now + renewInterval) │
│ 5. 更新currentTokens + StateStore │
│ │
│ newExpirationTime │
←─────────────────────────────────────────────────────── │
三、使用場(chǎng)景
3.1 典型場(chǎng)景: 長(cháng)時(shí)間運行的任務(wù)
場(chǎng)景描述:
- 用戶(hù)提交一個(gè)需要運行多天的MapReduce作業(yè)
- 作業(yè)期間Kerberos票據可能過(guò)期
- 用戶(hù)不希望頻繁重新登錄
解決方案:
// 1. 獲取 delegation token
Token<RMDelegationTokenIdentifier> token = rm.getDelegationToken(ugi);
// 2. 將token寫(xiě)入到作業(yè)上下文
job.getCredentials().addToken(RMDelegationTokenIdentifier.KIND_NAME, token);
// 3. 作業(yè)運行期間,YARN自動(dòng)使用token認證
// 4. 作業(yè)結束前可以手動(dòng)續期
token.renew(conf);
3.2 代理用戶(hù)場(chǎng)景 (Proxy User)
場(chǎng)景描述:
- 用戶(hù)A (realUser) 提交作業(yè),由用戶(hù)B (owner) 的服務(wù)代理執行
- 需要以用戶(hù)A的身份訪(fǎng)問(wèn)RM
// 創(chuàng )建token時(shí)指定realUser
RMDelegationTokenIdentifier identifier = new RMDelegationTokenIdentifier(owner, renewer, realUser);
3.3 YARN RM HA場(chǎng)景
場(chǎng)景描述:
- RM發(fā)生故障切換到Standby
- 新的Active RM需要繼續驗證已有token
解決方案:
- StateStore (ZooKeeper/LevelDB) 持久化:
- MasterKey集合
- 所有DelegationToken狀態(tài)
- 序列號
四、關(guān)鍵配置參數
| 配置項 | 默認值 | 說(shuō)明 |
yarn.resourcemanager.delegation.key.update-interval | 1天 | 密鑰更新間隔 |
yarn.resourcemanager.delegation.token.max-lifetime | 7天 | 令牌最大生命周期 |
yarn.resourcemanager.delegation.token.renew-interval | 24小時(shí) | 令牌續期間隔 |
yarn.resourcemanager.delegation.token.remover-scan-interval | 1小時(shí) | 過(guò)期令牌掃描間隔 |
五、安全特性總結
- 密鑰輪換: 定期滾動(dòng)主密鑰,即使當前密鑰泄露,歷史token也無(wú)法被驗證
- 密碼驗證: 使用HMAC-SHA256,密碼和密鑰不直接暴露
- 權限校驗: 只有owner或指定的renewer可以續期/撤銷(xiāo)
- 過(guò)期機制: 令牌和密鑰都有過(guò)期時(shí)間
- 持久化安全: 狀態(tài)存儲在RM的StateStore中,支持加密
六、源碼位置
- RMDelegationTokenSecretManager:
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java
- RMDelegationTokenIdentifier:
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/RMDelegationTokenIdentifier.java
- AbstractDelegationTokenSecretManager:
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java