強化叢集安全性


本頁面會帶領您實踐目前的最佳做法,強化 Google Kubernetes Engine (GKE) 叢集。本指南會優先介紹客戶在建立叢集時,需要採取的重要安全緩解措施。而重要性較低的功能、預設已將安全性納入考量的設定、可於建立後再啟用的項目,則於文章後段再細談。

這份文件適用於安全專家,他們負責定義、管理及實作政策和程序,以防機構的資料遭到未經授權的存取。如要進一步瞭解 Google Cloud 內容中提及的常見角色和範例工作,請參閱常見的 GKE Enterprise 使用者角色和工作

閱讀本頁面之前,請先熟悉下列概念:

如果您要在 GKE 上建立新叢集,根據預設,這類防護功能大多數會啟用。如果要升級現有叢集,請務必定期查看此強化指南並啟用新功能。

以 Autopilot 模式建立的叢集預設會實作許多 GKE 強化功能。

您可以使用安全性狀態分析功能,自動檢查大多數的建議事項和其他常見設定錯誤。

定期升級 GKE 基礎架構

CIS GKE 基準建議:6.5.3。確保 GKE 節點已啟用節點自動升級功能

如要提高安全防護效能,最簡單的方法之一是讓 Kubernetes 保持在最新版本。Kubernetes 經常推出新的安全防護功能,並提供安全修補程式。

請參閱 GKE 安全性公告,瞭解安全修補程式的相關資訊。

在 Google Kubernetes Engine 中,系統會自動修補及升級控制層。節點自動升級功能也會自動升級叢集中的節點。

自 2019 年 6 月起,透過Google Cloud 控制台建立的叢集,以及自 2019 年 11 月 11 日起使用 API 建立的叢集,根據預設皆會啟用節點自動升級功能。

如果您選擇停用節點自動升級功能,建議您每個月自行升級一次。請在舊叢集選擇加入節點自動升級功能,並密切留意 GKE 安全性公告以取得重要修補程式。

詳情請參閱自動升級節點

限制控制層和節點的網路存取權

CIS GKE Benchmark Recommendations:6.6.2。建議使用虛擬私有雲原生叢集,6.6.3 版。確保已啟用授權網路,6.6.4. 確保叢集建立時啟用了私人端點,並停用公開存取權,確保叢集建立時使用了私人節點

根據預設,GKE 叢集控制層和節點具有可從任何 IP 位址存取的網際網路轉送位址。

最佳做法

限制叢集控制層和節點在網際網路上的暴露程度。

限制控制層存取權

如要限制 GKE 叢集控制層的存取權,請參閱設定控制層存取權。 以下是網路層級防護的選項:

  • 啟用以 DNS 為基礎的端點 (建議):您可以透過 VPC Service Controls,控管哪些人可以存取以 DNS 為基礎的端點。VPC Service Controls 可讓您為專案中的所有 Google API 定義一個安全參數,並使用情境感知屬性 (例如網路來源)。您可以在所有 Google API 中集中控管專案的這些設定,減少必須設定存取規則的位置數量。

  • 停用外部和內部 IP 型端點存取權:這會禁止透過 IP 型端點存取控制層。

  • 停用外部 IP 型端點存取權:這會禁止透過網際網路存取兩個控制層。如果已將內部部署網路設定為使用Google Cloud 連線至 Cloud InterconnectCloud VPN,相當建議選擇此選項。這兩種技術可以有效地將您的公司網路連線至雲端 VPC。

  • 啟用外部 IP 型端點存取權並啟用授權網路這個選項可限制從您定義的來源 IP 位址存取控制層。如果您不具備既有的 VPN 基礎架構,或是遠端使用者或分公司需要透過公開網際網路進行連線 (而非使用公司 VPN 及 Cloud Interconnect 或 Cloud VPN),建議選擇此選項。

  • 啟用外部端點存取權,停用授權網路:這項設定允許網際網路上的任何人建立與控制層之間的網路連線。

如果使用以 IP 為基礎的端點,建議叢集使用授權網路

這樣可確保透過下列方式連線到控制層:

  • 授權網路中允許的 CIDR。
  • 叢集虛擬私人雲端 (VPC) 中的節點。
  • Google 保留的 IP 位址,用於叢集管理。

限制節點存取權

最佳做法

在叢集上啟用私人節點,防止外部用戶端存取節點。

如要停用對節點的直接網際網路存取,請在建立叢集時,指定 gcloud CLI 選項 --enable-private-nodes

如此即可告知 GKE 使用內部 IP 位址佈建節點,也就是無法直接透過公開網際網路連接到該節點。

限制叢集端點的匿名存取權

這項安全性改善措施可限制叢集端點的匿名存取權,有助於降低因意外或惡意角色繫結而造成的風險。根據預設,Kubernetes 會將 system:anonymous 使用者和 system:unauthenticated 群組指派給叢集端點的匿名要求。如果該使用者或群組透過 RBAC 繫結在叢集中擁有權限,可能會讓匿名使用者意外存取端點,進而危害服務或叢集本身的安全性。

