摘要:使用 OpenID Connect 的好處是:Kubernetes 永遠不會擁有用戶的憑據,它不可能泄漏 Kubernetes 沒有的東西。refresh_token   是 Kubernetes 的 API 服務器永遠不會使用的令牌,用戶可以將它視爲 secret。

原創:Marc Boorshtein

編譯:小君君(才雲)

當你完成 Kubernetes 部署時,你應該如何安全地將它交到開發人員和管理人員手中呢?

與其他複雜的系統一樣,Kubernetes 擁有自己的安全模型來與用戶、系統進行交互。在本文中,我將介紹 Kubernetes 的一些身份驗證方案,並提供有關管理集羣訪問權限的示例和建議。

身份對 Kubernetes 意味着什麼

首先,你需要明白在 Kubernetes 中,“什麼是身份”?Kubernetes 與大多數其他系統和應用程序截然不同。它是一組 API,沒有 “Web 界面”、沒有“登錄”、“會話”或“超時”等選項框。每個 API 請求都是唯一且不同的,並且它必須包含 Kubernetes 驗證和授權請求所需的所有內容。

也就是說,你要牢記這樣一個道理:Kubernetes 的用戶不會存在於任何持久狀態中。你不需要將 Kubernetes 連接到 LDAP 目錄或 Active Directory 中,但是每個請求都必須存在一種方法可以對 Kubernetes  ASSERT(斷言)身份。我將 ASSERT 大寫,是因爲它將在後文變得十分重要。Kubernetes 不會對用戶進行身份驗證,它驗證的是斷言。

服務賬戶  

服務帳戶正好與我們剛剛提到的規則相反。Kubernetes 不存儲有關用戶的信息,但它存儲服務帳戶的信息(該信息爲任何非人的事物)。在 Kubernetes 中,與任何內容交互的東西都會被作爲服務帳戶運行。例如,如果你要提交一個非常基本的 Pod:

在部署後的 Kubernetes 中,你可以通過運行   kubectl get pod myapp-pod -o yaml   來查看它:

你會發現這裏存在   serviceAccount    serviceAccountName  屬性,這兩者都是 default。此服務帳戶由入口控制器鏈爲使用者注入,你可以在 Pod 上設置自己的服務帳戶。

服務帳戶易於創建和使用,但它們有一些缺點:

  • 服務帳戶的令牌是一個很長的字符串,需要被記錄下來。如果處理不當,它就有可能會被利用;

  • 授權服務帳戶的唯一方法是通過 RBAC 進行綁定;

  • 在服務帳戶還在使用期間時,如果一個人泄露了令牌並且未被發覺。它可能會被一直濫用,直到被處理爲止。

在日常工作中,如果你的應用程序在一個 Pod 中運行並且需要與 API 服務器通信,你就可以通過掛載到 Pod 上的一個 secret 來檢索 Pod 的服務帳戶。

通過上面示例 YAML,你會發現一個掛載的卷被添加到了 /var/run/secrets/kubernetes.io/serviceaccount 中,這其中有一個令牌文件包含 Pod 的服務帳戶令牌。你需要注意:不要將服務帳戶令牌嵌入到集羣中運行的 Pod 的 secret 或配置中!因爲這樣的做法會使得你使用旋轉令牌(rotating token)變得更加困難,並且難以管理。

用戶賬戶  

Kubernetes 不連接任何類型的用戶存儲(至少不直接連接)。這意味着在每個請求中,你必須爲 Kubernetes 提供足夠的信息以驗證調用者的身份。Kubernetes 並不關心你如何建立身份,它只關心它如何證明身份是有效的。

Kubernetes 如何知道你是誰

OpenID Connect  

OpenID Connect 是你用來驗證用戶身份的選項:

  • OpenID Connect 令牌具有短暫性。當該類令牌被攔截或泄露時,如果攻擊者得知該令牌的字符串,那麼令牌就沒用了;

  • 使用 OpenID Connect 的好處是:Kubernetes 永遠不會擁有用戶的憑據,它不可能泄漏 Kubernetes 沒有的東西;

  • OpenID Connect 提供的用戶標識不僅可以提供用戶名信息,還可以提供組信息。這使得它們通過 LDAP 目錄或外部數據庫管理訪問變得更容易(你無需爲單個用戶創建 RBAC 綁定);

  • 通過在 Kubernetes 和身份層之間添加“代理”,你可以更輕鬆地添加多種類型的身份驗證,例如多因素身份驗證;

  • 大量的開源 OpenID Connect 可以與 Kubernetes 一起使用。

