Kubernetes 身份管理:身份驗證
摘要:使用 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
推薦閱讀:
在看點一下
寫留言