除非透過 RBAC 繫結明確限制,否則所有叢集端點都會接受匿名驗證要求。在 GKE 1.32.2-gke.1234000 以上版本中,建立或更新叢集時,您可以將匿名要求可連線的端點集限制為僅限三個 Kubernetes API 伺服器健康狀態檢查端點:/healthz/livez/readyz。您必須匿名存取這些健康狀態檢查端點,才能確認叢集是否正常運作。

如要限制叢集端點的匿名存取權,請在下列任一 gcloud CLI 指令中,為 --anonymous-authentication-config 旗標指定 LIMITED

--anonymous-authentication-config 旗標的值可以是 LIMITEDENABLED。預設值為 ENABLED。將值設為 LIMITED 時,即使現有的 RBAC 繫結允許這類存取權,系統仍會在驗證期間拒絕匿名要求。遭拒的要求會傳回 HTTP 狀態 401

如下列範例所示,您可以使用機構政策限制,在機構的叢集中強制執行這項存取限制:

name: organizations/ORGANIZATION_ID/customConstraints/custom.gkeAnonymousAccessLimited
    resourceTypes:
    - container.googleapis.com/Cluster
    methodTypes:
    - CREATE
    - UPDATE
    condition: "condition:resource.anonymousAuthenticationConfig.mode == "LIMITED"
    action: ALLOW
    displayName: Restrict anonymous access to cluster endpoints.
    description: All new and updated clusters must restrict anonymous access to cluster endpoints.

ORGANIZATION_ID 替換為機構 ID,例如 123456789

請勿只依賴這項功能來保護叢集安全。請考慮採取下列額外安全措施:

如要瞭解這項強化功能的基礎 Kubernetes 實作方式,請參閱「匿名驗證器設定」。如要進一步瞭解角色型存取權控管 (RBAC) 政策,請參閱 GKE RBAC 最佳做法

使用最低權限防火牆規則

使用防火牆規則的最小許可權原則,盡量降低非預期存取行為的風險

GKE 會建立預設的虛擬私有雲防火牆規則,以啟用系統功能並落實良好的安全做法。如需自動建立的防火牆規則完整清單,請參閱「自動建立的防火牆規則」一文。

GKE 會建立優先順序為 1000 的預設防火牆規則。如果您建立優先順序較高的寬鬆防火牆規則 (例如用於偵錯的 allow-all 防火牆規則),叢集可能會遭到未經授權的存取。

使用群組驗證

CIS GKE 基準建議:6.8.3。建議使用 RBAC 適用的 Google 群組管理 Kubernetes RBAC 使用者

請使用群組管理您的使用者。使用群組可讓您使用 Identity 管理系統和 Identity 管理員來控制身分。透過調整群組成員資格的方式,當新增或移除群組成員時,就無需更新 RBAC 設定。

如要使用 Google 網路論壇管理使用者權限,則須在叢集上啟用 RBAC 適用的 Google 網路論壇。這樣一來,您就能管理具有相同權限的使用者,同時身分管理員也能集中管理使用者並保持一致性。

如要瞭解如何啟用 RBAC 適用的 Google 群組,請參閱這篇文章

設定容器節點的安全性

以下各節會說明安全的節點設定選項。

啟用受防護的 GKE 節點

CIS GKE 基準建議:6.5.5。確保已啟用 Shielded GKE 節點

受防護的 GKE 節點提供可驗證的高強度節點身分和完整性,可進一步提高節點的安全性,應在所有的 GKE 叢集上啟用此類節點。

您可以在建立或更新叢集時啟用受防護的 GKE 節點。受防護的 GKE 節點應與安全啟動功能一起啟用。如果您需要第三方未簽署的核心模組,請不要使用安全啟動。如要瞭解如何啟用受防護的 GKE 節點,以及如何搭配受防護的 GKE 節點啟用安全啟動功能,請參閱「使用受防護的 GKE 節點」。

選擇含有 containerd 執行階段的強化節點映像檔

含有 containerd (cos_containerd) 映像檔的 Container-Optimized OS 是 Container-Optimized OS 映像檔的變體,以 containerd 做為直接與 Kubernetes 整合的容器執行階段。

containerd 是 Docker 的核心執行階段元件,用於提供 Kubernetes 容器執行階段介面 (CRI) 的核心容器功能。此元件比完整的 Docker Daemon 單純許多,因此攻擊面更少。

如要在叢集中使用 cos_containerd 映像檔,請參閱「Containerd 映像檔」。

cos_containerd 映像檔是 GKE 的首選映像檔,因為它是專為執行容器而打造,經過最佳化及強化處理

啟用 GKE 適用的工作負載身分聯盟

