Kubernetes 安全性設定牽涉層面廣泛,從 CI/CD 流程整合、組織政策制定到具體的叢集設定,都需要謹慎規劃。本文除了探討秘密管理的常見問題與最佳實務,例如避免將秘密儲存在 etcd、使用外部秘密管理服務、以及實作自動化輪替機制外,也深入 Kubernetes 的驗證與授權機制,說明如何利用 RBAC 以及服務帳戶有效控管叢集資源的存取許可權。此外,文章也示範如何使用 Python 程式碼與 Kubernetes API 互動,建立服務帳戶並設定相關許可權。最後,文章也涵蓋了 Pod Security Policies 的設定細節,說明如何透過限制 Pod 的許可權提升、資源使用以及網路存取等方式,強化叢集的安全性。

安全監控與稽核

CI/CD 資源的存取需要持續的稽核與監控,以判斷是否有過度存取、使用者離職或職務變動時的許可權廢止、濫用或可疑的使用者行為。

組織政策

為瞭解決 CI/CD 管道和掃描所帶來的挑戰,需要制定一個全球性的組織政策。該政策需要明確 CI/CD 資源的存取需求、使用者責任的分離、秘密管理、紀錄和監控需求以及稽核政策。

漏洞掃描最初可能會讓團隊感到不知所措。因此,開發、DevOps 和安全團隊需要明確的指導方針,以便根據組織的威脅模型發現和評估產品漏洞、風險、修復和關閉問題的時間表。

漏洞掃描解決方案可以具有編碼政策,根據掃描結果和組織的風險承受能力允許或拒絕映像。建立有效政策的過程需要是迭代的,並根據持續的反饋,以實作根據行業、規模、工作流程和合規要求量身定製的政策,平衡安全性和效能。

秘密管理

秘密可以是用於驗證和授權使用者、群組或實體的任何東西。它可以是使用者名稱/密碼、API 令牌或 TLS 證書。當應用程式或微服務遷移到 Kubernetes 時,開發人員需要做出的早期設計選擇是將這些秘密儲存在哪裡,以及如何檢索它們並在應用程式中按需提供,而不損害應用程式的安全態勢。

使用 etcd 儲存秘密

應用程式遷移到 Kubernetes 的常見場景是將秘密以 Base64 編碼格式儲存在 etcd 中作為鍵值對。Etcd 是 Kubernetes 佈署中支援的資料儲存。這些秘密可以在容器內作為磁碟區掛載或環境變數,從 Kubernetes 佈署規格中提供。由於環境變數儲存在記憶體中,因此與將秘密儲存在容器檔案系統中的磁碟區掛載相比,更難提取秘密。對 etcd 的存取由 Kubernetes RBAC 提供支援,帶來了必要的安全性和靈活性。

Etcd 提供了強大的平行原語、可線性化的讀取和 API,以大規模管理秘密。這種方法的缺點是,秘密以純文字格式(Base64 編碼)儲存,並且在未組態 etcd 使用 TLS 加密通訊的情況下,以純文字格式檢索和傳送。

此外,儲存在 etcd 中的秘密沒有版本控制或可還原性,一旦刪除,就無法還原。對 etcd 的存取也不會被稽核,因此任何有權存取 etcd 的人都可以存取所有秘密。由於 etcd 是 Kubernetes 資料儲存,因此無法滿足組織更廣泛的秘密管理需求。

秘密管理服務

為瞭解決組織的加密和秘密管理需求,可以使用雲端提供商提供的秘密管理服務。所有主要的公有雲提供商都提供秘密管理服務。

最流行的雲端提供商的秘密管理服務包括 AWS Secrets Manager、Google Secret Manager 和 Azure Key Vault。

一個值得注意的第三方例子是 HashiCorp Vault,它可以用作集中式的秘密管理器。它提供了許多功能,以滿足組織的端對端秘密管理需求(金鑰管理、加密、輪替、PKI、儲存、複製、復原、日誌記錄、監控、稽核等)。該工具可以與雲端提供商的秘密管理服務結合使用,例如,當保險函式庫初始化時,初始金鑰可以被加密並儲存在 Cloud KMS 中,這樣操作員就不必處理純文字金鑰。

Kubernetes 秘密儲存 CSI 驅動程式

