Kubernetes 儀錶板提供便捷的叢集管理介面,但若佈署不當,則可能成為資安漏洞。本文將探討儀錶板的安全風險,並提供安全佈署的最佳實踐。不安全的佈署方式,例如允許跳過登入或使用過高許可權的 Service Account,可能讓攻擊者有機可乘,例如 2018 年 Tesla 因儀錶板未妥善保護而遭入侵的事件。安全的佈署方式應採用反向代理機制,結合 OpenID Connect 進行身份驗證和授權,並妥善管理會話和許可權,避免敏感資訊洩露和未授權存取。
佈署安全的 Kubernetes 儀錶板
本章節將使用 Kubernetes 儀錶板來學習網頁應用程式安全,並將這些模式應用於自己的叢集中。這些經驗不僅適用於儀錶板,也適用於其他叢集為中心的應用程式,如 Istio 的 Kiali 儀錶板、Grafana、Prometheus 等叢集管理應用程式。
本章涵蓋以下主題
- 儀錶板如何識別使用者身份?
- 儀錶板是否不安全?
- 使用反向代理佈署儀錶板
- 將儀錶板與 OpenUnison 整合
技術需求
儀錶板如何識別使用者身份?
Kubernetes 儀錶板是一個功能強大的網頁應用程式,用於從瀏覽器內快速存取叢集。它允許您瀏覽名稱空間、檢視節點狀態,甚至提供一個殼層用於直接存取 Pod。使用儀錶板和 kubectl 之間有一個基本的區別。儀錶板作為一個網頁應用程式,需要管理會話,而 kubectl 不需要。這導致佈署期間出現不同的安全問題,通常沒有被考慮,進而導致嚴重的後果。在本文中,我們將探討儀錶板如何識別使用者並與 API 伺服器互動。
儀錶板架構
在探討儀錶板如何驗證使用者之前,瞭解儀錶板的工作原理是非常重要的。儀錶板在高層次上有三層架構:
- 使用者介面:這是在瀏覽器中顯示並與之互動的 Angular + HTML 前端。
- 中間層:前端與儀錶板的容器中託管的一組 API 互動,將前端的呼叫轉換為 Kubernetes API 呼叫。
- API 伺服器:中間層 API 直接與 Kubernetes API 伺服器互動。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 儀錶板架構
rectangle "API呼叫" as node1
rectangle "Kubernetes API呼叫" as node2
node1 --> node2
@enduml圖表翻譯: 此圖示展示了 Kubernetes 儀錶板的架構,包括使用者介面、中間層和 API 伺服器之間的互動關係。
身份驗證方法
儀錶板可以透過三種方式確定使用者的身份:
- 無憑證:可以指示儀錶板不收集任何令牌或憑證。此時,儀錶板將使用容器的服務帳戶與 API 伺服器互動,根據 RBAC 分配的許可權。
- 從登入/上傳的 kubectl 組態中取得令牌:儀錶板可以提示使用者提供 kubectl 組態檔案或持有者令牌。一旦提供了令牌(或從上傳的組態檔案中提取),就會建立一個加密的 cookie 來儲存令牌。這個 cookie 由中間層解密,內部的令牌被傳遞給 API 伺服器。
- 從反向代理取得令牌:如果從使用者介面到中間層的請求中包含持有者令牌的授權標頭,中間層將在對 API 伺服器的請求中使用該持有者令牌。這是本章將詳細介紹的最安全的選項。
瞭解儀錶板的安全風險
在設定新叢集時,經常會出現有關儀錶板安全性的問題。確保儀錶板的安全歸根結柢取決於如何佈署它,而不是它本身是否安全。回到儀錶板應用程式的架構,可以看出它並沒有內建「安全性」的概念。中間層只是將令牌傳遞給 API 伺服器。
#### 內容解密:
上述段落描述了 Kubernetes 儀錶板的架構和身份驗證方法。下面是關於這些內容的詳細解說:
- 無憑證模式:在這種模式下,儀錶板使用其服務帳戶與 Kubernetes API 互動,這可能帶來安全風險,因為服務帳戶可能具有過高的許可權。
- 從登入/上傳的 kubectl 組態中取得令牌:這種方法需要使用者手動提供憑證或上傳組態檔案。雖然這種方法可行,但它需要使用者參與,並可能導致安全問題,如果處理不當。
- 從反向代理取得令牌:這是推薦的方法,因為它提供了更好的安全性和使用者經驗。透過在反向代理中處理身份驗證,可以確保只有授權的使用者可以存取儀錶板。
使用反向代理佈署儀錶板
使用反向代理是佈署 Kubernetes 儀錶板的一種安全方法。它允許在代理層處理身份驗證和授權,從而保護儀錶板免受未授權的存取。
# 示例:使用 Nginx 作為反向代理
server {
listen 443 ssl;
server_name kubernetes-dashboard.example.com;
ssl_certificate /path/to/ssl.crt;
ssl_certificate_key /path/to/ssl.key;
location / {
proxy_pass http://kubernetes-dashboard:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
內容解密:
上述 Nginx 組態示例展示瞭如何設定反向代理來保護 Kubernetes 儀錶板。下面是對這個組態的詳細解釋:
listen 443 ssl;:監聽 HTTPS 連線埠。proxy_pass http://kubernetes-dashboard:8080;:將請求轉發到 Kubernetes 儀錶板的內部服務。proxy_set_header指令:設定轉發請求的標頭,以保持原始請求資訊。
將儀錶板與 OpenUnison 整合
OpenUnison 可以與 Kubernetes 儀錶板整合,提供更安全的存取控制和單一登入(SSO)功能。這種整合增強了叢集的安全性,並簡化了使用者存取多個應用程式的過程。
Kubernetes 儀錶板的安全風險解析
在探討任何與 IT 安全相關的話題時,採用「縱深防禦」(defense in depth)的思維至關重要。這個概念強調任何系統都應具備多層次的安全防護措施,以確保當某一層防護失效時,其他層次能夠彌補漏洞,直至失效的層次得到修復。這樣,即使某一層防護被突破,攻擊者也不會直接獲得系統的存取許可權。
歷史案例:Tesla 的安全漏洞
最常被提及的與 Kubernetes 儀錶板(dashboard)安全相關的事件,是 2018 年發生在 Tesla 的安全漏洞。攻擊者能夠存取 Tesla 叢集(cluster)中執行的 Pods,是因為儀錶板未被妥善保護。這些 Pods 擁有存取 Tesla 雲端服務供應商的權杖(token),使得攻擊者能夠利用這些權杖存取 Tesla 的雲端資源,並執行加密貨幣挖礦(crypto-mining)系統。
儀錶板安全風險
Kubernetes 儀錶板往往成為攻擊者的目標,因為它讓攻擊者能夠輕易找到所需資源,而且容易被不安全地佈署。在 KubeCon NA 2019 上,曾經舉辦了一個 Capture the Flag (CTF) 活動,其中一個場景就是開發人員「無意中」暴露了叢集的儀錶板。
自 Tesla 事件之後,要在沒有憑證(credentials)的情況下佈署 Kubernetes 儀錶板變得更加困難。現在,這已經不是預設的行為,需要對儀錶板和叢集進行額外的設定。
不安全佈署儀錶板的風險
雖然聽起來有些誇張,但我們在實際環境中已經見過太多次不安全的儀錶板佈署。官方推薦的儀錶板安裝多次強調,不應在生產環境中使用這種組態。然而,由於這種組態使得佈署儀錶板變得非常簡單,很多新手管理員會在生產叢集中使用相同的佈署方式。
示範不安全佈署儀錶板的風險
現在,讓我們來示範一下攻擊一個未經安全考慮而佈署的儀錶板有多麼容易:
首先,告訴儀錶板允許使用者繞過身份驗證。編輯
kubernetes-dashboard名稱空間中的kubernetes-dashboarddeployment:kubectl edit deployment kubernetes-dashboard -n kubernetes-dashboard在容器的
args選項中新增--enable-skip-login,然後儲存:# 圖 9.2 – 在儀錶板上啟用 skip-login
程式碼解析:不安全的 Ingress 組態
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: dashboard-external-auth
namespace: kubernetes-dashboard
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/backend-protocol: https
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.org/ssl-services: kubernetes-dashboard
spec:
rules:
- host: k8s-secret-dashboard.apps.192-168-2-129.nip.io
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 443
path: /
內容解密:
此 YAML 組態檔案定義了一個 Ingress 資源,用於將外部流量匯入 kubernetes-dashboard 服務。其中,annotations 部分包含了多個 Nginx Ingress Controller 的註解,用於控制 Ingress 的行為,如會話親和性(affinity)和後端協定等。spec.rules 部分定義了根據主機名的路由規則,將特定主機名的流量匯入後端的 kubernetes-dashboard 服務。
建立一個新的 Ingress 資源來暴露儀錶板。使用以下 YAML 組態建立一個名為
insecure-dashboard.yaml的檔案,並記得替換host部分的 IP 地址為你的 Docker 主機的 IP 地址。使用
kubectl命令建立 Ingress 資源:kubectl create -f insecure-dashboard.yaml一旦 Ingress 被建立,開啟瀏覽器並存取你在 Ingress 組態檔案中指定的 Nip.io 名稱所對應的 URL。
你將看到一個要求提供 token 或 Kubeconfig 檔案的身份驗證介面,但由於我們之前編輯了儀錶板的組態以允許跳過登入,你可以直接點選「Skip」按鈕跳過登入。
登入後,你會發現預設的服務帳戶(service account)並沒有存取任何資源的許可權。
為了提升預設服務帳戶的許可權,建立一個新的
ClusterRoleBinding將cluster-adminClusterRole 繫結到預設服務帳戶。建立一個名為dashboard-role.yaml的檔案,並填入以下內容:apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: secret-dashboard-cluster-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: default namespace: kubernetes-dashboard
圖表翻譯:
此圖展示了 Kubernetes 中的 Role-Based Access Control (RBAC) 組態,特別是如何透過 ClusterRoleBinding 將 cluster-admin 角色繫結到特定的服務帳戶上,從而賦予該帳戶叢集管理員許可權。
Kubernetes 儀錶板的安全風險與安全佈署
瞭解儀錶板的安全風險
在 Kubernetes 環境中,儀錶板(Dashboard)是一個重要的管理工具。然而,如果不當組態或使用不安全的佈署方式,它可能會成為安全漏洞的來源。本章節將探討 Kubernetes 儀錶板的安全風險,並介紹如何安全地佈署儀錶板。
不安全的佈署方式
在前面的章節中,我們已經瞭解瞭如何佈署 Kubernetes 儀錶板。但是,如果我們不小心,很容易就會落入安全陷阱。以下是一個例子:
假設我們在 Reddit 上看到一篇標題為「這是一個保護 Kubernetes 儀錶板的好工具」的帖子。帖子看起來很合法,我們很想試試這個工具。於是,我們下載了該工具並執行它,結果卻發現它竟然在我們的叢集中佈署了一個比特幣挖礦程式!
go run kubectl-secure-my-dashboard.go https://k8s-secret-dashboard.apps.192-168-2-129.nip.io
內容解密:
這段程式碼是用 Go 語言寫的,用於測試 Kubernetes 儀錶板的安全性。它模擬了一個攻擊者試圖利用儀錶板的漏洞來佈署惡意程式的場景。
這個例子告訴我們,不安全的佈署方式可能會導致嚴重的後果。攻擊者可以利用 kubectl port-forward 或 kubectl proxy 等命令來繞過身份驗證,直接存取儀錶板。
使用 Token 登入
為了避免使用不安全的佈署方式,我們可以使用 Token 登入儀錶板。這樣可以避免使用具有高許可權的 Service Account。然而,這種方法也有其自身的問題。儀錶板無法像 kubectl 一樣重新整理 Token,因此 Token 需要有較長的有效期。這可能會降低安全性。
使用反向代理佈署儀錶板
那麼,如何安全地佈署 Kubernetes 儀錶板呢?答案是使用反向代理。反向代理是一種常見的模式,在 Kubernetes 中被廣泛使用。它可以提供一個安全的入口點,用於存取儀錶板。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 使用反向代理佈署儀錶板
rectangle "HTTPS" as node1
rectangle "HTTP" as node2
node1 --> node2
@enduml圖表翻譯: 此圖示展示了使用反向代理佈署 Kubernetes 儀錶板的架構。客戶端透過 HTTPS 連線到反向代理,反向代理再將請求轉發給 Kubernetes 儀錶板。
使用反向代理可以提供額外的安全層,例如 SSL/TLS 加密和身份驗證。這樣可以確保只有授權的使用者可以存取儀錶板。
Kubernetes 儀錶板的反向代理佈署與安全性探討
在 Kubernetes 叢集管理中,儀錶板(Dashboard)扮演著重要的角色。為了確保其安全性,使用反向代理(Reverse Proxy)是一種常見且有效的方法。本篇文章將探討如何利用反向代理佈署 Kubernetes 儀錶板,並分析其安全性。
反向代理的三個主要功能
- 身份驗證(Authentication):反向代理攔截未經身份驗證的請求,並觸發與 OpenID Connect 身份提供者的身份驗證過程。
- 會話管理(Session Management):Kubernetes 儀錶板是一個導向使用者的應用程式,需要支援會話超時和復原功能。應避免使用將所有會話資料儲存在 Cookie 中的反向代理,因為這種方法難以復原。
- 身份注入(Identity Injection):一旦代理驗證了使用者,它需要能夠在每個請求中注入 HTTP 授權標頭,該標頭是一個 JWT,標識已登入的使用者,並由相同的 OpenID Connect 身份提供者簽名,具有與 API 伺服器相同的發行者和接收者。
程式碼範例:反向代理組態
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubernetes-dashboard
spec:
rules:
- host: dashboard.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 80
tls:
- hosts:
- dashboard.example.com
secretName: tls-secret
內容解密:
- 此 YAML 組態定義了一個 Kubernetes Ingress 資源,用於將外部請求路由到 Kubernetes 儀錶板服務。
spec.rules部分指定了主機名稱dashboard.example.com,並將根路徑/的請求轉發到kubernetes-dashboard服務的 80 埠。spec.tls部分組態了 TLS 證書,用於加密與儀錶板的通訊。
當地儀錶板(Local Dashboards)的安全性
許多第三方儀錶板在本地工作站上執行,並使用 Kubernetes SDK 與 API 伺服器互動,就像 kubectl 一樣。這些工具的好處是不需要佈署額外的基礎設施來確保其安全性。例如,Visual Studio Code 的 Kubernetes 外掛程式就是一個利用直接 API 伺服器連線的本地應用程式。
將儀錶板與 OpenUnison 整合
OpenUnison 的佈署包含兩個整合的應用程式:
- OpenID Connect 身份提供者與登入入口網站:此應用程式託管登入過程和 API 伺服器用於取得驗證
id_token所需的金鑰的發現 URL。 - 儀錶板:一個反向代理應用程式,它向整合的 OpenID Connect 身份提供者進行身份驗證,並將使用者的
id_token注入每個請求中。
圖表說明:OpenUnison 與儀錶板的整合
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 圖表說明:OpenUnison 與儀錶板的整合
rectangle "存取儀錶板" as node1
rectangle "驗證使用者" as node2
rectangle "傳回 id_token" as node3
rectangle "注入 id_token" as node4
node1 --> node2
node2 --> node3
node3 --> node4
@enduml圖表翻譯:
此圖展示了使用者如何透過反向代理存取 Kubernetes 儀錶板,並由 OpenID Connect 身份提供者進行身份驗證。驗證成功後,反向代理將使用者的 id_token 注入請求中,以便存取儀錶板。