CIS GKE 基準建議:6.2.2。建議您使用專屬的 Google Cloud 服務帳戶和 Workload Identity

如要向 Google Cloud API 進行驗證,建議使用 Workload Identity Federation for GKE

GKE 適用的 Workload Identity Federation 取代了使用中繼資料隱藏功能的必要性,因此這兩種方法互不相容。由「中繼資料隱藏功能」保護的敏感中繼資料,也會受到 Workload Identity Federation for GKE 保護。

使用 GKE Sandbox 強化工作負載隔離

CIS GKE 基準建議:6.10.4。建議您使用 GKE Sandbox 強化工作負載隔離,特別是不受信任的工作負載

GKE Sandbox 提供額外的安全防護層,可防止惡意程式碼影響叢集節點上的主機核心。

您可以在沙箱環境中執行容器,防範大多數容器逸出攻擊 (也稱為本機權限提升攻擊)。如要瞭解過去的容器跳脫安全漏洞,請參閱安全性公告。攻擊者可藉此存取容器的主機 VM,進而存取同一 VM 上的其他容器。例如 GKE Sandbox 等沙箱可協助限制這類攻擊的影響。

在下列情況中,建議您將工作負載放入沙箱:

  • 工作負載執行不受信任的程式碼
  • 您希望在攻擊者入侵工作負載中的容器時,將影響降到最低。

請參閱「使用 GKE Sandbox 強化工作負載隔離」,瞭解如何使用 GKE Sandbox。

啟用安全性公告通知

如果出現與叢集相關的安全性公告,GKE 會將這些事件的通知以訊息形式發布至您設定的 Pub/Sub 主題。您可以透過 Pub/Sub 訂閱項目接收這類通知、整合第三方服務,並篩選需要的通知類型

如要進一步瞭解如何透過 GKE 叢集通知接收安全性公告,請參閱「叢集通知」。

停用不安全的 kubelet 唯讀連接埠

停用 kubelet 唯讀通訊埠,並將使用通訊埠 10255 的任何工作負載,改為使用更安全的通訊埠 10250

節點上執行的 kubelet 程序會使用不安全的 10255 連接埠,提供唯讀 API。Kubernetes 不會對這個通訊埠執行任何驗證或授權檢查。kubelet 會在更安全的已驗證通訊埠 10250 上提供相同的端點。

如需操作說明,請參閱在 GKE 叢集中停用 kubelet 唯讀埠

授予存取權限

下列各節說明如何授予 GKE 基礎架構的存取權。

使用最低權限的 IAM 服務帳戶

CIS GKE 基準建議:6.2.1。建議不要使用 Compute Engine 預設服務帳戶執行 GKE 叢集

GKE 會使用附加至節點的 IAM 服務帳戶,執行記錄和監控等系統工作。這些節點服務帳戶至少必須具備專案的「Kubernetes Engine 預設節點服務帳戶」(roles/container.defaultNodeServiceAccount) 角色。根據預設,GKE 會使用專案中自動建立的 Compute Engine 預設服務帳戶做為節點服務帳戶。

如果您在專案或機構中將 Compute Engine 預設服務帳戶用於其他函式,該服務帳戶的權限可能超出 GKE 的需求,進而導致安全風險。

附加至節點的服務帳戶應僅供執行記錄和監控等工作的系統工作負載使用。對於您自己的工作負載,請使用 Workload Identity Federation for GKE 佈建身分。

如要建立自訂服務帳戶,並授予 GKE 服務帳戶所需角色,請完成下列步驟:

控制台

  1. 在 Google Cloud 控制台中,啟用 Cloud Resource Manager API:

    Enable the API

  2. 前往「Service accounts」(服務帳戶) 頁面:

    前往「Service accounts」(服務帳戶)

  3. 按一下 「建立服務帳戶」
  4. 輸入服務帳戶名稱。系統會根據名稱,在「服務帳戶 ID」欄位中自動產生服務帳戶的專屬 ID。
  5. 按一下「建立並繼續」
  6. 在「Select a role」(選取角色) 選單中,選取「Kubernetes Engine Default Node Service Account」(Kubernetes Engine 預設節點服務帳戶) 角色。
  7. 按一下 [完成]

gcloud

  1. 啟用 Cloud Resource Manager API:
    gcloud services enable cloudresourcemanager.googleapis.com
  2. 建立服務帳戶:
    gcloud iam service-accounts create SA_NAME

    SA_NAME 替換為可識別服務帳戶的不重複名稱。

  3. Kubernetes Engine 預設節點服務帳戶 (roles/container.defaultNodeServiceAccount) 角色授予服務帳戶:
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member="serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
        --role=roles/container.defaultNodeServiceAccount

    更改下列內容:

    • PROJECT_ID:您的 Google Cloud 專案 ID。
    • SA_NAME:您建立的服務帳戶名稱。

