一 Kubernetes集群安全
1.1 安全機制
Kubernetes通過一系列機制來實現集群的安全控制,其中包括API Server的認證授權、准入控制機制及保護敏感信息的Secret機制等。集群的安全性主要有如下目標:
- 保證容器與其所在宿主機的隔離。
- 限制容器給基礎設施或其他容器帶來的干擾。
- 最小權限原則—合理限制所有組件的權限, 確保組件只執行它被授權的行為, 通過限制單個組件的能力來限制它的權限范圍。
- 明確組件間邊界的划分。
- 划分普通用戶和管理員的角色。
- 在必要時允許將管理員權限賦給普通用戶。
- 允許擁有Secret數據(Keys、 Certs、 Passwords) 的應用在集群中運行。
二 API Server認證管理
2.1 認證安全
Kubernetes集群中所有資源的訪問和變更都是通過Kubernetes API Server的RESTAPI來實現的,因此集群安全的關鍵點就在於如何識別並認證客戶端身份(Authentication),以及隨后訪問權限的授權(Authorization)環節。
Kubernetes集群提供了3種級別的客戶端身份認證方式。
- HTTPS證書認證:此方式最嚴格,基於CA根證書簽名的雙向數字證書認證方式。
- HTTP Token認證:通過一個Token來識別合法用戶。
- HTTP Base認證:通過用戶名+密碼的方式認證。
2.2 HTTPS認證原理
此方式需要有一個CA證書,CA是PKI系統中通信雙方都信任的實體,被稱為可信第三方(TrustedThirdParty,TTP)。CA作為可信第三方的重要條件之一就是CA的行為具有非否認性。作為第三方而不是簡單的上級,就必須能讓信任者有追究自己責任的能力。
CA通過證書證實他人的公鑰信息,證書上有CA的簽名。用戶如果因為信任證書而有了損失,則證書可以作為有效的證據用於追究CA的法律責任。正是因為CA承擔責任的承諾,所以CA也被稱為可信第三方。
在很多情況下,CA與用戶是相互獨立的實體,CA作為服務提供方,有可能因為服務質量問題(例如,發布的公鑰數據有錯誤)而給用戶帶來損失。在證書中綁定了公鑰數據和相應私鑰擁有者的身份信息,並帶有CA的數字簽名;在證書中也包含了CA的名稱,以便於依賴方找到CA的公鑰,驗證證書上的數字簽名。
CA認證涉及諸多概念,比如根證書、自簽名證書、密鑰、私鑰、加密算法及HTTPS等。
如下大致為SSL協議的流程,在Kubernetes CA中認證大概包含下面幾個步驟:
- HTTPS通信雙方的服務器端向CA機構申請證書,CA機構是可信的第三方機構,它可以是一個公認的權威企業,也可以是企業自身。企業內部系統一般都用企業自身的認證系統。CA機構下發根證書、服務端證書及私鑰給申請者。
- HTTPS通信雙方的客戶端向CA機構申請證書,CA機構下發根證書、客戶端證書及私鑰給申請者。
- 客戶端向服務器端發起請求,服務端下發服務端證書給客戶端。客戶端接收到證書后,通過私鑰解密證書,並利用服務器端證書中的公鑰認證證書信息比較證書里的消息,例如,比較域名和公鑰與服務器剛剛發送的相關消息是否一致,如果一致,則客戶端認可這個服務器的合法身份。
- 客戶端發送客戶端證書給服務器端,服務端在接收到證書后,通過私鑰解密證書,獲得客戶端證書公鑰,並用該公鑰認證證書信息,確認客戶端是否合法。
- 客戶端通過隨機密鑰加密信息,並發送加密后的信息給服務端。在服務器端和客戶端協商好加密方案后,客戶端會產生一個隨機的密鑰,客戶端通過協商好的加密方案加密該隨機密鑰,並發送該隨機密鑰到服務器端。服務器端接收這個密鑰后,雙方通信的所有內容都通過該隨機密鑰加密。
上述是雙向認證SSL協議的具體通信過程,這種情況要求服務器和用戶雙方都有證書。單向認證SSL協議則不需要客戶端擁有CA證書,對於上面的步驟,只需將服務器端驗證客戶證書的過程去掉,之后協商對稱密碼方案和對稱通話密鑰時,服務器發送給客戶的密碼沒被加密即可。
2.3 HTTP Token認證原理
HTTP Token的認證是用一個很長的特殊編碼方式的並且難以被模仿的字符串—Token來表明客戶身份的一種方式。在通常情況下,Token是一個很復雜的字符串,比如我們用私鑰簽名一個字符串后的數據就可以被當作一個Token。此外,每個Token對應一個用戶名,存儲在API Server能訪問的一個文件中。當客戶端發起API調用請求時,需要在HTTP Header里放入Token,這樣一來,API Server就能識別合法用戶和非法用戶了。
2.4 HTTP Base認證原理
通常,HTTP是無狀態的,瀏覽器和Web服務器之間可以通過Cookie來進行身份識別。桌面應用程序(比如新浪桌面客戶端、SkyDrive客戶端、命令行程序)一般不會使用Cookie,若需要與Web服務器之間通信並且進行認證。則需要使用HTTP Base認證,這種認證方式是把“用戶名+冒號+密碼”用BASE64算法進行編碼后的字符串放在HTTP Request中的Header Authorization域里發送給服務端,服務端在收到后進行解碼,獲取用戶名及密碼,然后進行用戶身份鑒權。
三 API Server授權管理
3.1 授權管理概述
當客戶端發起API Server調用時,API Server內部要先進行用戶認證,然后執行用戶授權流程,即通過授權策略來決定一個API調用是否合法。對合法用戶進行授權並且隨后在用戶訪問時進行鑒權,是權限與安全系統的重要一環。
授權就是授予不同的用戶不同的訪問權限。
API Server目前支持以下幾種授權策略(通過API Server的啟動參數“--authorization-mode”設置):
- AlwaysDeny:表示拒絕所有請求,一般用於測試。
- AlwaysAllow:允許接收所有請求,如果集群不需要授權流程,則可以采用該策略,這也是Kubernetes的默認配置。
- ABAC(Attribute-BasedAccessControl):基於屬性的訪問控制,表示使用用戶配置的授權規則對用戶請求進行匹配和控制。
- Webhook:通過調用外部REST服務對用戶進行授權。
- RBAC:Role-BasedAccessControl,基於角色的訪問控制。
- Node:是一種專用模式,用於對kubelet發出的請求進行訪問控制。
API Server在接收到請求后,會讀取該請求中的數據,生成一個訪問策略對象,如果在該請求中不帶某些屬性(如Namespace),則這些屬性的值將根據屬性類型的不同,設置不同的默認值(例如,為字符串類型的屬性設置一個空字符串;為布爾類型的屬性設置false;為數值類型的屬性設置0)。然后將這個訪問策略對象和授權策略文件中的所有訪問策略對象逐條匹配,如果至少有一個策略對象被匹配,則該請求被鑒權通過,否則終止API調用流程,並返回客戶端的錯誤調用碼。
四 ABAC授權模式
4.1 ABAC授權策略
在API Server啟用ABAC模式時,需要指定授權策略文件的路徑和名稱(--authorization-policy-file=SOME_FILENAME),授權策略文件里的每一行都以一個Map類型的JSON對象進行設置,這被稱為“訪問策略對象”。通過設置訪問策略對象中的apiVersion、kind、spec屬性來確定具體的授權策略。
其中,apiVersion當前版本為abac.authorization.kubernetes.io/v1beta1;kind被設置為Policy;spec指詳細的策略設置,包括主題屬性、資源屬性、非資源屬性這三個字段。
- 主體屬性
- user(用戶名):字符串類型,該字符串類型的用戶名來源於Token文件(--token-auth-file參數設置的文件)或基本認證文件中用戶名稱段的值。
- group(用戶組):在被設置為“system:authenticated”時表示匹配所有已認證的請求,在被設置為“system:unauthenticated”時表示匹配所有未認證的請求。
- 資源屬性
- API Group(API組):字符串類型,表明匹配哪些API Group,例如extensions或*(表示匹配所有API Group)。
- namespace(命名空間):字符串類型,表明該策略允許訪問某個Namespace的資源,例如kube-system或*(表示匹配所有Namespace)。
- resource(資源):字符串類型,API資源對象,例如pods或*(表示匹配所有資源對象)。
- 非資源屬性
- nonResourcePath(非資源對象類路徑):非資源對象類的URL路徑,例如/version或/apis,*表示匹配所有非資源對象類的請求路徑,也可以設置為子路徑,/foo/*表示匹配所有/foo路徑下的所有子路徑。
- readonly(只讀標識):布爾類型,當它的值為true時,表明僅允許GET請求通過。
4.2 ABAC授權算法
API Server進行ABAC授權的算法為:在API Server收到請求之后,首先識別出請求攜帶的策略對象的屬性,然后根據在策略文件中定義的策略對這些屬性進行逐條匹配,以判定是否允許授權。如果有至少一條匹配成功,那么這個請求就通過了授權(不過還是可能在后續其他授權校驗中失敗)。
常見的策略配置如下:
- 要允許所有認證用戶做某件事,可以寫一個策略,將group屬性設置為system:authenticated。
- 要允許所有未認證用戶做某件事,可以把策略的group屬性設置為system:unauthenticated。
- 要允許一個用戶做任何事,將策略的API Group、namespace、resource和nonResourcePath屬性設置為“*”即可。
4.3 使用kubectl授權機制
kubectl使用API Server的/api和/apis端點來獲取版本信息。要驗證kubectlcreate/update命令發送給服務器的對象,kubectl需要向OpenAPI進行查詢,對應的URL路徑為/openapi/v2。
當使用ABAC授權模式時,下列特殊資源必須顯式地通過nonResourcePath屬性進行設置:
- API版本協商過程中的/api、/api/*、/apis、和/apis/*。
- 使用kubectlversion命令從服務器獲取版本時的/version。
- create/update操作過程中的/swaggerapi/*。
在使用kubectl操作時,如果需要查看發送到API Server的HTTP請求,則可以將日志級別設置為8。
4.4 常見ABAC示例
更多ABAC參考:《附007.Kubernetes ABAC授權》。
五 RBAC授權模式
見《附006.Kubernetes RBAC授權》