本文已發布超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
使用者命名空間:現在在 Alpha 版本中支援執行具狀態的 Pod!
Kubernetes v1.25 引入了僅針對無狀態 Pod 的使用者命名空間支援。在 1.27 中完成一些設計變更後,Kubernetes 1.28 解除了該限制。
此功能的優點在於
- 它很容易採用(您只需要在 Pod 規格中設定一個布林值)
- 大多數應用程式不需要任何變更
- 透過大幅增強容器的隔離並減輕評級為 HIGH 和 CRITICAL 的 CVE,提高安全性。
這篇文章解釋了使用者命名空間的基本知識,並展示了
- 最近的 Kubernetes v1.28 版本中發生的變更
- 評級為 HIGH 的漏洞示範,該漏洞在使用使用者命名空間時是不可利用的
- 使用此功能的執行階段需求
- 您可以期待未來版本中關於使用者命名空間的內容。
什麼是使用者命名空間?
使用者命名空間是 Linux 的一項功能,可將容器的使用者和群組識別碼 (UID 和 GID) 與主機上的識別碼隔離。容器中的識別碼可以映射到主機上的識別碼,這樣用於不同容器的主機 UID/GID 永遠不會重疊。更重要的是,識別碼可以映射到主機上非特權且不重疊的 UID 和 GID。這基本上意味著兩件事
由於不同容器的 UID 和 GID 映射到主機上不同的 UID 和 GID,因此容器即使逃脫容器邊界,也更難以互相攻擊。例如,如果容器 A 在主機上以與容器 B 不同的 UID 和 GID 執行,則它對容器 B 的檔案和程序可以執行的操作受到限制:僅讀取/寫入檔案允許其他人執行的操作,因為它永遠不會擁有所有者或群組的權限(保證不同容器的主機上的 UID/GID 是不同的)。
由於 UID 和 GID 映射到主機上的非特權使用者,因此如果容器逃脫容器邊界,即使它在容器內部以 root 身分執行,它在主機上也沒有任何特權。這極大地保護了它可以讀取/寫入的主機檔案、它可以向其發送訊號的程序等。
此外,授予的功能僅在使用者命名空間內有效,而在主機上無效。
如果不使用使用者命名空間,以 root 身分執行的容器在容器突破的情況下,將擁有節點上的 root 權限。如果某些功能被授予容器,則這些功能在主機上也有效。當使用使用者命名空間時,這些情況都不成立(當然,bug 除外 🙂)。
1.28 中的變更
如前所述,從 1.28 開始,Kubernetes 支援具狀態 Pod 的使用者命名空間。這表示具有使用者命名空間的 Pod 可以使用任何類型的磁碟區,它們不再像以前一樣僅限於某些磁碟區類型。
用於啟用此功能的 Feature Gate 已重新命名,不再是 UserNamespacesStatelessPodsSupport
,而是從 1.28 開始,您應該使用 UserNamespacesSupport
。進行了許多變更,並且節點主機上的需求也發生了變化。因此,在 Kubernetes 1.28 中,重新命名了功能標誌以反映這一點。
示範
Rodrigo 建立了一個示範,該示範利用 CVE 2022-0492,並展示了在沒有使用者命名空間的情況下如何發生漏洞利用。他還展示了如何無法從容器使用此漏洞利用,其中容器正在使用此功能。
此漏洞的評級為高,並允許沒有特殊權限的容器讀取/寫入主機上的任何路徑,並以 root 身分啟動主機上的程序。
如今,容器中的大多數應用程式都以 root 身分或半可預測的非 root 使用者身分 (使用者 ID 65534 是一個相當流行的選擇) 執行。當您執行 Pod 時,容器使用 userns,Kubernetes 會以非特權使用者身分執行這些容器,而您的應用程式無需進行任何變更。
這表示以使用者 65534 執行的兩個容器將有效地映射到主機上不同的使用者,從而限制了它們在逃脫時可以對彼此執行的操作,並且如果它們以 root 身分執行,則主機上的權限將降低為非特權使用者的權限。
節點系統需求
使用此功能對 Linux 核心版本以及容器執行階段都有需求。
在 Linux 上,您需要 Linux 6.3 或更高版本。這是因為該功能依賴於名為 idmap 掛載的核心功能,並且在 Linux 6.3 中合併了將 idmap 掛載與 tmpfs 搭配使用的支援。
如果您將 CRI-O 與 crun 搭配使用,則 CRI-O 1.28.1 和 crun 1.9 或更高版本支援此功能。如果您將 CRI-O 與 runc 搭配使用,則仍不支援此功能。
containerd 支援目前以 containerd 2.0 為目標;如果您將其與 crun 或 runc 搭配使用,則可能沒有關係。
請注意,containerd 1.7 新增了對 Kubernetes 1.25 和 1.26 中實作的使用者命名空間的實驗性支援。containerd 1.7 不支援在 1.27 中完成的重新設計,因此在使用者命名空間支援方面,它僅適用於 Kubernetes 1.25 和 1.26。
containerd 1.7 中存在的一個限制是,它需要在 Pod 啟動期間變更容器映像內每個檔案和目錄的所有權。這表示它具有儲存額外負荷,並且可能會顯著影響容器啟動延遲。Containerd 2.0 可能會包含一個實作,該實作將消除新增的啟動延遲和儲存額外負荷。如果您計劃在生產環境中使用 containerd 1.7 和使用者命名空間,請考慮這一點。
這些 containerd 限制都不適用於 CRI-O 1.28。
接下來是什麼?
展望 Kubernetes 1.29,計畫是與 SIG Auth 合作,將使用者命名空間整合到 Pod 安全標準 (PSS) 和 Pod 安全許可中。目前,計畫是在使用使用者命名空間時放寬 PSS 策略中的檢查。這表示如果正在使用使用者命名空間,則欄位 spec[.*].securityContext
runAsUser
、runAsNonRoot
、allowPrivilegeEscalation
和 capabilities
將不會觸發違規。行為可能會透過利用 API Server 功能閘道來控制,例如 UserNamespacesPodSecurityStandards
或類似的閘道。
我該如何參與?
您可以透過多種方式聯絡 SIG Node
您也可以直接聯絡我們
- GitHub:@rata @giuseppe @saschagrunert
- Slack:@rata @giuseppe @sascha