設定連接器

附註:此步驟需要使用設定連接器。請按照安裝操作說明在叢集上安裝設定連接器。

  1. 如要建立服務帳戶,請以 service-account.yaml 格式下載以下資源:
    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMServiceAccount
    metadata:
      name: [SA_NAME]
    spec:
      displayName: [DISPLAY_NAME]

    更改下列內容:

    • [SA_NAME]:新服務帳戶的名稱。
    • [DISPLAY_NAME]:服務帳戶的顯示名稱。
  2. 建立服務帳戶:
    kubectl apply -f service-account.yaml
  3. 在服務帳戶中套用 roles/logging.logWriter 角色:
    1. policy-logging.yaml 格式下載下列資源。
      apiVersion: iam.cnrm.cloud.google.com/v1beta1
      kind: IAMPolicyMember
      metadata:
        name: policy-logging
      spec:
        member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
        role: roles/logging.logWriter
        resourceRef:
          kind: Project
          name: [PROJECT_ID]

      更改下列內容:

      • [SA_NAME]:服務帳戶的名稱。
      • [PROJECT_ID]:您的 Google Cloud 專案 ID。
    2. 將角色套用至服務帳戶:
      kubectl apply -f policy-logging.yaml
  4. 在服務帳戶中套用 roles/monitoring.metricWriter 角色:
    1. policy-metrics-writer.yaml 格式下載以下資源。 將 [SA_NAME][PROJECT_ID] 改成您自己的資訊。
      apiVersion: iam.cnrm.cloud.google.com/v1beta1
      kind: IAMPolicyMember
      metadata:
        name: policy-metrics-writer
      spec:
        member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
        role: roles/monitoring.metricWriter
        resourceRef:
          kind: Project
          name: [PROJECT_ID]

      更改下列內容:

      • [SA_NAME]:服務帳戶的名稱。
      • [PROJECT_ID]:您的 Google Cloud 專案 ID。
    2. 將角色套用至服務帳戶:
      kubectl apply -f policy-metrics-writer.yaml
  5. 在服務帳戶中套用 roles/monitoring.viewer 角色:
    1. policy-monitoring.yaml 格式下載以下資源。
      apiVersion: iam.cnrm.cloud.google.com/v1beta1
      kind: IAMPolicyMember
      metadata:
        name: policy-monitoring
      spec:
        member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
        role: roles/monitoring.viewer
        resourceRef:
          kind: Project
          name: [PROJECT_ID]

      更改下列內容:

      • [SA_NAME]:服務帳戶的名稱。
      • [PROJECT_ID]:您的 Google Cloud 專案 ID。
    2. 將角色套用至服務帳戶:
      kubectl apply -f policy-monitoring.yaml
  6. 在服務帳戶中套用 roles/autoscaling.metricsWriter 角色:
    1. policy-autoscaling-metrics-writer.yaml 格式下載以下資源。
      apiVersion: iam.cnrm.cloud.google.com/v1beta1
      kind: IAMPolicyMember
      metadata:
        name: policy-autoscaling-metrics-writer
      spec:
        member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
        role: roles/autoscaling.metricsWriter
        resourceRef:
          kind: Project
          name: [PROJECT_ID]

      更改下列內容:

      • [SA_NAME]:服務帳戶的名稱。
      • [PROJECT_ID]:您的 Google Cloud 專案 ID。
    2. 將角色套用至服務帳戶:
      kubectl apply -f policy-autoscaling-metrics-writer.yaml

您也可以將這個服務帳戶用於其他專案的資源。如需操作說明,請參閱「啟用跨專案的服務帳戶模擬功能」。

授予私人映像檔存放區的存取權

如要在 Artifact Registry 中使用私人映像檔,請將Artifact Registry 讀取者角色 (roles/artifactregistry.reader) 授予服務帳戶。

gcloud

gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
    --member=serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --role=roles/artifactregistry.reader

REPOSITORY_NAME 替換為 Artifact Registry 存放區名稱。

設定連接器

附註:此步驟需要使用設定連接器。請按照安裝操作說明在叢集上安裝設定連接器。

  1. 將下列資訊清單儲存為 policy-artifact-registry-reader.yaml

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-artifact-registry-reader
    spec:
      member: serviceAccount:"SA_NAME"@"PROJECT_ID".iam.gserviceaccount.com
      role: roles/artifactregistry.reader
      resourceRef:
        apiVersion: artifactregistry.cnrm.cloud.google.com/v1beta1
        kind: ArtifactRegistryRepository
        name: "REPOSITORY_NAME"

    更改下列內容:

    • SA_NAME:IAM 服務帳戶的名稱。
    • PROJECT_ID:您的 Google Cloud 專案 ID。
    • REPOSITORY_NAME:Artifact Registry 存放區的名稱。
  2. 將 Artifact Registry 讀者角色指派給服務帳戶:

    kubectl apply -f policy-artifact-registry-reader.yaml
    

