天天看點

KubeCube 使用者管理與身份認證

KubeCube (https://kubecube.io) 是由網易數帆近期開源的一個輕量化的企業級容器平台,為企業提供 kubernetes 資源可視化管理以及統一的多叢集多租戶管理功能。KubeCube 社群将通過系列技術文章解讀 KubeCube 的設計特點和技術實作,幫助開發者和使用者更快地了解和上手 KubeCube。本文是第三篇,重點介紹 KubeCube 中使用者管理與身份認證的實作方案。

所有 Kubernetes 叢集都有兩類使用者:由 Kubernetes 管理的服務賬号和普通使用者。 Kubernetes 假定普通使用者是由一個與叢集無關的服務通過以下方式之一進行管理的: 負責分發私鑰的管理者 類似 Keystone 或者 Google Accounts 這類使用者資料庫 包含使用者名和密碼清單的檔案 有鑒于此,Kubernetes 并不包含用來代表普通使用者賬号的對象。 普通使用者的資訊無法通過 API 調用添加到叢集中。

根據 Kubernetes 官方所述,Kubernetes 本身并不直接提供使用者管理的特性,不支援普通使用者對象,更不存儲普通使用者的任何資訊。如果需要建立一個使用者,需要為該使用者建立私鑰和證書,通過證書進行身份認證。并且,由于不存儲使用者資訊,叢集管理者無法集中管理使用者,對其他使用者無感覺。是以,KubeCube 首先重新定義了使用者這一概念,即提供了 User 這一資源類型,存儲使用者資訊,進行使用者管理,同時友善後續的身份認證和權限校驗等。

使用者可以由管理者在前端頁面手動建立,也可以在使用外部認證第一次登入時系統自動建立。是以,使用者在注冊方式上可以分為系統普通注冊使用者和第三方授權登入使用者。但對于這兩種建立方式,都是對應在管控叢集建立相應的 User cr。然後 Warden 的資源同步管理器會将該 cr 從管控叢集同步到計算叢集,以便于後續多叢集統一認證。

這樣,在使用者管理頁面,隻需要查詢管控叢集内的 User 資源,即可實作使用者的集中管理。并且,可以輕松地添加使用者、查詢使用者以及對使用者元資訊的修改。

在 KubeCube 中,支援本地認證和外部認證。本地認證是指,在 KubeCube 中建立普通使用者,使用者再使用其建立時注冊的使用者名密碼進行登入和認證。而外部認證,是指無需建立使用者,通過第三方的認證平台認證使用者身份,進而通路 KubeCube。下面将分别介紹這兩種認證方式的實作。

在 KubeCube 中,主要是通過 JWT(JSON Web Token)進行使用者的身份認證的。

在使用本地認證登入時,使用者需要輸入使用者名和密碼。KubeCube 會根據使用者名在叢集中查詢 User cr 并比較密碼,如果查詢到 User 并且密碼一緻,視為登入成功。KubeCube 在更新使用者登入狀态後,會根據使用者名生成 JWT 并拼接成 Bearer Token,存儲在 cookie 中傳回。

KubeCube 使用者管理與身份認證

使用者登入時校驗使用者名密碼成功後的代碼如下:

使用者成功登入後,後續的每次請求,前端都會通過 cookie 帶上該 JWT進行請求,後端認證中間件再對該 JWT 進行校驗。如果有效,則會生成新的 token 傳回,循環上述過程。這樣,即使 KubeCube 中生成 JWT 的預設有效時間為1小時,隻要使用者持續通路,JWT 便會不斷重新整理使使用者始終處于登入狀态。

KubeCube 使用者管理與身份認證

認證中間件的部分代碼如下:

外部認證的實作目前主要分為3種,分别為通用認證、LDAP 認證和 OAuth2 認證。

為了友善使用者可以對接一套自己的認證系統,KubeCube 中支援了一種通用認證方式。使用者可以通過開啟通用認證方式以及配置認證系統的位址,使使用者在每一次通路 KubeCube 時,都會去自己的認證系統中進行認證。認證通過後,需要傳回給 KubeCube 該使用者的使用者名,KubeCube 依然會根據該使用者名生成對應的 Bearer Token 放在 header 中,以進行後續的權限校驗等。主要的邏輯代碼實作如下:

當使用者選擇 LDAP 登入方式時,使用者輸入使用者名和密碼。首先會檢查叢集内是否存在該使用者,并且該使用者是否為“禁用”狀态。如果不存在或存在且為正常狀态,則開始進行 LDAP 認證:

KubeCube 作為 LDAP 用戶端,擷取到使用者的使用者名和密碼,以管理者DN和管理者密碼為參數向 LDAP 伺服器發送管理者綁定請求封包以獲得查詢權限。

LDAP 伺服器收到管理者綁定請求封包後,驗證管理者DN和管理者密碼是否正确。如果管理者DN和管理者密碼正确,則向 KubeCube 發送綁定成功的管理者綁定響應封包。

KubeCube 收到綁定響應封包後,以使用者輸入的使用者名為參數構造過濾條件,向 LDAP 伺服器發送使用者DN查詢請求封包。例如:構造過濾條件為 CN=User2。

LDAP 伺服器收到使用者DN查詢請求封包後,根據封包中的查詢起點、查詢範圍、以及過濾條件,對使用者DN進行查找。如果查詢成功,則向 KubeCube 發送查詢成功的響應封包。查詢得到的使用者DN可以是一個或多個。如果得到的使用者不為一個,認為使用者名或密碼錯誤,認證失敗。

KubeCube 根據查詢得到的使用者DN和使用者輸入的密碼為參數,向 LDAP 伺服器發送使用者綁定請求封包。

LDAP 伺服器收到使用者綁定請求封包後,檢查使用者輸入的密碼是否正确。

如果使用者輸入的密碼正确,則向 KubeCube 發送綁定成功的綁定響應封包。

如果使用者輸入的密碼不正确,則向 KubeCube 發送綁定失敗的響應封包。KubeCube 以查詢到的下一個使用者DN為參數,繼續向 LDAP 伺服器發送綁定請求,直至有一個DN綁定成功。如果所有使用者DN都綁定失敗,則 KubeCube 通知使用者認證失敗。

認證成功後,和本地認證的邏輯相同:如果該使用者在叢集中未存在,則根據使用者名建立User cr; 并且根據該使用者名生成對應的 Bearer Token 存儲到 Cookie 中,在下次請求時攜帶以識别使用者身份。

KubeCube 使用者管理與身份認證

在 KubeCube 中 OAuth2 認證采用授權碼模式,因為該模式是功能最完整、流程最嚴密的授權模式。OAuth2 通常的認證流程為:

使用者通路用戶端,後者将前者導向認證伺服器。 使用者選擇是否給予用戶端授權。 假設使用者給予授權,認證伺服器将使用者導向用戶端事先指定的"重定向URI"(redirection URI),同時附上一個授權碼。 用戶端收到授權碼,附上早先的"重定向URI",向認證伺服器申請令牌。這一步是在用戶端的背景的伺服器上完成的,對使用者不可見。 認證伺服器核對了授權碼和重定向URI,确認無誤後,向用戶端發送通路令牌(access token)和更新令牌(refresh token)。

在 KubeCube 的實作中,以 GitHub 登入為例:

使用者在登入時選擇 GitHub 認證登入,前端将請求轉發給 GitHub;

GitHub 詢問使用者是否同意授權給 KubeCube;

如果使用者同意,GitHub 就會重定向回KubeCube(<code>/oauth/redirect</code>),同時發回一個授權碼(<code>code</code>);

KubeCube 使用授權碼,向 GitHub 請求令牌(<code>access_token</code>);

GitHub 傳回令牌(<code>access_token</code>);

KubeCube 使用令牌(<code>access_token</code>),向 GitHub 請求使用者資訊資料;

查詢叢集,如果該使用者不存在,則根據使用者資訊建立 User cr;

根據使用者名生成通路叢集的 Bearer Token,并傳回認證成功;

前端将 Bearer Token 存儲到 Cookie 中,在下次請求時攜帶。

基于以上的設計方案,可以輕松的推斷出,OpenAPI的認證實作,也是通過 JWT 完成。User 和每組 AK、SK進行綁定,通過AK、SK查詢到對應的 User,再通過該 User.Name 生成 Bearer Token 傳回。在下次請求時,使用者需要在 Cookie 或 header 中攜帶該 Token,KubeCube 認證中間件就可以通過該 Token 解析出使用者身份,進而完成認證。

在中間件完成身份認證後會 refresh token,但是如果直接在請求頭中攜帶該 token 請求 kube-apiserver 來完成叢集認證,則需要在部署 KubeCube 時修改 kube-apiserver 的認證後端,即修改 kube-apiserver 的配置。這會對原生的 kubernetes 叢集造成侵入,大大增加 KubeCube 的部署成本和運維成本。是以,我們需要建立另一子產品來幫助完成叢集認證——auth-proxy。

使用者對 KubeCube 進行通路請求 kubernetes 資源時,在通過認證中間件進入到透傳接口後,會走到 auth-proxy 子產品;auth-proxy 将 request 中的 Bearer Token 解析為對應的 User;再使用 User impersonation 的方式,将 request 代理發送至 kube-apiserver,即使用 “admin” 使用者僞裝成目前使用者來請求 kube-apiserver, 進而“跳過”認證,并且有利于後續鑒權。

KubeCube 的使用者管理系統主要基于 User CRD 實作;認證系統支援了本地和外部兩種認證方式,本地認證基于 JWT 實作,外部認證在第三方認證平台認證通過後同樣需要在叢集内建立一個 User cr,以進行後續的使用者管理、權限綁定等。對于叢集認證,主要使用了 Kubernetes 提供的 Impersonation 方法“跳過認證”。整體設計和實作相對簡單,秉承了 KubeCube 輕量化的設計理念。

更多資訊請參閱:

KubeCube 官網:https://www.kubecube.io/

KubeCube 源碼:https://github.com/kubecube-io/kubecube

深入解讀 KubeCube 多叢集管理

KubeCube 多級租戶模型

KubeCube 開源:簡化 Kubernetes 落地的六大特性

網易數帆更多開源項目

作者簡介: 嘉慧,網易數帆進階工程師,KubeCube 社群核心成員