秘密儲存容器儲存介面(CSI)驅動程式使用 CSI 將外部秘密儲存(如 Azure、GCP、AWS 和 HashiCorp 的 Vault)整合到 Kubernetes 中,自 1.13 版以來通常可用。

簡而言之,CSI 驅動程式使用磁碟區屬性與您的秘密儲存服務進行身份驗證,並無縫地將所需的秘密掛載到 pod 中。這種方法避免了使用 Kubernetes etcd 資料儲存,並允許您有效地擴充套件和管理組織的秘密。

秘密管理最佳實踐

以下是管理 Kubernetes 中秘密時要考慮的最佳實踐。

避免秘密擴散

秘密管理的主要目的是避免秘密擴散,即您的應用程式秘密散佈在 config 檔案、yamls 和 Git 儲存函式庫等地方。這通常是組織中缺乏秘密管理工作流程的跡象。減輕秘密擴散的唯一方法是制定集中式的秘密管理策略,在該策略中,憑證可以安全地儲存在單一地點並檢索,並由整個組織在適當的授權、日誌記錄和監控機制下使用。

使用反親和性規則

理想情況下,秘密管理解決方案應該是在少量專用 VM 或專用主機上執行的單一程式。由於您可能需要在 Kubernetes 上將此解決方案作為微服務執行,因此它將是在專用 pod 中執行的程式。但問題在於這些 pod 應該在哪個節點上執行。這裡,反親和性有助於將 pod 分佈在所需的節點上,這些節點被分類別為執行秘密管理解決方案。

資料加密(傳輸中和靜止)

預設情況下,Kubernetes 以不安全的方式儲存和傳輸秘密。組態或擁有可以使用端對端 TLS 加密的解決方案至關重要,在該解決方案中,秘密在傳輸過程中被加密。同時,擁有將秘密以加密形式儲存的機制也很重要。有關如何實作此目標的選項,請參閱第 2 章。

使用自動化的秘密輪換

組織遵循不同的時間框架來輪換不同的秘密,但隨著自動化的秘密輪換的出現,您可以每天甚至每小時進行輪換。雲端秘密管理服務和外部第三方解決方案都可以幫助以自動化的方式輪換和管理秘密。

短暫或動態秘密

短暫或動態秘密是臨時生成的、按需生成的秘密,通常具有短暫的生命週期,並在該時間間隔後被銷毀。這些秘密可以根據需要提供給應用程式類別或維運團隊。如果攻擊者發現了一個秘密(例如,如果透過除錯日誌洩露、應用程式碼或意外地透過 GitHub 公開),則這些秘密在短時間內就會被更改,從而保護應用程式。此外,它們可以幫助追蹤攻擊者在基礎架構中的足跡,因為很容易確定攻擊者發現該秘密的時間範圍。HashiCorp Vault 和 CyberArk Conjur 是一些提供此類別功能的第三方秘密提供者。

Kubernetes 驗證與授權機制詳解

在 Kubernetes 中,正確的驗證和授權機制對於叢集的安全性至關重要。本篇文章將探討 Kubernetes 的驗證和授權方法,幫助您瞭解如何保護您的叢集。

啟用稽核日誌

在您的秘密管理解決方案中啟用稽核日誌,可以提供組織內秘密及其使用的可見性。稽核日誌對於確定故意或無意的洩露、攻擊的影響範圍以及相關的取證步驟至關重要。

安全儲存秘密

當容器化應用程式接收到秘密時,不要將秘密儲存在磁碟上(或主機上的 volumeMount 中)。相反,將其儲存在記憶體中,以便在發生洩露時,攻擊者不容易取得這些秘密。

秘密零問題

許多秘密管理解決方案遵循信封加密,其中 DEK 受 KEK 保護。KEK 被視為秘密零。如果攻擊者洩露了 KEK,那麼他們可以解密 DEK,進而解密由 DEK 加密的資料。雲端提供者的 IAM 和 KMS 的組合可以用來幫助保護秘密零。

使用自訂憑證授權單位

作為深度防禦的一部分,可以使用自訂憑證授權單位(CA)實作端對端 TLS。組織可以選擇使用自己的 CA 簽署憑證。在這種情況下,只有出示由組織簽署的憑證的服務才能被存取。

Kubernetes 驗證機制