如果您使用的是 Container Registry 中的私人映像檔,還必須將存取權授予那些私人映像檔:

gcloud

gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
  --member=serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
  --role=roles/storage.objectViewer

儲存圖片的值區名稱 BUCKET_NAME 格式如下:

  • artifacts.PROJECT_ID.appspot.com,適用於推送至 gcr.io 主機中註冊資料庫的映像檔,或是
  • STORAGE_REGION.artifacts.PROJECT_ID.appspot.com

更改下列內容:

  • PROJECT_ID:您的 Google Cloud 控制台專案 ID。
  • STORAGE_REGION:儲存空間 bucket 的位置:
    • us,適用於 us.gcr.io 主機中的註冊資料庫
    • eu,適用於 eu.gcr.io 主機中的註冊資料庫
    • asia,適用於 asia.gcr.io 主機中的註冊資料庫

如要進一步瞭解指令,請參閱 gcloud storage buckets add-iam-policy-binding 說明文件。

設定連接器

附註:此步驟需要使用設定連接器。請按照安裝操作說明在叢集上安裝設定連接器。

在服務帳戶中套用 storage.objectViewer 角色。以 policy-object-viewer.yaml 格式下載以下資源。將 [SA_NAME][PROJECT_ID] 改成您自己的資訊。

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-object-viewer
spec:
  member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/storage.objectViewer
  resourceRef:
    kind: Project
    name: [PROJECT_ID]
kubectl apply -f policy-object-viewer.yaml

如果您想讓其他人類使用者能使用此服務帳戶建立新的叢集或節點集區,則須授予對方此服務帳戶的「服務帳戶使用者」角色:

gcloud

gcloud iam service-accounts add-iam-policy-binding \
    SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --member=user:USER \
    --role=roles/iam.serviceAccountUser

設定連接器

附註:此步驟需要使用設定連接器。請按照安裝操作說明在叢集上安裝設定連接器。

在服務帳戶中套用 iam.serviceAccountUser 角色。以 policy-service-account-user.yaml 格式下載以下資源。將 [SA_NAME][PROJECT_ID] 改成您自己的資訊。

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-service-account-user
spec:
  member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/iam.serviceAccountUser
  resourceRef:
    kind: Project
    name: [PROJECT_ID]
kubectl apply -f policy-service-account-user.yaml

對於現有的標準叢集,您現在可以使用這個新的服務帳戶建立新的節點集區。如果是 Autopilot 叢集,您必須使用服務帳戶建立新叢集。如需操作說明,請參閱「建立 Autopilot 叢集」。

  • 建立使用新服務帳戶的節點集區:

    gcloud container node-pools create NODE_POOL_NAME \
    --service-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --cluster=CLUSTER_NAME

如果 GKE 叢集需要存取其他服務,請使用 Workload Identity Federation for GKE。 Google Cloud

限制叢集探索 API 的存取權

根據預設,Kubernetes 會使用一組探索 ClusterRoleBindings 權限來啟動叢集,這組權限可讓您廣泛存取叢集 API (包含 CustomResourceDefinitions 的 API) 的相關資訊。

使用者應瞭解,在 system:discoverysystem:basic-user ClusterRoleBindings 主題中包含的 system:authenticated 群組,可包含任何已驗證的使用者 (包括 Google 帳戶使用者),且不代表與 GKE 上叢集安全性有關的有意義等級。詳情請參閱「避免預設角色和群組」。

對於希望加強叢集探索 API 安全性的使用者,建議採取以下其中一項或多項措施:

  • 僅啟用 DNS 型端點,以存取控制層。
  • 設定授權網路來限制 IP 範圍設定的存取權。
  • 限制控制層存取權,並啟用私人節點。

如果上述選項都不適合您的 GKE 用途,您應將所有 API 探索資訊 (即 CustomResources 的結構定義、APIService 定義,以及擴充功能 API 伺服器代管的探索資訊) 視為公開揭露的資訊。

使用命名空間和 RBAC 來限制叢集資源的存取權

CIS GKE 基準建議:5.6.1。使用命名空間在資源之間建立管理界線

為每個團隊和環境分別建立不同的命名空間或叢集,授予團隊存取 Kubernetes 的最低權限。為每個命名空間分配成本中心與適當的標籤,以便於問責和退款。僅向開發人員提供部署和管理應用程式所需的命名空間存取層級 (尤其是在實際工作環境)。規劃您的使用者需要對叢集執行的工作,並定義執行各項工作所需的權限。

如要進一步瞭解如何建立命名空間,請參閱 Kubernetes 說明文件。如要瞭解規劃 RBAC 設定的最佳做法,請參閱「GKE RBAC 的最佳做法」。

IAM角色型存取控制 (RBAC) 會互相搭配運作,且實體必須擁有其中一個層級的完整權限,才能使用您叢集中的資源。

