Skip to content

Security Model & Shared Responsibility — Bản Đồ Phòng Thủ

Vì sao mô hình trách nhiệm là điều đầu tiên phải hiểu

Nguyên nhân số một của sự cố bảo mật trên managed Kubernetes không phải là lỗ hổng zero-day — mà là hiểu sai về việc ai chịu trách nhiệm cho lớp nào. Đội ngũ giả định Google "lo phần bảo mật" vì GKE là managed service, rồi để workload chạy root, network phẳng, image không scan. Ngược lại, có đội tốn công hardening control plane — thứ Google đã làm — trong khi bỏ ngỏ những thứ thực sự thuộc về họ. Cả hai sai lầm đều bắt nguồn từ việc không có một bản đồ rõ ràng về ranh giới trách nhiệm.

Trên GKE, bảo mật là một hợp đồng hai bên. Google nhận một phần; bạn nhận phần còn lại; và vùng ở giữa — nơi ranh giới mờ — là nơi mọi sự cố xảy ra. Mục tiêu của file này là vẽ ranh giới đó thật sắc nét, cho cả GKE Standard lẫn Autopilot, rồi đặt nó vào một khung defense-in-depth để bạn biết: lớp nào ai giữ, lớp nào nếu thủng thì hệ quả tới đâu, và đâu là lớp bạn buộc phải tự bảo vệ.

Theo tài liệu GKE security overview, bảo mật GKE được mô tả là một mô hình shared responsibility trải dài nhiều lớp hạ tầng và ứng dụng. Điểm quan trọng cần nội tâm hóa: ranh giới này dịch chuyển tùy theo chế độ vận hành (Standard vs Autopilot) và tùy theo từng tính năng cụ thể. Không có một đường kẻ cố định — có một phổ trách nhiệm.

Internal model: shared responsibility chia thế nào

Những gì Google luôn quản lý

Bất kể Standard hay Autopilot, Google chịu trách nhiệm cho phần hạ tầng nền tảng mà bạn không có quyền chạm tới:

  • Control plane: API server, scheduler, controller-manager, và etcd chạy trong project do Google quản lý, không nằm trong project của bạn. Bạn không SSH vào được control plane node. Google patch, scale, và bảo vệ các thành phần này.
  • Mã hóa etcd at-rest: dữ liệu cluster state (bao gồm cả Kubernetes Secrets ở dạng base64) được mã hóa at-rest bởi Google bằng key do Google quản lý theo mặc định. Bạn có thể nâng cấp lên Application-layer Secrets Encryption với Cloud KMS để mã hóa thêm một lớp envelope cho Secrets — đó là phần bạn quyết định bật.
  • Datapath nền tảng và physical security: data center, phần cứng, mạng vật lý, BIOS/firmware của host — toàn bộ thuộc Google (đối chiếu Chương 2 về hạ tầng vật lý).
  • Vá lỗ hổng control plane: khi có CVE ở tầng Kubernetes control plane, Google rollout bản vá qua release channel.

Những gì bạn luôn quản lý

Đây là phần thường bị đánh giá thấp, và là nơi tập trung gần như toàn bộ rủi ro thực tế:

  • Workload security: image bạn deploy, securityContext, có chạy root không, có privileged không. Google không biết và không kiểm soát code của bạn.
  • Authorization trong cluster (RBAC): ai có quyền gì trong cluster là việc của bạn. Google cấp IAM ở tầng project, nhưng RBAC bên trong là trách nhiệm của bạn hoàn toàn.
  • Network Policy: lưu lượng giữa các Pod. Mặc định Kubernetes là allow-all; nếu bạn không viết Network Policy, không có ai khác làm điều đó.
  • Secrets management thực sự: quyết định dùng Kubernetes Secret hay Secret Manager, có rotate không, có để key tĩnh trong image không.
  • Image và supply chain: scan vulnerability, ký attestation, kiểm soát registry. Google cung cấp công cụ (Artifact Analysis, Binary Authorization) nhưng bạn phải bật và cấu hình.
  • Cấu hình hardening của cluster: bật Shielded nodes, Workload Identity, private cluster, tắt legacy auth — đây là các nút bạn phải gạt.