OpenID Connect Primer  

在深入研究如何使用 OpenID Connect 之前,你需要先了解一下該協議:

  • OpenID Connect 是一個建立在 OAuth2 之上的斷言生成協議;

  • OAuth2 則是一個用於傳輸承載令牌授權的協議。

這兩點似乎缺少一個詞:認證!那是因爲 OpenID Connect 不是身份驗證協議。它不關心你如何進行身份驗證。如果用戶使用的是用戶名和密碼,那麼一張智能卡或許看起來真的很值得信賴,但是 OpenID Connect 是一種用於生成、檢索和刷新用戶斷言的協議。用戶如何進行身份驗證最終取決於 OpenID Connect 的實現。

OAuth2 是一個比較關鍵的協議,它可以用於傳遞令牌,但是它沒有定義令牌是什麼或如何使用。它只是定義了令牌和依賴方之間如何傳遞令牌。

Kubernetes 如何使用 OpenID Connect

圖 1 顯示了 Kubernetes 身份驗證頁面:

圖 1 Kubernetes OpenID Connect 流程

以下爲該圖的基礎知識點:

  • 用戶可以登錄到用戶身份的提供程序中;

  • 身份提供者會生成一個   id_token  和一個 refresh_token

  • id_token  可以將用戶的身份斷言爲 Kubernetes 的;

  •   id_token   過期時, refresh_token   用於生成新的 id_token

一個   id_token  是一個 JSON Web Token(JWT),它可以表示:

  • 用戶是誰;

  • 用戶所屬的組(可選);

  • 令牌有效時長;

  • 它包含一個數字簽名,用於驗證 JWT 是否未被篡改。

用戶的 ID 屬性 sub 通常是用戶的唯一標識符。用戶經常會使用 Active Directory 的登錄 ID(也稱爲 samAccountName),還有一些人更喜歡使用電子郵件地址。一般來說,這不是最佳的做法。用戶的 ID 應該是唯一的和不可變的。雖然電子郵件地址也是唯一的,但它並不總是不可變的(例如,有時名稱會更改)。

JWT 將在從   kubectl  到 Kubernetes 的每個請求上傳遞。其中 id_token   被稱爲 “承載令牌”,因爲它會授予承載者訪問權限而無需任何額外的檢查。這意味着,如果 API 調用流程中的系統泄漏此令牌,攻擊者就可以濫用該系統了。

因爲這些令牌很容易被濫用,所以它們的壽命極短。我推薦它們的使用壽命在一分鐘左右。這樣,如果當一個令牌被泄露時,即使攻擊者知道它是什麼,但是令牌也已經過期。使用此類短期令牌,最重要的是在它過期後,系統會配置一個 refresh_token   去更新你的  id_token

kubectl  知道如何通過使用 refresh_token   調用標識提供者的授權服務 URL,並更新  id_token   令牌。

refresh_token   是 Kubernetes 的 API 服務器永遠不會使用的令牌,用戶可以將它視爲 secret。該令牌用於獲取新的 JWT,此時可以使用 JWT 中新的  refresh_token 。如果   id_token  的生命週期非常短,則   refresh_token   超時與非活動超時類似,通常爲 15-20 分鐘。這樣,你的 Kubernetes 實現將符合企業中針對不活動超時的策略。使用一個   refresh_token   獲取一個新   id_token   內容比使用更長時間更安全,因爲這個 refresh_token   意味着以下內容:

  • 它只能使用一次。一旦使用,就會生成一個新的令牌;

  • 它只在用戶和身份提供者之間傳遞,在極少情況下會被泄露;

  • 如果它自己被泄漏了,就不能被用來識別你。因爲它是不透明的,所以如果沒有額外的信息,攻擊者根本不知道該如何處理它。

Kubernetes 儀表板

儀表板沒有自己的登錄系統。所有這一切都可以使用代表用戶的現有令牌。這意味着在儀表板前面放置了一個反向代理,它將 id_token 在每個請求上注入 ,然後反向代理會根據需求刷新令牌。

我應該使用哪個身份提供商

在選擇身份提供商時,Kubernetes 實際上只有兩個要求:

  • 它必須支持 OpenID Connect 發現;

  • 它提供了一種生成令牌並將其注入到 〜/.kube/config 的機制中。