Kubernetes 允許多種驗證機制。最簡單的形式是使用憑證、權杖或基本驗證(使用者名稱和密碼)。此外,可以使用 webhook 來驗證持有者權杖,並整合外部 OpenID 提供者。

X509 使用者端憑證

有兩種方法可以簽署使用者端憑證,以便用於驗證 Kubernetes API。第一種方法是使用 Kubernetes API 內部簽署憑證。第二種方法是使用企業 PKI 簽署使用者端提交的 CSR。

持有者權杖

Kubernetes 服務帳戶使用持有者權杖來驗證 Kubernetes API。可以透過建立新的服務帳戶來使用持有者權杖。Kubernetes API 自動發出與服務帳戶相關聯的隨機權杖,可以檢索並用於驗證該帳戶。

OIDC 權杖

OpenID Connect 協定透過擴充套件現有的 OAuth2 協定構建。Kubernetes 不提供 OpenID Connect 身份提供者。您可以使用像 Google 或 Azure 這樣的身份提供者,或者使用 dex、keycloak 或 UAA 執行自己的身份提供者。

Kubernetes 授權機制

Kubernetes 有多種授權機制,例如 Node、ABAC、RBAC 和 AlwaysDeny/AlwaysAllow。RBAC 是 Kubernetes 中的行業標準。

Node

Node 授權是 Kubernetes 內部使用的特殊授權模式。它專門用於授權 kubelet 發出的 API 請求。

ABAC

Kubernetes 將屬性型存取控制(ABAC)定義為「一種存取控制正規化,透過使用將屬性組合在一起的策略來授予使用者存取許可權」。

AlwaysDeny/AlwaysAllow

AlwaysDeny 或 AlwaysAllow 授權模式通常用於開發環境中,需要允許或拒絕所有對 Kubernetes API 的請求。

程式碼範例:使用 Kubernetes API 建立服務帳戶

import requests

# 設定 Kubernetes API URL 和 Token
api_url = 'https://your-kubernetes-api-url.com/api/v1/namespaces/default/serviceaccounts'
token = 'your-kubernetes-token'

# 設定 headers
headers = {
    'Authorization': f'Bearer {token}',
    'Content-Type': 'application/json'
}

# 建立服務帳戶
response = requests.post(api_url, headers=headers, json={
    'apiVersion': 'v1',
    'kind': 'ServiceAccount',
    'metadata': {
        'name': 'your-service-account-name'
    }
})

#### 內容解密:
此程式碼範例展示如何使用 Kubernetes API 建立服務帳戶首先我們需要設定 Kubernetes API URL 和 Token然後我們設定 headers包括 Authorization 和 Content-Type最後我們使用 POST 請求建立服務帳戶並將結果儲存在 response 變數中

Kubernetes 安全機制:授權與存取控制

在 Kubernetes 叢集中,安全是至關重要的議題。為了確保叢集的安全,需要對存取控制進行嚴格的管理。Kubernetes 提供了多種授權機制,其中最推薦的是 Role-Based Access Control(RBAC)。

RBAC 的基本原理

RBAC 是一種根據使用者在叢集中的角色來限制系統存取的方法。它允許組織實施最小許可權原則。Kubernetes RBAC 採用宣告式的方式,明確定義了授權請求中的許可權(操作)、API 物件(資源)和主體(使用者、群組或 ServiceAccount)。

RBAC 的實作步驟

實作 RBAC 需要兩個步驟:

  1. 建立 Role 或 ClusterRole:Role 是名稱空間物件,而 ClusterRole 是全域物件。Role 或 ClusterRole 由動詞、資源和主體組成,提供對資源的能力(動詞)。
  2. 建立 ClusterRoleBinding:將步驟 1 中定義的許可權分配給使用者或群組。

例子:為 dev-admins 群組提供讀取所有 Secret 的許可權

  1. 建立一個名為 secret-reader 的 ClusterRole,允許讀取 Secret。
  2. secret-reader ClusterRole 繫結到 dev-admins 群組。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]

繫結 ClusterRole 到群組

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: secret-reader-binding
roleRef:
  name: secret-reader
  kind: ClusterRole
subjects:
- kind: Group
  name: dev-admins
  apiGroup: rbac.authorization.k8s.io