Vùng xám: node OS và phụ thuộc vào auto-upgrade

Phần gây tranh cãi nhất là node. Trên GKE Standard, node là VM trong project của bạn. Ai patch OS của node?

Câu trả lời phụ thuộc vào cấu hình: nếu bạn dùng Container-Optimized OS (COS) và bật node auto-upgrade (mặc định với release channel), Google quản lý việc vá OS node — đây là lý do COS + auto-upgrade là khuyến nghị hardening cốt lõi. Nhưng nếu bạn tắt auto-upgrade, hoặc dùng custom node image, trách nhiệm patch OS chuyển về bạn. Đây chính là "vùng xám dịch chuyển theo cấu hình": một quyết định cấu hình của bạn quyết định ranh giới trách nhiệm nằm ở đâu.

Standard vs Autopilot: ranh giới dịch chuyển

Khác biệt lớn nhất về security model giữa hai chế độ là Autopilot dịch chuyển ranh giới trách nhiệm về phía Google và đồng thời áp đặt các default an toàn không thể tắt.

Khía cạnhGKE StandardGKE Autopilot
Node OS patchingBạn (qua auto-upgrade nếu bật)Google hoàn toàn
Truy cập node (SSH/privileged DaemonSet)Cho phépBị giới hạn mạnh — không SSH, hạn chế privileged
Pod Security mặc địnhBạn phải cấu hìnhÁp default cứng (cấm nhiều thứ như privileged, hostPath nhạy cảm)
Node service accountBạn chọn (dễ để default rộng)Quản lý chặt hơn, hướng least-privilege
Workload IdentityBạn phải bậtBật mặc định
Shielded nodesBạn phải bật (mặc định bật ở cluster mới)Luôn bật
Node configuration tự doToàn quyềnHạn chế để Google đảm bảo an toàn

Hệ quả thiết kế: Autopilot là lựa chọn "secure by default" mạnh hơn. Nó loại bỏ cả một lớp lỗi misconfiguration bằng cách không cho bạn cấu hình sai. Đổi lại, bạn mất tính linh hoạt: không chạy được privileged DaemonSet tùy ý, không SSH debug node, một số tooling bảo mật bên thứ ba yêu cầu node access sẽ không hoạt động.