指派適當的 GKE IAM 角色給群組和使用者,以提供專案層級的權限,並使用 RBAC 授予叢集和命名空間層級的權限。詳情請參閱存取權控管一文。

您可以搭配使用 IAM 和 RBAC 權限與命名空間,限制使用者在 Google Cloud console 上與叢集資源的互動。詳情請參閱「 依命名空間啟用存取及查看叢集資源」。

使用網路政策限制 Pod 之間的流量

CIS GKE 基準建議:6.6.7。確保已啟用網路政策,並視需要進行設定

依預設,同一叢集裡的所有 Pod 都能互相通訊。您應該根據工作負載,視情況控管 Pod 到 Pod 的通訊。

限制對服務的網路存取權後,攻擊者會更難以在叢集內橫向移動,同時也能為服務提供部分保護,防範意外或刻意阻斷服務的情形。以下推薦兩種流量控制方法:

  1. 使用 Istio。如果您對負載平衡、服務授權、節流、配額及指標等感興趣,請參閱「在 Google Kubernetes Engine 上安裝 Istio」。
  2. 使用 Kubernetes 網路政策。請參閱建立叢集網路政策。如果需要 Kubernetes 公開的基本存取控制功能,請選擇此選項。如要採用常見方法,使用網路政策限制流量,請按照 GKE Enterprise 安全藍圖的實作指南操作。此外,Kubernetes 說明文件有極佳的逐步操作說明,可協助進行簡單的 nginx 部署。建議使用網路政策記錄,確認網路政策運作正常。

如有需要,也可以同時使用 Istio 和網路政策。

透過密鑰管理保護資料

CIS GKE 基準建議:6.3.1。考慮使用 Cloud KMS 管理的金鑰加密 Kubernetes Secret

請針對機密資料 (例如密鑰) 額外提供一層安全防護。如要這麼做,需設定與 GKE 叢集整合的密鑰管理員。部分解決方案在 GKE 和 Google Distributed Cloud 中均可執行,如果您是在多種環境中執行工作負載,可能更適合使用這類解決方案。如果選擇使用 HashiCorp Vault 這類外部密鑰管理員,則建議在建立叢集前先行設定。

有多種選項可供管理密鑰。

  • 您可以在 GKE 中以原生方式使用 Kubernetes 密鑰。您也可以使用應用程式層密鑰加密,在應用程式層以您管理的金鑰來進行加密。
  • 您可以使用密鑰管理系統,例如 HashiCorp Vault。在強化版的 HA 模式下執行時,即可提供一致且可用於實際工作環境的密鑰管理方式。您可以使用 Kubernetes 服務帳戶或 Google Cloud 服務帳戶來驗證 HashiCorp Vault。如要進一步瞭解如何搭配使用 GKE 與 Vault,請參閱在 Kubernetes 上執行並連線至 HashiCorp Vault

Google Cloud 預設會在儲存層級加密資料。 這項預設儲存層加密機制包括儲存叢集狀態的資料庫,該資料庫是以 etcd 或 Spanner 為基礎。

使用許可控制器強制執行政策

許可控制器是一種外掛程式,可管理並強制控制叢集的使用方式。必須先啟用這類程式,才能使用 Kubernetes 部分更為進階的安全功能,同時這也是強化叢集深度防護措施的重要環節之一。

依預設,Kubernetes 中的 Pod 能以超乎必要的功能運作。您應該將 Pod 的功能限制在工作負載需要的範圍內。

Kubernetes 支援多種控制項,可將 Pod 限制為僅以受到明確授權的功能來執行。舉例來說,機群中的叢集可以使用 Policy Controller。Kubernetes 也內建 PodSecurity 許可控制器,可讓您在個別叢集中強制執行 Pod 安全性標準。

Policy Controller 是 GKE Enterprise 的一項功能,可讓您使用宣告式政策,大規模強制執行及驗證 GKE 叢集的安全性。如要瞭解如何使用 Policy Controller 在 GKE 叢集上強制執行宣告式控制項,請參閱「安裝 Policy Controller」。

Pod 安全性許可控制器可讓您在特定命名空間或整個叢集中,強制執行預先定義的政策。這些政策對應不同的 Pod 安全性標準

限制工作負載自行修改的能力

特定 Kubernetes 工作負載 (尤其是系統工作負載) 有權自行修改。舉例來說,部分工作負載會自動垂直擴充。雖然方便,但如果攻擊者已入侵節點,就能在叢集中進一步擴大影響範圍。舉例來說,攻擊者可能會讓節點上的工作負載變更,以同一個命名空間中權限較高的服務帳戶身分執行。

理想情況下,工作負載不應獲得修改自身的權限。如果需要自行修改,您可以套用 Gatekeeper 或 Policy Controller 限制 (例如開放原始碼 Gatekeeper 程式庫中的 NoUpdateServiceAccount),藉此限制權限。這個程式庫提供多項實用的安全性政策。

