Kubernetes 提供了 Secret 物件來管理敏感資料,例如密碼、API 金鑰等。Secret 物件的型別包括 Opaque、dockerconfigjson 和 service-account-token 等,用於不同場景。建立 Secret 時,可以使用 kubectl 命令搭配 from-literal 和 from-file 標誌,將資料以 base64 編碼後儲存於 etcd 中。然而,etcd 本身不提供加密,因此資料安全性需要額外考量。kube-apiserver 作為 Kubernetes 的主要元件,也可能成為攻擊目標。惡意攻擊者可能透過 API 存取 etcd 或直接提取 etcd 的本地檔案來取得 Secret 資料。Kubernetes 節點的檔案系統以及叢集備份也存在潛在風險。為了降低風險,需要實施多層次安全措施,例如許可權控制、加密傳輸、監控和稽核。平台層面的 Secret 物件不應移交到外部保管函式庫,而應用層面的 Secret 則可以考慮使用外部保管函式庫或類別似方案。RBAC 機制可以控制對 Secret 的存取,透過設定 Role 和 RoleBinding,限制只有授權使用者才能操作 Secret。此外,稽核和監控 Secret 的變更記錄也至關重要,以便及時發現潛在威脅。實務上,可以使用 Podman Desktop、Go 語言和 Minikube 等工具來操作和管理 Secret,並結合 RBAC 和稽核機制,構建更安全的 Kubernetes 應用環境。
Kubernetes 秘密管理的基本概念與應用
在理解 Kubernetes 的起源和設計原則後,讓我們進一步探討 Kubernetes 中的「Secret」概念。這些 Secret 如何在 Kubernetes 上儲存,如何注入到 Pod 中,以及我們需要面對的安全問題。秘密管理在現代雲原生架構中非常重要,因為它涉及到敏感資料的處理與保護。
Secret 的基本概念
在設計和佈署 Red Hat OpenShift 的過程中,秘密管理這個主題往往被視為無關緊要。這是因為我們過去幾十年的傳統環境中,基礎設施和應用程式團隊之間存在明確的分離原則。基礎設施團隊負責基礎設施,應用程式團隊負責應用程式。然而,在 Kubernetes 中,這些擔憂合而為一,成為平台的一部分。
在容器映像的設計中,秘密不能硬編碼或包含在容器映像中。如果將秘密硬編碼,這些秘密將會對所有有權存取容器映像倉函式庫的內部和外部相關者公開。如果將容器映像推播到公共倉函式庫,這些秘密將會對更多的人公開。
為瞭解決這些問題,Kubernetes 提供了一個內建的秘密管理框架,專門有一個名為 Secret 的 API 物件來管理這些敏感資料。以下是一個 Secret 物件定義的範例:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4K
password: UGFja3QxMjMhCg==
內容解密:
在這個範例中,我們建立了一個名為 mysecret
的 Secret 物件。這個物件的型別是 Opaque
,表示我們自己定義資料容器中的內容。
data
欄位包含兩個鍵值對:
username
:這裡的值是以 base64 編碼後的字串YWRtaW4K
。password
:這裡的值是以 base64 編碼後的字串UGFja3QxMjMhCg==
。
base64 編碼的作用
為什麼要使用 base64 編碼?首先,base64 編碼並不是加密,它只是為了便於命令列、網路傳輸和 kube-apiserver 處理避免因特殊字元而截斷負載。
然而,base64 編碼後的資料仍然可以在任何作業系統或網站上進行解碼。因此,當 kube-apiserver 將負載儲存到 etcd 健值儲存時,不會對資料進行加密。
ConfigMap 與 Secret 的區別
另一個與 Secret 功能類別似的 API 物件是 ConfigMap。ConfigMap 主要用於傳遞環境變數和應用程式引數,但它也被廣泛用於包含高階應用程式組態。例如:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-environment
data:
appversion1: dev
此圖示顯示了 ConfigMap 和 Secret 在資料欄位上的主要區別——編碼部分。ConfigMap 的資料欄位期望 UTF-8 字串,而 Secret 則期望鍵值對中的值以 base64 編碼。
在 Kubernetes 中儲存秘密
接下來我們來看一下實際操作範例:
- 建立 Secret 物件:使用提供的 YAML 清單建立一個 Secret 物件並檢查其狀態。
- 從 Kubernetes 還原 YAML 清單:如果惡意攻擊者成功與 kube-apiserver 談判,則他們可以提取 Kubernetes 叢集中的一些或全部 Secret 物件。
- 建立新的 Secret 物件:從頭開始編寫鍵值對、編寫 YAML 清單並透過命令列推播。
資料流圖示:
graph TD; A[應用程式] --> B[Kubernetes叢集]; B --> C[etcd健值儲存]; C --> D[Secret物件]; D --> E[Pod]; E --> F[應用程式]
此圖示顯示了應用程式如何透過 Kubernetes 叢集存取 Secret 物件並注入到 Pod 中。Secret 物件由 etcd 健值儲儲存存並由 kube-apiserver 管理。
內容解密:
- A:應用程式需要存取敏感資料。
- B:Kubernetes 叢集作為中介層管理和分配秘密。
- C:etcd 健值儲存作為 Kubernetes 的後端資料函式庫儲存所有組態和秘密。
- D:Secret 物件包含敏感資料並被 kube-apiserver 啟用。
- E:Pod 作為最小執行單元從叢集取得所需的秘密。
- F:應用程式最終存取和使用敏感資料。
安全考量
儘管 Kubernetes 提供了強大的秘密管理功能,但我們仍需注意以下安全問題:
- 許可權控制:確保只有授權的人員能夠存取和修改秘密。
- 加密傳輸:確保在傳輸過程中使用 TLS 加密。
- 監控和稽核:定期檢查和監控秘密變更記錄以發現潛在威脅。
總結來說,Kubernetes 的 Secret 提供了一種有效的方式來管理敏感資料。透過理解其設計原則和實際操作範例,我們可以更好地保護我們的雲原生應用程式。
Kubernetes 的秘密管理深度分析
Kubernetes Secret 物件的解密與注入
在 Kubernetes 中,Secret 物件用來儲存敏感資訊,如密碼、API 金鑰等。這些 Secret 物件可以被注入到 Pod 中,供容器使用。以下是詳細的過程和注意事項:
首先,我們需建立一個 Secret 物件,並將其注入到 Pod 中。為了進行測試和除錯,我們可以使用 busybox
容器,這是一個小型且高效的環境。Pod 清單檔案中包含對新建立 Secret 物件的參照,並將值分配給環境變數。這些變數在容器的日誌中可以被 echo 出來。
此圖示
graph TD; A[Kubernetes Master] --> B[kube-apiserver]; B --> C[etcd]; C --> D[Kubelet]; D --> E[Pod]; E --> F[Busybox Container];
此圖示展示了 Kubernetes 中 Secret 物件從建立到注入 Pod 的過程。
Secret 的解密與傳輸
在這個過程中,kubelet
負責解碼 base64 編碼的 Secret 載荷。這樣的設計確保了在不同元件之間及網路傳輸過程中的資料安全性。
etcd 的安全性挑戰
etcd 是 Kubernetes 的核心資源管理元件,它儲存了所有的 Kubernetes 資源狀態。然而,etcd 本身並不提供加密功能,這意味著儲存在其中的資料是未加密的。
如果惡意攻擊者成功突破了 etcd Pod 的防線,他們將能夠完全控制整個應用平台,甚至可能影響到雲端服務提供商的帳戶。
# 惡意攻擊者可能會嘗試透過 API 存取 etcd
import requests
etcd_url = "http://etcd-server:2379/v3/kv/put"
secret_data = {"key": "my-secret-key", "value": "my-secret-value"}
response = requests.post(etcd_url, json=secret_data)
print(response.content)
內容解密:
上述 Python 程式碼展示了一個簡單的 API 請求範例,用於向 etcd 傳送一個秘密資料。這段程式碼首先定義了 etcd 的 URL 和要傳送的秘密資料(鍵值對)。接著使用 requests.post
函式向 etcd 傳送一個 POST 請求,並將秘密資料作為 JSON 格式傳送。最後列印預出伺服器的回應內容。
惡意攻擊者可透過 API 呼叫直接讀取 etcd 中的資料。
敏感資料的本地提取
進一步地,惡意攻擊者可能會提取 etcd 的本地檔案並進行分析,以取得建立的 Secret 物件。雖然這看似是一種極端情況,但如果考慮到檔案系統存取或 Kubernetes 叢集備份中的 etcd 檔案,這種風險是存在的。
Kubernetes 的安全設計原則
Kubernetes 提供了一個無摩擦體驗給平台和應用團隊,但它並不是一個硬化解決方案。為瞭解決這些安全問題,我們需要考慮多層次的安全措施。
平台層面
當 Kubernetes 被佈署時,會建立一系列 Secret 物件以允許內部元件之間的互動(如儲存、網路、執行單元、控制器等)。後來佈署的第三方元件也會遵循相同的模型。這些 Secret 物件不應該被移交到外部保管函式庫以確保還原力度。
應用層面
應用在存取內部或外部服務(如資料函式庫、S3 桶等)時需要使用 Secret 物件,這些可以被移交到外部保管函式庫或類別似解決方案中。然而,應用可能還需要 ConfigMap 物件、卷加金鑰、TLS 證書等。
安全性挑戰與解決方案
在 Kubernetes 中管理 Secret 物件所面臨的安全挑戰並不簡單。以下是一些潛在的安全漏洞:
- kube-apiserver:這是 Kubernetes 的主要元件之一,惡意攻擊者可能透過它進入應用平台。
- etcd:管理 Kubernetes 資源狀態,存在多種安全漏洞:
- 資料函式庫檔案:etcd 沒有提供加密能力,資料函式庫檔案是二進位制格式且易於讀取。
- API 服務:類別似於 kube-apiserver,etcd 是根據 API 的服務,任何存取或網路追蹤都可能洩露資料。
- Kubernetes 節點:
- 節點檔案系統:etcd Pod 的檔案系統寄宿在一個捲上以提供持久儲存。該卷附加到節點上,透過存取節點可以透過附加捲取得資料。
- 備份:Kubernetes 叢集備份包含 etcd 檔案,存取備份可能洩露資料。
Secret 暴露途徑
Secret 物件可能透過多種方式被暴露:
- 與 Kubernetes 元件(如 kube-apiserver 和 etcd)互動。
- 輸入物理層面(如直接節點存取或備份)。
為了確保敏感資料在 Kubernetes 中的安全性,我們需要綜合考慮上述所有因素並採取相應的安全措施。
Kubernetes 密碼管理概述
在前一章節中,我們已經對 Kubernetes 及其各元件有了一個全面的瞭解,並且成功地在 Kubernetes 上佈署了一個使用 Go 語言編寫的應用程式。在這個過程中,我們需要為應用程式的組態新增秘密(Secrets)。管理這些秘密涉及多種考量,從建立、修改到刪除,我們都需要處理安全性、可擴充套件性和韌性等問題。
本章將探討 Kubernetes 密碼管理的概念,包括以下幾個主題:
- Kubernetes 密碼與其他 Kubernetes 物件的區別
- 不同型別的密碼及其使用場景
- 在 Kubernetes 中建立、修改和刪除密碼
- 不同佈署情境下的 Kubernetes 密碼組態
- 管理密碼的需求,包括安全儲存和存取控制
- 使用 RBAC 安全存取密碼
- 稽核和監控密碼使用情況
技術需求
為了將理論與實踐結合起來,我們將使用一系列常見的工具和平台來互動容器、Kubernetes 和密碼管理。本章將使用以下工具:
- Podman Desktop:一款開源軟體,可以互動容器、執行本地 Kubernetes 例項,並連線到遠端平台如 Red Hat OpenShift、Azure Kubernetes Service(AKS)等。你可以從官方網站取得安裝指引。
- Go 語言:我們將在本章中使用 Go 語言進行開發。安裝指引可以參考 Go 的官方檔案。
- Minikube:用於本地執行 Kubernetes 叢集。安裝指引可以參考 Minikube 的官方檔案。
- GitHub 儲存函式庫:本文中的所有程式碼範例都已經上傳到 GitHub 儲存函式庫中,結構清晰且有詳細說明。
Kubernetes 密碼與其他 Kubernetes 物件的區別
Kubernetes 的核心建構塊之一就是 Kubernetes 物件。透過這些物件,我們可以表示系統狀態。在 Kubernetes 上執行的應用程式由實際程式、應用程式使用的資源以及應用程式組態(如健康檢查)組成。關於安全性等跨切面問題,我們會有角色基礎存取控制(RBAC)的組態,包括叢集範圍角色、名稱空間角色以及與使用者或實體繫結的角色。
除了上述物件外,Kubernetes 還包括名稱空間(Namespace),它們作為邏輯容器;還有網路策略(NetworkPolicy),它們是叢集範圍內的流量規則。透過建立這些物件,我們宣告瞭叢集的期望狀態。Kubernetes 則負責確保實際狀態與我們建立的物件所定義的狀態比對。
以下是一個典型的 Kubernetes 物件 YAML 表示:
apiVersion: apps/v1 #Kubernetes API 版本
kind: Deployment #物件型別
metadata: #後設資料資訊
name: example-deployment
spec: #物件應該達到的狀態
常見的 Kubernetes 物件包括 Pod、Deployment、StatefulSet、CronJob、Service、Ingress、NetworkPolicy、ConfigMap 和 Secret。
不同型別的密碼及其使用場景
Kubernetes 提供了多種型別的密碼。背後的儲存機制與前一章節中提到的是一樣的:密碼一旦建立,將被序列化並儲存在 etcd 中。不同之處在於它們在使用時如何處理。
Opaque
Opaque 是預設型別的秘密。無論是檔案還是變數,只要需要新增敏感組態,它都會被建立為 Opaque 秘密。
$ kubectl create secret generic opaque-example-from-literals --from-literal=literal1=text-for-literal-1
$ kubectl get secret opaque-example-from-literals -o yaml
內容解密:
以上命令建立了一個名為 opaque-example-from-literals
的 Opaque Secret。其中 --from-literal
標誌允許我們直接透過命令列建立 Key-Value 單元。
apiVersion: v1
data:
literal1: dGV4dC1mb3ItbGl0ZXJhbC0x #Base64 編碼後的文字
kind: Secret
type: Opaque
這段 YAML 組態顯示了 Secret 的結構。data
欄位中的值是 Base64 編碼過後的文字 text-for-literal-1
。
其他型別的秘密
除了 Opaque 外,Kubernetes 還支援其他型別的秘密,例如 kubernetes.io/dockerconfigjson
用於 Docker 認證、kubernetes.io/service-account-token
用於服務帳戶令牌等。
建立與管理 Secret
以下是如何使用 kubectl
命令來建立和管理 Secret 的範例:
$ kubectl create secret generic my-secret --from-file=my-key=./key.txt --from-literal=username=user --from-file=my-cert=./cert.pem
$ kubectl get secret my-secret -o yaml
內容解密:
以上命令建立了一個名為 my-secret
的 Secret。其中 --from-file
標誌允許從檔案讀取資料,而 --from-literal
標誌則允許直接透過命令列建立 Key-Value 單元。
apiVersion: v1
data:
my-key: <Base64 編碼後內容>
username: <Base64 編碼後內容>
my-cert: <Base64 編碼後內容>
kind: Secret
type: Opaque
這段 YAML 組態顯示了 Secret 的結構。每個 Key 值都是 Base64 編碼後的原始資料。
RBAC 與 Secret 安全性
Kubernetes 提供了 Role-Based Access Control(RBAC)機制來控制對 Secret 的存取。透過適當地設定 Role 和 RoleBinding,我們可以確保只有授權使用者才能存取特定 Secret。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: secret-reader-role
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-secrets-binding
subjects:
- kind: User
name: "user-name"
roleRef:
kind: Role
name: secret-reader-role
內容解密:
以上是如何設定 RBAC 清單來限制對 Secret 的存取許可權:
- Role:定義了一個名為
secret-reader-role
的角色,該角色允許對 Secret 的get
,watch
, 和list
操作。 - RoleBinding:將該角色繫結到特定使用者
user-name
上。
跨切面關注點
Secret 的使用涉及一些跨切面關注點,例如稽核和監控。我們需要確保系統能夠記錄和監控誰何時存取了哪些 Secret。
apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata #設定稽核等級為 Metadata, 用來記錄哪些 API 被呼叫以及什麼時間被呼叫。
內容解密:
這段組態顯示瞭如何設定稽核策略以記錄對 Secret 操作相關資訊:
- level: 指定了稽核等級為 Metadata, 用於記錄哪些 API 被呼叫以及何時被呼叫。
總結來說,Kubernetes Secrets 是儲存敏感組態資料的一種安全方式。透過適當地組態和管理 Secrets,我們可以確保敏感資訊得到保護並只被授權人員存取。
此圖示展示了不同時期技術演進歷史:從裸機(Bare Metal)、虛擬機器(Virtual Machine)、到容器化(Containerization)技術發展之路。
graph LR; A[Bare Metal] --> B[Virtual Machine]; B --> C[Containerization]; C --> D[Kubernetes];
分析解釋:
- A[Bare Metal]:最初時代直接在硬體上運作應用程式。
- B[Virtual Machine]:虛擬機器技術允許在單一硬體上執行多個作業系統例項。
- C[Containerization]:容器技術進一步提升效率與可移植性。
- D[Kubernetes]:Kubernetes 作為容器協調工具提供強大且靈活的佈署功能。