Theo tài liệu hardening của GKE (Harden your cluster's security), nhiều khuyến nghị hardening mà bạn phải làm thủ công trên Standard đã được Autopilot áp đặt sẵn. Với một đội platform mới, nhỏ, hoặc không có security engineer chuyên trách, chọn Autopilot là một quyết định bảo mật đúng đắn — nó chuyển rủi ro misconfiguration từ bạn sang Google. Với đội cần kiểm soát sâu (custom CNI, security agent cấp node, GPU/đặc thù hạ tầng), Standard là bắt buộc nhưng đi kèm gánh nặng hardening tự thân.

Theo tài liệu Google Cloud, Autopilot áp dụng các cấu hình bảo mật được tăng cường và hạn chế các thao tác rủi ro ở cấp node mà người dùng không thể vô hiệu hóa, dịch chuyển phần lớn trách nhiệm vận hành node sang Google.

Defense-in-depth: bảy lớp và ý nghĩa từng lớp

Defense-in-depth không phải là khẩu hiệu — nó là một nguyên tắc kiến trúc cụ thể: không lớp phòng thủ nào được phép là single point of failure. Mỗi lớp giả định lớp ngoài có thể đã bị thủng, và vẫn phải bảo vệ được phần lõi.

Hãy đi qua bảy lớp theo hướng từ ngoài vào trong, và với mỗi lớp, đặt câu hỏi: "nếu lớp này thủng, điều gì xảy ra, và lớp nào chặn lại?"

Lớp 1 — Organization / Project. Đây là ranh giới ngoài cùng. IAM, Org Policy, VPC Service Controls, và resource hierarchy (Chương 1) quyết định ai chạm được tới cluster ở mức GCP. Nếu thủng (ví dụ một principal có roles/owner ở project bị lộ), kẻ tấn công có thể xóa cluster, đọc Secret qua API, tạo node mới. Lớp chặn tiếp theo: không có nhiều — đây là lý do bảo vệ IAM ở tầng project là tối quan trọng, và vì sao least-privilege ở tầng này không thể thỏa hiệp.

Lớp 2 — Cluster control plane. API server là cửa duy nhất vào cluster. Bảo vệ gồm: private cluster (control plane không có public IP, hoặc dùng DNS-based endpoint), authorized networks (chỉ IP tin cậy gọi được API), và tắt legacy auth (static certificate, basic auth, ABAC). Nếu thủng, kẻ tấn công nói chuyện được với API server. Lớp chặn tiếp: RBAC — kể cả gọi được API server, vẫn cần quyền RBAC để làm gì đó.

Lớp 3 — Identity & access (IAM ↔ RBAC). Đây là lớp authorize. Mô hình hai cổng (file 02) đảm bảo mỗi principal chỉ làm được đúng việc được phép. Nếu thủng (RBAC quá rộng, hoặc IAM container.admin cho mọi người), một identity bị lộ = quyền lớn trong cluster. Lớp chặn tiếp: Pod Security và Network Policy giới hạn cả khi đã có quyền tạo Pod.

Lớp 4 — Node. Node là một máy thật chia sẻ kernel với mọi Pod trên nó. Bảo vệ: Shielded nodes (chống boot-level tampering), Confidential nodes (mã hóa bộ nhớ), gVisor (cô lập syscall), COS (attack surface tối thiểu), và node service account tối thiểu. Nếu thủng (container escape), kẻ tấn công có quyền root trên node và mọi Pod trên đó. Lớp chặn tiếp: node SA tối thiểu giới hạn được kẻ tấn công làm gì với GCP API; network policy giới hạn lateral movement.

Lớp 5 — Pod / workload. Bảo vệ: Pod Security StandardssecurityContext đảm bảo Pod không chạy root, không privileged, không escalate được. Nếu thủng (RCE trong app), kẻ tấn công có quyền của process trong container. Lớp chặn tiếp: securityContext đúng làm việc escape khó hơn nhiều (non-root + readOnlyRootFilesystem + drop capabilities).

Lớp 6 — Network. Bảo vệ: Network Policy default-deny ngăn Pod bị chiếm nói chuyện với Pod/dịch vụ khác. Nếu thủng, lateral movement và data exfiltration. Lớp chặn tiếp: FQDN egress policy chặn cả việc gọi ra C2 server bên ngoài.

Lớp 7 — Supply chain. Bảo vệ: Binary Authorization và admission policy đảm bảo chỉ image tin cậy mới chạy. Đây là lớp phòng ngừa — nó ngăn image độc hại vào cluster ngay từ đầu, trước khi các lớp khác phải đối phó.

Quan sát then chốt: các lớp này bù trừ cho nhau. Một securityContext tốt (lớp 5) làm giảm xác suất container escape (lớp 4) thành công. Một node SA tối thiểu (lớp 4) làm giảm thiệt hại khi node bị chiếm. Một Network Policy (lớp 6) làm chậm lateral movement đủ để detection (file 10) kịp phản ứng. Đây là ý nghĩa thực của "depth": không lớp nào hoàn hảo, nhưng tổng hợp lại chúng biến một lỗ hổng đơn lẻ từ "thảm họa toàn cluster" thành "sự cố giới hạn được điều tra".

Threat model thực tế của GKE

Hardening mà không có threat model là bật tính năng ngẫu nhiên. Hãy đặt tên các mối đe dọa cụ thể để biết mỗi cơ chế chống lại cái gì.

1. Container escape → node compromise

Container chia sẻ kernel với host. Một lỗ hổng kernel hoặc một container chạy privileged cho phép process bên trong thoát ra namespace và chiếm node. Đây là mối đe dọa nghiêm trọng nhất với multi-tenant.

  • Chống bằng: securityContext chặt (non-root, drop ALL capabilities, no privilege escalation), Pod Security restricted, gVisor cho untrusted workload, Confidential/Shielded nodes, COS read-only rootfs.

2. Lateral movement (di chuyển ngang)

Sau khi chiếm một Pod, kẻ tấn công dò quét và pivot sang Pod/dịch vụ khác trong cluster. Network phẳng allow-all biến một Pod compromise thành recon toàn cluster.

  • Chống bằng: Network Policy default-deny, namespace isolation, RBAC tối thiểu để token bị lộ không làm được nhiều.

3. Credential theft → privilege escalation tới GCP

Mối đe dọa kinh điển của GKE: Pod bị chiếm gọi metadata server (169.254.169.254 / metadata.google.internal), lấy access token của node service account, rồi dùng quyền đó gọi GCP API. Nếu node SA là Compute Engine default SA với scope rộng, kẻ tấn công giờ có quyền lớn trên project.

  • Chống bằng: Workload Identity (file 04) để Pod không dùng node SA, metadata concealment để Pod không truy cập được metadata endpoint của node, và node SA tối thiểu để dù lộ cũng ít quyền.

4. Supply chain attack

Image chứa malware, dependency bị nhiễm, hoặc image từ registry không tin cậy. Kẻ tấn công không cần phá cluster — họ chỉ cần bạn deploy image của họ.

  • Chống bằng: Binary Authorization require-attestation (file 09), vulnerability scanning (Artifact Analysis), admission policy chặn registry lạ và tag latest.

5. Misconfiguration

Đây không phải là tấn công chủ động mà là điều kiện cho phép mọi tấn công khác: một RBAC binding quá rộng, một Pod public-facing chạy root, một Secret hardcode. Misconfiguration là nguyên nhân gốc thống kê của phần lớn sự cố thực tế.

  • Chống bằng: enforcement tự động (Pod Security Admission, Policy Controller), GKE Security Posture quét liên tục (file 10), và Autopilot áp default an toàn.

Production architecture patterns

Pattern: phân tầng trách nhiệm theo team

Ở quy mô tổ chức, ranh giới shared responsibility được phản ánh trong cơ cấu team: platform/security team sở hữu các lớp 1–4 (org policy, cluster hardening, node config, base Network Policy, Binary Authorization), còn application team sở hữu lớp 5 (workload securityContext, image của họ) trong khuôn khổ guardrail. Guardrail được enforce bằng Policy Controller và Pod Security Admission ở cấp namespace, để application team không thể vượt rào dù vô tình hay cố ý. Đây là mô hình "paved road": platform team tạo con đường an toàn, app team đi trên đó, và việc đi ra ngoài đường bị admission control chặn lại.

Pattern: Autopilot cho workload thường, Standard cho ngoại lệ

Nhiều tổ chức chạy Autopilot làm mặc định cho phần lớn microservice (tận dụng secure-by-default), và chỉ dùng Standard cluster riêng cho các workload cần node access đặc thù (GPU training, security agent cấp node, custom kernel module). Việc tách cluster theo nhu cầu hạ tầng cũng đồng thời tạo một security boundary tự nhiên: workload đặc quyền không chạy chung cluster với workload thường.

Pattern: cluster theo môi trường và độ nhạy cảm

Production, staging, và workload nhạy cảm (xử lý PII, payment) nằm trên cluster riêng, thậm chí project riêng, thay vì chỉ tách namespace. Lý do: namespace là một soft boundary trong Kubernetes — một lỗ hổng API server hoặc một RBAC sai có thể vượt namespace, nhưng vượt project đòi hỏi phá luôn lớp IAM. Với dữ liệu thực sự nhạy cảm, isolation cấp project + VPC Service Controls là ranh giới đáng tin hơn nhiều so với namespace.

Common mistakes / anti-patterns

1. "GKE là managed nên Google lo bảo mật." Đây là hiểu lầm nền tảng. Google lo control plane và hạ tầng; bạn lo workload, RBAC, network, image, và phần lớn cấu hình hardening. Hệ quả: cluster chạy với mọi default lỏng lẻo, workload root, network phẳng — và đội ngũ ngạc nhiên khi bị tấn công. Phòng tránh: in ra bảng shared responsibility, đánh dấu rõ từng dòng "ai sở hữu", và đối chiếu với cấu hình thực tế.

2. Hardening sai lớp. Tốn hàng tuần cấu hình mTLS giữa control plane components (thứ Google đã làm) trong khi workload vẫn chạy root và không có Network Policy. Hệ quả: cảm giác an toàn giả, rủi ro thật không giảm. Phòng tránh: ưu tiên theo threat model — bắt đầu từ những lớp bạn thực sự sở hữu và những mối đe dọa thực tế nhất (credential theft, misconfiguration).

3. Tắt auto-upgrade vì sợ downtime. Để tránh node bị recreate, đội ngũ tắt node auto-upgrade — và vô tình nhận lại trách nhiệm patch OS mà không có quy trình làm việc đó. Hệ quả: node chạy kernel có CVE đã biết hàng tháng. Phòng tránh: dùng release channel + surge upgrade + maintenance window + PodDisruptionBudget để upgrade an toàn thay vì tắt nó (đối chiếu Chương 6).

4. Coi namespace là security boundary cứng. Đặt tenant A và tenant B vào hai namespace cùng cluster và gọi đó là "isolation". Namespace cô lập tên và RBAC, nhưng chia sẻ node, kernel, control plane. Hệ quả: container escape của tenant A chạm tới tenant B. Phòng tránh: với multi-tenant thực sự nhạy cảm, dùng node pool riêng/cluster riêng + gVisor, không chỉ namespace.

5. Bật tính năng bảo mật nhưng không quan sát. Bật Network Policy, Binary Authorization, Pod Security nhưng không bật audit log hay Security Posture. Hệ quả: khi có sự cố, không có dấu vết để điều tra; khi có misconfiguration mới, không ai biết. Phòng tránh: detection và enforcement đi đôi (file 10) — phòng thủ mà không quan sát là phòng thủ mù.

GCP-native implementation guidance

Kiểm tra nhanh ranh giới trách nhiệm thực tế của một cluster: các cấu hình bảo mật cốt lõi đang ở trạng thái nào.

bash
# Kiểm tra các thuộc tính security của cluster
gcloud container clusters describe CLUSTER_NAME \
  --region REGION \
  --format="yaml(autopilot.enabled,
    shieldedNodes.enabled,
    workloadIdentityConfig.workloadPool,
    networkPolicy.enabled,
    binaryAuthorization.evaluationMode,
    masterAuth.clientCertificateConfig,
    privateClusterConfig.enablePrivateNodes,
    releaseChannel.channel)"