部署政策時,通常需要允許管理叢集生命週期的控制器略過政策。這是必要步驟,因為控制器需要變更叢集,例如套用叢集升級。舉例來說,如果您在 GKE 上部署 NoUpdateServiceAccount 政策,就必須在 Constraint 中設定下列參數:

parameters:
  allowedGroups:
  - system:masters
  allowedUsers:
  - system:addon-manager

限制使用已淘汰的 gcePersistentDisk 磁碟區類型

已淘汰的 gcePersistentDisk 磁碟區類型可讓您將 Compute Engine 永久磁碟掛接至 Pod。建議您在工作負載中限制使用 gcePersistentDisk 磁碟區類型。掛接這類磁碟區時,GKE 不會對 Pod 執行任何 IAM 授權檢查,但 Google Cloud 將磁碟掛接到基礎 VM 時,會執行授權檢查。因此,如果攻擊者已能在命名空間中建立 Pod,就能存取 Google Cloud 專案中 Compute Engine 永久磁碟的內容。

如要存取及使用 Compute Engine 永久磁碟,請改用 PersistentVolumes 和 PersistentVolumeClaims。在叢集中套用安全性政策,禁止使用 gcePersistentDisk 磁碟區類型。

如要禁止使用 gcePersistentDisk 磁碟區類型,請套用 Baseline 或 Restricted 政策,並搭配 PodSecurity 許可控制器,或在 Policy Controller 或 Gatekeeper 許可控制器中定義自訂限制。

如要定義自訂限制來限制這個磁碟區類型,請執行下列操作:

  1. 安裝以政策為基礎的許可控制器,例如 Policy Controller 或 Gatekeeper OPA。

    Policy Controller

    在叢集中安裝 Policy Controller

    Policy Controller 是 GKE 使用者的付費功能。 Policy Controller 以開放原始碼 Gatekeeper 為基礎,但您也可以存取完整的限制範本庫、政策套裝組合,以及與 Google Cloud 控制台資訊主頁的整合功能,有助於觀察及維護叢集。政策套裝組合是您可套用至叢集的最佳做法,包括根據建議 (例如 CIS Kubernetes 基準) 建立的套裝組合。

    Gatekeeper

    在叢集中安裝 Gatekeeper

    如果是 Autopilot 叢集,請在文字編輯器中開啟 Gatekeeper gatekeeper.yaml 資訊清單。修改 MutatingWebhookConfiguration 規格中的 rules 欄位,將萬用字元 (*) 替換為特定 API 群組和資源名稱,如下列範例所示:

    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    ...
    webhooks:
    - admissionReviewVersions:
      - v1
      - v1beta1
      ...
      rules:
      - apiGroups:
        - core
        - batch
        - apps
        apiVersions:
        - '*'
        operations:
        - CREATE
        - UPDATE
        resources:
        - Pod
        - Deployment
        - Job
        - Volume
        - Container
        - StatefulSet
        - StorageClass
        - Secret
        - ConfigMap
      sideEffects: None
      timeoutSeconds: 1
    

    將更新後的 gatekeeper.yaml 資訊清單套用至 Autopilot 叢集,安裝 Gatekeeper。這是必要步驟,因為 Autopilot 會禁止變動准入 Webhook 中的萬用字元,以做為內建安全措施。

  2. 部署內建的 Pod 安全性政策磁碟區類型 ConstraintTemplate:

    kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/volumes/template.yaml
    
  3. 將下列限制連同允許的磁碟區類型清單儲存為 constraint.yaml

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: k8sPSPVolumeTypes
    metadata:
      name: nogcepersistentdisk
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pods"]
      parameters:
        volumes: ["configMap", "csi", "projected", "secret", "downwardAPI", "persistentVolumeClaim", "emptyDir", "nfs", "hostPath"]
    

    這項限制會將卷冊限制為 spec.parameters.volumes 欄位中的清單。

  4. 部署限制:

    kubectl apply -f constraint.yaml
    

監控您的叢集設定

請檢查您的叢集設定是否與定義的設定有所出入。

您可以使用安全性狀態分析功能,自動檢查本強化指南中提到的大多數建議事項,以及其他常見設定錯誤。

查看預設安全選項

以下各節會介紹在新叢集中,根據預設已先安全設定完畢的選項。請確認先前已存在的叢集設定安全無誤。

保護節點中繼資料

CIS GKE 基準建議:6.4.1。確保舊版 Compute Engine 執行個體中繼資料 API 已停用,且版本為 6.4.2。確保已啟用 GKE 中繼資料伺服器

v0.1v1beta1 Compute Engine 中繼資料伺服器端點已於 2020 年 9 月 30 日淘汰並關閉。這些端點不會強制使用中繼資料查詢標頭。如需關閉時間表,請參閱「v0.1v1beta1 中繼資料伺服器端點淘汰」一文。

