K8s 中的認(rèn)證機(jī)制大多都是用 ServiceAccount 來做的,雖然 K8s 有 User 的概念,但沒有一種資源與“人”對應(yīng),所以在 K8s 里做用戶管理還是很困難的。好在 K8s 對于用戶管理提供了另一種方式,即對接 OIDC 協(xié)議。本篇文章我們就來了解一下什么是 OIDC 協(xié)議,及其在 K8s 中的運(yùn)用。 OIDC 協(xié)議 OpenID Connect 協(xié)議(OIDC 協(xié)議)是基于 OAuth 2.0 協(xié)議的身份認(rèn)證標(biāo)準(zhǔn)協(xié)議,在 OAuth 2.0 上構(gòu)建了一個身份層。在介紹 OIDC 協(xié)議之前,我們先來看看 OAuth 2.0 協(xié)議。 OAuth 2.0 協(xié)議 OAuth 2.0 協(xié)議主要適用的場景是第三方應(yīng)用登錄,比如我們新登錄一個網(wǎng)站,就可以不注冊賬號,而使用 Github 賬號登錄。 OAuth 2.0 協(xié)議在客戶端和服務(wù)器之間定義了一個授權(quán)層,客戶端只需要根據(jù)獲取的 token 來認(rèn)證登錄即可,不需要存儲密碼信息。具體流程如下: 這一套流程不難理解,重點在于相比普通的賬號密碼登錄,多了一層以 code 換取 token 的步驟。 這一步看似十分多余,然而保證了安全性,因為從 OAuth Server 跳轉(zhuǎn)到 Client 這一步,code 需要放置在 URL 參數(shù)中,若直接將 token 放在 URL 參數(shù)中傳給 Client,相當(dāng)于把鑰匙公開給整個互聯(lián)網(wǎng)。所以在 OAuth 2.0 協(xié)議中,將 token 傳輸放在了后面一步,即將 token 放置在 Response body 中。 OIDC 協(xié)議的流程 總的來說,OAuth 2.0 協(xié)議只提供了授權(quán)認(rèn)證,并沒有身份認(rèn)證的功能,而這一缺陷就由 OIDC 協(xié)議補(bǔ)上了。OIDC 協(xié)議又構(gòu)建了一個身份層,具體流程如下: 可以看到,當(dāng) Client A 要求登錄時,OIDC Server 會檢測到該用戶沒有登錄,從而啟動類似 OAuth 流程的登錄過程;而當(dāng)同一個用戶在 Client B 要求登錄時,OIDC Server 會檢測到該用戶已經(jīng)登錄了,繼而開始后面的流程。 而 OIDC 的登錄過程與 OAuth 相比,最主要的擴(kuò)展就是提供了 ID Token,下面我們進(jìn)一步來熟悉一下 ID Token。 ID Token ID Token 是一個安全令牌,其數(shù)據(jù)格式滿足 JWT 格式,在 JWT 的 Payload 中由服務(wù)器提供一組用戶信息。其主要信息包括: iss(Issuer Identifier):必須。提供認(rèn)證信息者的唯一標(biāo)識。一般是一個 https 的 url(不包含q uerystring 和 fragment 部分); sub(Subject Identifier):必須。iss 提供的用戶標(biāo)識,在 iss 范圍內(nèi)唯一,它有時也會被客戶端用來標(biāo)識唯一的用戶。最長為 255 個 ASCII 字符; aud(Audiences):必須。標(biāo)識 ID Token 的受眾。必須包含 OAuth2 的 client_id; exp(Expiration time):必須。過期時間,超過此時間的 ID Token 會作廢; iat(Issued At Time):必須。JWT 的構(gòu)建時間; auth_time(AuthenticationTime):用戶完成認(rèn)證的時間; nonce:客戶端發(fā)送請求的時候提供的隨機(jī)字符串,用來減緩重放攻擊,也可以來關(guān)聯(lián) ID Token 和客戶端本身的 Session 信息; acr(Authentication Context Class Reference):可選。表示一個認(rèn)證上下文引用值,可以用來標(biāo)識認(rèn)證上下文類; amr(Authentication Methods References):可選。表示一組認(rèn)證方法; azp(Authorized party):可選。結(jié)合 aud 使用。只有在被認(rèn)證的一方和受眾(aud)不一致時才使用此值,一般情況下很少使用。 除了上述這些,ID Token 的用戶信息還可以包含其他信息,由服務(wù)器端配置。 另外 ID Token 必須進(jìn)行 JWS 簽名和 JWE 加密,從而保證認(rèn)證的完整性、不可否認(rèn)性以及可選的保密性。 K8s 中使用 OIDC 的原理 在了解了 OIDC 協(xié)議的流程及原理后,我們再來看 K8s 中使用 OIDC 的原理。 首先先來看看 K8s 中使用 OIDC 的流程: 可以看到,APIServer 本身與 OIDC Server(即 Identity Provider)并沒有太多交互,需要我們自己獲取到 ID Token 后,將其寫入 Kubectl 的配置,由 Kubectl 使用 ID Token 來與 APIServer 交互。 此外,除了 ID Token,我們還需要將 refresh Token 提供給 Kubectl,而 refresh Token 則是用來在 ID Token 過期后自動重新獲取 ID Token 的。 APIServer 拿到 ID Token 后,有以下幾個步驟: 檢查其是否 JWT 格式; 判斷 Token 是否過期(根據(jù) iat 和 exp); 該用戶對此操作是否有權(quán)限。 而 APIServer 如何根據(jù) ID Token 知道是哪個用戶的呢?這也需要我們在 APIServer 的配置中指定 ID Token 中的對應(yīng)字段。 另外需要注意的是,雖然在 OIDC Server 中可以做到用戶的權(quán)限管理,但由上述過程我們也可以發(fā)現(xiàn),K8s 并不認(rèn) OIDC Server 的權(quán)限管理。因為 K8s 已經(jīng)有一套非常完善的 RBAC 體系,我們將權(quán)限控制管理的步驟留在 K8s 集群內(nèi)就可以了。 |
|