Các tín hiệu cần thấy trên một cluster Standard đã hardening: shieldedNodes.enabled: true, workloadIdentityConfig.workloadPool có giá trị (PROJECT_ID.svc.id.goog), binaryAuthorization.evaluationMode khác DISABLED, privateClusterConfig.enablePrivateNodes: true, releaseChannel.channel đã đăng ký (REGULAR/STABLE). Nếu masterAuth.clientCertificateConfig còn bật client certificate (legacy auth), đó là một cờ đỏ cần tắt.

Trên Autopilot, nhiều giá trị này đã được Google đặt sẵn và không thể đảo ngược — đó chính là ý nghĩa "ranh giới dịch chuyển về phía Google".

Operational implications

Mô hình shared responsibility có một hệ quả vận hành ít người để ý: trách nhiệm bảo mật không tĩnh — nó thay đổi mỗi khi bạn thay đổi cấu hình. Bật custom node image → bạn nhận lại trách nhiệm patch OS. Tắt Workload Identity và dùng SA key → bạn nhận lại trách nhiệm rotate credential. Cấp container.admin cho team → bạn vô hiệu hóa RBAC như một lớp phòng thủ. Mỗi quyết định cấu hình là một quyết định dịch chuyển ranh giới trách nhiệm, và đội ngũ trưởng thành về bảo mật là đội ngũ ý thức được điều đó tại thời điểm ra quyết định, chứ không phải sau sự cố.

Điều này cũng định hình cách review: mọi thay đổi cấu hình cluster nên đi kèm câu hỏi "thay đổi này dịch chuyển ranh giới trách nhiệm về phía nào, và chúng ta có đủ năng lực gánh phần vừa nhận không?". Một đội không có quy trình patch OS thì không nên tắt auto-upgrade; một đội không có hệ thống quản lý secret thì không nên rời bỏ Workload Identity.

References