詳細解說:

  1. ClusterRole 定義:定義了一個名為 secret-reader 的 ClusterRole,該角色允許對 Secret 資源執行 getlist 操作。
  2. ClusterRoleBinding 定義:將 secret-reader ClusterRole 繫結到 dev-admins 群組,使該群組中的所有使用者能夠讀取叢集中的所有 Secret。

Namespaced RBAC

除了全域的 RBAC 之外,Kubernetes 也支援名稱空間層級的 RBAC。這需要使用 Role 和 RoleBinding 資源。

注意事項:

  • Role 和 RoleBinding 是名稱空間資源。
  • ClusterRoleBinding 不能與 Role 一起使用。
  • RoleBinding 不能與 ClusterRole 一起使用,除非使用特定的設定。

許可權提升的防範

Kubernetes RBAC 可以減少攻擊者透過編輯角色或角色繫結來提升許可權的可能性。這種行為在 Kubernetes 的 API 層級被強制執行,即使 RBAC 授權器未被使用。

工作負載執行階段安全

Kubernetes 的預設 Pod 組態機制具有廣泛的攻擊面,可能被攻擊者利用來攻擊叢集或逃逸容器。在本章中,我們將討論如何實作 Pod 安全策略(PSP)來限制 Pod 的攻擊面,以及如何監控程式、檔案存取和執行階段安全。

Pod 安全策略(PSP)

PSP 是 Kubernetes 中的一種叢集範圍的資源,用於在 Pod 被允許執行之前檢查一系列條件。PSP 可以幫助限制 Pod 的攻擊面。

PSP 的實作細節

PSP 的實作涉及 Pod 安全上下文的設定。儘管 PSP 在 Kubernetes v1.21 中已被棄用,但由於其仍被廣泛使用,因此在本章中仍會討論。

程式監控和執行階段安全

本章還將討論程式監控的需求,以及如何使用核心安全功能(如 seccomp、SELinux 和 AppArmor)來防止容器存取主機資源。

Pod Security Policies:Kubernetes的安全防護機制

Pod Security Policies(PSP)是Kubernetes中的一種安全機制,用於控制Pod的建立和執行。PSP允許管理員定義一組安全規則,以確保Pod以最小的許可權執行,從而減少攻擊面。

為什麼需要Pod Security Policies?

在Kubernetes中,Pod是執行應用程式的基本單位。然而,如果沒有適當的安全控制,Pod可能會以過高的許可權執行,從而對叢集的安全構成威脅。PSP的目的是確保Pod以最小的許可權執行,以防止潛在的安全風險。

Pod Security Policies的工作原理

PSP透過Admission Controller來實作。Admission Controller會評估每個Pod建立請求,以確保其符合指定的PSP。如果Pod不符合PSP的要求,則建立請求將被拒絕。

使用Pod Security Policies

要使用PSP,需要進行以下步驟:

  1. 建立PSP:定義一組安全規則,以控制Pod的建立和執行。
  2. 建立ClusterRole:定義一個ClusterRole,以授權Pod佈署控制器使用PSP。
  3. 建立ClusterRoleBinding:將ClusterRole繫結到特定的群組或服務帳戶。

以下是一個PSP的示例:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535

內容解密:

此PSP定義了一組嚴格的安全規則,包括:

  • 禁止特權模式
  • 禁止許可權提升
  • 丟棄所有Linux capabilities
  • 限制可使用的卷型別
  • 禁止使用主機網路、IPC和PID名稱空間
  • 要求容器以非root使用者執行
  • 定義了supplementalGroups和fsGroup的規則

Pod Security Policy的能力

PSP提供了多種能力,可以根據具體需求進行組態。以下是一些常見的能力:

  • privileged:允許容器以特權模式執行。
  • hostPID、hostIPC:允許容器存取主機的PID和IPC名稱空間。
  • hostNetwork、hostPorts:允許容器存取主機的網路和埠。
  • volumes:允許容器使用特定的卷型別。
  • allowedHostPaths:允許容器使用特定的主機路徑。
  • fsGroup:定義了擁有Pod卷的GID或GID範圍。
  • readOnlyRootFilesystem:將容器的根檔案系統設定為只讀。
  • runAsUser、runAsGroup、supplementalGroups:定義了容器的UID和GID。