只要符合以上兩個要求,你就可以使用了。因爲這種類型的身份提供商,它使你不必手動告訴 Kubernetes 不同的 URL 在哪裏,用於簽名的密鑰是什麼 ...... 將 Kubernetes 指向所有具有這種信息發現的 URL 就容易多了。因爲大多數身份提供商都支持開箱即用(通用標準)。

而關於如何從你的登錄點(通常是 Web 瀏覽器)將令牌信息添加到 〜/.kube/config 中,可以有不同的方法。

Web 瀏覽器注入 

在此模型中,所有內容都集中在你的 Web 瀏覽器上。你可以通過瀏覽器進行身份驗證,然後獲得正確設置 kubectl 客戶機的命令。例如,OpenUnison(我們自己的項目)爲你提供了一個命令,該命令可用於身份驗證後設置集羣的配置(圖 2)。

圖 2 瀏覽器令牌

你可以使用   kubectl   的內置功能從命令行配置配置文件以完成設置。

這種方法有幾個優點:

  • 瀏覽器具有最多的身份驗證選項。除了用戶名和密碼,你還可以集成 Kerberos、Multi-Factor 等;

  • 你不需要管理複雜的 Kubernetes 配置;

  • 這種方法適用於 stock kubectl 命令。

Kubectl 插件

你可以使用插件擴展   kubectl  命令。使用插件,你可以收集用戶的憑據,然後生成令牌。我看到過一些插件可以從 CLI 收集到你的憑證,還有一些插件可以啓動瀏覽器提示你登錄。從 CLI 角度來看,這種方法很好,因爲它可以讓你的 CLI 驅動你的用戶體驗。這種方法的主要缺點是需要在每個工作站上安裝插件。

下載配置

使用此方法,身份提供程序(或自定義應用程序)可以爲你提供用於下載的完整生成配置文件。但是,如果你沒有將某些內容保存到正確的位置上,就可能會產生支持問題。

選擇身份提供者後,請按照其說明進行集成,其中關鍵項是發現 URL、標識符“claim”以及組的“claim”。

X509 證書 

證書身份驗證利用客戶端(通常是 kubectl 命令)和 Kubernetes API 服務器之間的 TLS 握手,通過向 API 服務器提供證書來聲明身份。除了一個用例之外,這種方法並不是 “最佳實踐”:

  • 證書不能在 Kubernetes 中撤銷。你需要等到證書過期或重新生成整個集羣后纔可以撤銷;

  • 證書的私鑰永遠不離開生成它的安全介質。通常情況下,你會一起“獲得”密鑰對和證書;

  • 使用帶證書的組很困難,你需要將它們嵌入到 subject 中。

你可以使用 X509 證書來進行身份驗證的情形是:當你在引導集羣時,或者在緊急情況下,你的身份提供程序不可用。

大多數發行版都會爲每個主服務器部署密鑰對。因此,如果你 ssh 進入該主服務器,則可以使用它 kubectl 管理集羣。這意味着你需要鎖定對主服務器的訪問權限。

Webhook  

此方法允許你通過 webhook 集成第三方登錄或令牌系統。Kubernetes 不會告訴你 Kubernetes 如何驗證身份,而是調用 webhook 並詢問“這是誰”。

除非你是雲提供商並擁有自己的身份解決方案,否則請勿這樣做。幾乎我見過的每一個實現都變成了一個糟糕的 OpenID Connect。

帶模擬的反向代理  

這裏客戶端(kubectl 或其他)不直接與 API 服務器通信。它會與反向代理進行通信,然後反向代理會將頭部注入請求以表示用戶。這通常被當作處理高級身份驗證的一種方法,因爲從 API 服務器的角度來看,它需要的工作量最少。實施步驟如下:

  • 創建服務帳戶;

  • 授權服務帳戶進行模擬;

  • 配置反向代理以將服務帳戶和模擬標頭注入到每個請求中。

這個方案現有的標準可能會更適合用戶的需求,因爲它易於管理和維護。

如何將身份整合到 Kubernetes 中

要將身份整合到 Kubernetes 中,請遵循以下基本覈對清單:

  • 僅將服務帳戶用於系統,而不是人員;

  • 建議使用 OpenID Connect。因爲它會受到多種系統的審覈和支持,包括開源和專有系統;

  • 僅對“緊急情況”使用證書認證。

遵循這些規則,你會發現團隊中的開發人員會很樂意記住身份驗證的密碼,安防人員也會很高興地遵守合規性的要求。

--

參考文獻:

1.https://www.linuxjournal.com/content/kubernetes-identity-management-authentication

推薦閱讀:

在看點一下

寫留言

相關文章