有些針對 Kubernetes 發動的實際攻擊事件,是靠著存取 VM 中繼資料伺服器來擷取憑證。若您使用的是 Workload Identity Federation for GKE中繼資料隱藏功能,系統就會封鎖這類攻擊。

停用舊版用戶端驗證方法

CIS GKE 基準建議:6.8.1。確保已停用使用靜態密碼的基本驗證,且 6.8.2。確保已停用用戶端憑證驗證功能

Kubernetes API 伺服器有好幾種驗證方法。在 GKE 中,支援的方法有服務帳戶不計名憑證、OAuth 憑證和 x509 用戶端憑證。GKE 會使用 gcloud 為您管理驗證作業:使用 OAuth 憑證方法、設定 Kubernetes、取得存取憑證並持續更新。

在 GKE 與 OAuth 整合之前,一次性產生的 x509 憑證或靜態密碼是唯一可用的驗證方法,現在我們不建議使用以上方法,且應停用。這些方法的受攻擊面較大,叢集容易遭駭,因此自 GKE 1.12 版起,這些方法預設為停用。如果您使用舊版驗證方法,建議停用這些方法。使用靜態密碼進行驗證已遭淘汰,且自 GKE 1.19 版起已移除。

請將現有叢集移至 OAuth。如果叢集外部的系統需要使用長期憑證,建議您建立具有必要權限的 Google 服務帳戶或 Kubernetes 服務帳戶,並匯出金鑰。

如要更新現有叢集並移除靜態密碼,請參閱「停用靜態密碼驗證」。

目前沒有方法可從現有叢集移除預先核發的用戶端憑證,但如果啟用 RBAC 且停用 ABAC,則此憑證就不具權限。

維持啟用 Cloud Logging

CIS GKE 基準建議:6.7.1。確保已啟用 Stackdriver Kubernetes Logging 和 Monitoring

如要降低作業負擔,並維持記錄檔的統整檢視畫面,請在部署叢集的位置採用一致的記錄策略。根據預設,GKE Enterprise 叢集會與 Cloud Logging 整合,且應會保留設定。

所有 GKE 叢集預設會啟用 Kubernetes 稽核記錄功能,依時間順序記錄對 Kubernetes API 伺服器做出的呼叫。Kubernetes 稽核記錄項目適合用於調查可疑的 API 要求、收集統計資料,或是針對不想要的 API 呼叫建立監控快訊。

GKE 叢集整合 Kubernetes Audit Logging 與 Cloud Audit LogsCloud Logging。記錄檔可以從 Cloud Logging 路由傳送至您自己的記錄系統。

維持停用 Kubernetes 網頁版 UI (資訊主頁)

CIS GKE 基準建議:6.10.1。確保已停用 Kubernetes 網頁版 UI

在 GKE 上執行時,請停用 Kubernetes 網頁版 UI (資訊主頁)。

高權限 Kubernetes 服務帳戶支援 Kubernetes 網頁版 UI (資訊主頁)。Google Cloud 控制台提供許多相同的功能,因此您不需要這些權限。

如要停用 Kubernetes 網頁版 UI,請按照下列步驟操作:

gcloud container clusters update CLUSTER_NAME \
    --update-addons=KubernetesDashboard=DISABLED

維持停用 ABAC

CIS GKE 基準建議:6.8.4。確保已停用舊版授權 (ABAC)

您應該停用屬性型存取權控管 (ABAC),改成在 GKE 中使用角色型存取權控管 (RBAC)。

根據預設,使用 GKE 1.8 以上版本建立的叢集會停用 ABAC。在 Kubernetes 中,RBAC 用於將權限授予叢集和命名空間層級的資源。RBAC 可讓您使用含有一組權限的規則來定義角色。RBAC 在安全性方面比 ABAC 具有顯著優勢。

如果您仍然仰賴 ABAC,請先查閱使用 RBAC 的事前準備。如果您已從舊版升級叢集,且目前正在使用 ABAC,則應該更新存取權控管設定:

gcloud container clusters update CLUSTER_NAME \
    --no-enable-legacy-authorization

依照上述建議來建立新叢集:

gcloud container clusters create CLUSTER_NAME \
    --no-enable-legacy-authorization

保持啟用DenyServiceExternalIPs准入控制器

請勿停用 DenyServiceExternalIPs 准入控制器。

DenyServiceExternalIPs 准入控制器會禁止服務使用 ExternalIP,並減輕已知安全漏洞的影響。

在 GKE 1.21 以上版本中建立的新叢集,預設會啟用 DenyServiceExternalIPs 准入控制器。如要將叢集升級至 GKE 1.21 以上版本,可以使用下列指令啟用許可控制器:

gcloud beta container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --no-enable-service-externalips

後續步驟