Chương 13: GKE Workload Identity & Service Accounts — Modern Authentication
Vì sao chương này là xương sống của mọi workload gọi Google API
Gần như mọi workload production trên GKE đều phải gọi một Google API nào đó: đọc object từ Cloud Storage, publish message lên Pub/Sub, query BigQuery, đọc credential từ Secret Manager, ghi metric/log lên Cloud Operations. Câu hỏi tưởng chừng đơn giản — "workload chứng minh nó là ai với Google bằng cách nào" — lại là một trong những quyết định kiến trúc có hệ quả bảo mật sâu rộng nhất của toàn bộ cluster. Trả lời sai, bạn để lại một long-lived service account key nằm trong etcd, image Docker, và Git history — chính xác là vector tấn công mà mọi báo cáo sự cố credential theft của Google Cloud đều trỏ tới. Trả lời đúng, bạn có một hệ thống xác thực không-key, token short-lived tự refresh, và mọi quyền truy cập đều gắn với một danh tính có thể audit ở mức từng workload.
Chương 12 đã giới thiệu Workload Identity ở góc bảo mật — tại sao nó tồn tại và vector tấn công nào nó cắt đứt. Chương 13 này đi tới tận đáy cơ chế: chính xác token nào được sinh ra, ai ký nó, ai verify, request đi qua những thành phần nào, và điều gì xảy ra ở từng millisecond của token exchange path. Đây không phải kiến thức "biết để cho vui" — nó là kiến thức bạn bắt buộc phải có khi một Pod báo 403 Permission Denied lúc 3 giờ sáng và bạn cần biết: lỗi nằm ở projected token, ở metadata server, ở STS exchange, hay ở IAM binding. Mỗi tầng có một cơ chế lỗi riêng, một điểm điều tra riêng, và một cách vá riêng.
Có ba mental model sai phổ biến mà chương này phá bỏ:
"Workload Identity là một loại key đặc biệt được Google quản lý." Sai. Không có key nào cả. Cái workload có là một OIDC JWT short-lived do chính cluster (đóng vai trò OIDC provider) ký, và một federated access token đổi từ JWT đó. Hiểu nhầm điều này dẫn tới việc đi tìm "key Workload Identity ở đâu" — một câu hỏi vô nghĩa.
"Metadata server chỉ là một endpoint, gọi vào là có token." Sai ở mức nguy hiểm.
gke-metadata-serverlà một DaemonSet chạy trên từng node, chặn (intercept) mọi request tới169.254.169.254/metadata.google.internal, và thực hiện một chuỗi token exchange phức tạp đằng sau. Hiểu nó là "magic endpoint" khiến bạn không debug được khi DaemonSet bị OOM-killed hoặc khi Pod dùnghostNetwork: truebypass mất nó."Workload Identity Federation cho GKE và Workload Identity Federation cho external IdP là hai thứ khác nhau." Sai về bản chất. Chúng là cùng một cơ chế federation xây trên cùng STS endpoint và cùng OAuth 2.0 token exchange (RFC 8693). GKE chỉ là một trường hợp đặc biệt nơi external IdP chính là OIDC provider của cluster. Hiểu thống nhất điều này cho phép bạn dùng cùng một mental model cho cả Pod GKE lẫn GitHub Actions runner lẫn workload chạy trên AWS.
Điểm mấu chốt xuyên suốt chương: xác thực hiện đại trên GCP là một bài toán trao đổi token dựa trên niềm tin OIDC, không phải bài toán quản lý secret. Toàn bộ chương xây dựng một mental model duy nhất — một danh tính bên ngoài (KSA, GitHub repo, AWS role) được một IdP xác nhận bằng JWT có chữ ký; Google STS verify chữ ký đó dựa trên cấu hình tin cậy (pool + provider); và đổi nó lấy một credential Google short-lived gắn với quyền IAM tối thiểu — rồi áp dụng mental model đó cho mọi tình huống.
Điều kiện tiên quyết
- Chương 12 (GKE Security), đặc biệt file 04 — Workload Identity Federation: chương này là phần deep-dive được Chương 12 chỉ định nối tiếp. Bạn cần đã nắm: vì sao long-lived key nguy hiểm, khái niệm pool
PROJECT_ID.svc.id.goog, và bức tranh tổng thể của token exchange ba bước. Chương 13 không lặp lại lập luận bảo mật đó — nó giải phẫu cơ chế. - IAM service accounts và IAM policy binding: principal, role, member,
roles/iam.workloadIdentityUser,roles/iam.serviceAccountTokenCreator. Toàn bộ tầng authorization của Workload Identity là IAM thuần túy. - OIDC basics: ID token, JWT (header/payload/signature),
iss/sub/aud/expclaims, JWKS endpoint, RS256 signing. Workload Identity là OIDC ở mọi tầng; không nắm OIDC thì cơ chế sẽ trông như phép thuật. - Kubernetes ServiceAccount và TokenRequest API: projected volume, bound token, BoundServiceAccountTokenVolume. File 02 đào sâu, nhưng nền tảng giúp ích.
- Application Default Credentials (ADC): thứ tự ADC dò credential trong client library Google. File 03 và 06 giả định bạn hiểu ADC là gì.
Mức độ sâu
5/5 — Chương đi tới mức: cấu trúc payload của projected ServiceAccount token (iss = OIDC issuer https://container.googleapis.com/v1/projects/.../clusters/..., aud = sts.googleapis.com, exp ≤ 1 giờ, kubernetes.io claims); JWKS endpoint /.well-known/openid-configuration và cơ chế Google STS verify chữ ký JWT mà không cần gọi về cluster; kiến trúc DaemonSet của gke-metadata-server, giới hạn 500 concurrent connection/node, ngưỡng 3.000 ServiceAccount/cluster, quota 6.000 request/phút của STS Exchange Token API; bốn dạng principal/principalSet identifier (subject by name, by UID, namespace-level, cluster-level) và ngữ nghĩa "identity sameness" giữa các cluster; CEL attribute mapping (google.subject=assertion.sub) và attribute condition chống confused-deputy; token exchange flow RFC 8693 qua sts.googleapis.com cho external IdP với từng loại (AWS SigV4, Azure/Entra ID, GitHub Actions OIDC token.actions.githubusercontent.com, Kubernetes, OIDC generic); và quy trình debug từ curl metadata endpoint bên trong Pod đến verify IAM binding. Mọi tuyên bố kỹ thuật đối chiếu trực tiếp tài liệu Google Cloud.
Cấu trúc chapter
1. Workload Identity Architecture — Cluster Như Một OIDC Provider
Mô hình niềm tin nền tảng: cluster phát hành danh tính, IAM tin tưởng danh tính đó.
- GKE OIDC provider: mỗi cluster là một OIDC issuer với endpoint riêng và JWKS riêng
- Workload Identity Pool
PROJECT_ID.svc.id.goog: cây cầu để IAM hiểu danh tính Kubernetes, tồn tại ngay cả khi xóa hết cluster - Bốn dạng định danh:
principal://...subject/ns/NS/sa/KSA(theo tên),.../kubernetes.serviceaccount.uid/UID(theo UID),principalSet://...namespace/NS(cấp namespace),.../kubernetes.cluster/...(cấp cluster) - Identity sameness: vì sao cùng tên KSA ở hai cluster cùng project = cùng danh tính IAM, và hệ quả isolation
- Fleet Workload Identity pool vs project pool; mối quan hệ federation tổng quát
2. ServiceAccount Token & Projection Mechanics — Danh Tính Được Ký
Token gốc của toàn bộ chuỗi: ai sinh, ai ký, hết hạn khi nào.
- TokenRequest API và bound token: khác biệt với legacy secret-based token (không hết hạn, không bound)
- Projected volume: kubelet mount token qua
serviceAccountTokenprojection, vớiaudience,expirationSeconds,path - Cấu trúc JWT:
iss(OIDC issuer của cluster),sub,aud(sts.googleapis.com),exp, các claimkubernetes.io/namespace,.../serviceaccount/name,.../pod - OIDC issuer endpoint
https://container.googleapis.com/v1/projects/.../clusters/...và/.well-known/openid-configuration; JWKS public key để STS verify offline - Vòng đời refresh: kubelet tự rotate token trước khi hết hạn; vì sao không bao giờ có token "vĩnh viễn"
3. Metadata Server & Token Exchange Path — Trái Tim Của Cơ Chế
Giải phẫu từng bước con đường từ "app gọi ADC" đến "có access token Google".
gke-metadata-serverDaemonSet: một Pod/node, chặn request tới169.254.169.254:80/metadata.google.internal- Trust boundary cấp node: HTTP interception, vì sao
hostNetwork: truebypass và rủi ro của nó - Token exchange path năm bước chi tiết: app gọi ADC → metadata server chặn → lấy projected KSA JWT từ API server → đổi qua Security Token Service (
sts.googleapis.com) lấy federated token → trả access token short-lived cho app - Caching và refresh: token lifetime 1 giờ (3.600s), client library refresh khi còn 3 phút 45 giây; quota STS 6.000 req/phút
- Scale bottleneck: 500 concurrent connection/node, 3.000 ServiceAccount/cluster làm OOM metadata server; network policy egress
169.254.169.254/32:80(Dataplane V2) hoặc169.254.169.252/32:988
4. IAM Binding Models — Cấp Quyền Cho Danh Tính Workload
Hai mô hình authorization và khi nào dùng cái nào.
- Mô hình trực tiếp (khuyến nghị): IAM binding role GCP thẳng cho
principal://...sa/KSA, không cần GSA trung gian - Mô hình impersonation (legacy/phổ biến): annotate KSA
iam.gke.io/gcp-service-account, GSA cấproles/iam.workloadIdentityUserchoserviceAccount:PROJECT_ID.svc.id.goog[NS/KSA] principalSetcấp namespace/cluster: cấp quyền cho cả một namespace hoặc cả một cluster cùng lúc — và rủi ro của nó- Cross-project Workload Identity: KSA ở cluster project A impersonate GSA ở project B; annotation
credential-quota-project - Autopilot: Workload Identity luôn bật, không thể tắt; hệ quả thiết kế
- Annotation
iam.gke.io/return-principal-id-as-emailvà format danh tính trả về
5. Workload Identity Federation cho External IdP — Liên Bang Danh Tính Đa Đám Mây
Cùng cơ chế federation mở rộng ra ngoài Google Cloud.
- Workload Identity Pool + Provider cho external IdP: khác biệt với pool GKE cố định
- Token exchange RFC 8693 qua
sts.googleapis.com: external JWT → federated token - IdP được hỗ trợ: AWS (SigV4 caller identity), Microsoft Entra ID/Azure, GitHub Actions (
token.actions.githubusercontent.com), GitLab, Kubernetes, Okta/AD FS, OIDC/SAML generic - Attribute mapping (CEL):
google.subject=assertion.sub,attribute.NAME=...,google.groups; tối đa 50 custom attribute - Attribute condition: chống confused deputy — ví dụ
assertion.repository_owner=='ORG' && assertion.ref=='refs/heads/main' - Direct resource access vs service account impersonation;
principalSet://...attribute.NAME/VALUE
6. Truy Cập Dịch Vụ & Application Default Credentials Patterns
Từ cơ chế đến code: workload thực sự gọi API như thế nào.
- ADC behavior trên GKE: thứ tự dò credential, vì sao client library "tự hoạt động không cần sửa code"
- Pattern truy cập Secret Manager qua Workload Identity (thay cho mount SA key)
- Pattern Cloud Storage / Pub/Sub / BigQuery: KSA-per-workload với quyền tối thiểu trên đúng resource
- Credential helper trong container image: Artifact Registry pull qua Workload Identity,
docker-credential-gcr - Access external service (không phải Google API) bằng token federation ngược; impersonation chain
- ADC trong môi trường local/dev vs trong cluster: vì sao test local cần
gcloud auth application-default login
7. Debugging Workload Identity — Khi Token Exchange Thất Bại
Quy trình điều tra có hệ thống cho mọi failure mode.
- Debug từ trong Pod:
kubectl exec→curl -H "Metadata-Flavor: Google"các endpoint/computeMetadata/v1/instance/service-accounts/default/emailvà/token - Verify GKE_METADATA mode trên mọi node pool; phát hiện pool còn ở
GCE_METADATA - Verify IAM binding:
gcloud ... get-iam-policy, kiểm tra principal string đúng namespace/tên KSA - Token validity check: decode JWT, kiểm
aud,exp,sub; phân biệt lỗi authentication vs authorization - Cây quyết định lỗi:
unable to detect environment,403 Permission Denied,404từ metadata, token rỗng, DNS/network policy chặn metadata - Lỗi scale: metadata server OOM, vượt 500 concurrent connection, vượt quota STS
Bản đồ tinh thần: một danh tính, bốn lần biến đổi
Trước khi vào từng file, hãy ghim chuỗi biến đổi danh tính này — nó là khung tham chiếu cho mọi quyết định và mọi lần debug trong chương. Một workload đi từ "không có danh tính Google nào" đến "gọi được Google API" qua đúng bốn lần biến đổi:
| Bước | Danh tính ở dạng | Ai tạo/ký | Ai verify | File |
|---|---|---|---|---|
| 1. KSA | Một ServiceAccount Kubernetes (ns/sa) | Người vận hành tạo trong cluster | — | 1, 2 |
| 2. Projected JWT | OIDC token short-lived, ký bởi cluster | kubelet (qua TokenRequest API) | Google STS (qua JWKS) | 2 |
| 3. Federated token | Short-lived access token của Google | Security Token Service | Google API backend | 3 |
| 4. (tùy chọn) GSA token | Access token của IAM service account | IAM Credentials API (impersonation) | Google API backend | 4 |
Ba quan sát quyết định cách đọc cả chương:
Không bước nào trong chuỗi này là một long-lived secret. KSA là một object Kubernetes, không phải credential. JWT, federated token, GSA token — tất cả đều short-lived và tự refresh. Đây là toàn bộ lý do Workload Identity tồn tại: chuyển từ "quản lý vòng đời secret" sang "quản lý cấu hình niềm tin".
Bước 4 là tùy chọn — và đó là điểm phân biệt hai mô hình IAM binding. Mô hình trực tiếp (file 4) dừng ở bước 3: federated token gọi thẳng API. Mô hình impersonation thêm bước 4: federated token dùng để mạo danh một GSA. Biết bạn đang ở mô hình nào quyết định bạn debug IAM binding ở đâu.
External IdP federation (file 5) chỉ thay bước 1–2 bằng IdP khác. Thay vì KSA + cluster-signed JWT, bạn có GitHub repo +
token.actions.githubusercontent.com-signed JWT, hoặc AWS role + SigV4. Bước 3–4 giống hệt. Đây là lý do nắm vững chuỗi này cho GKE giúp bạn hiểu ngay mọi kịch bản federation khác.
Khung quyết định Workload Identity (tóm tắt)
Ma trận quyết định cốt lõi của chương. Mỗi dòng là một câu hỏi thiết kế thật, file tương ứng đào sâu.
| Tình huống / Nhu cầu | Lựa chọn đúng | Vì sao | File |
|---|---|---|---|
| Workload GKE mới cần gọi Google API | Workload Identity, IAM binding trực tiếp cho principal://...sa/KSA | Ít thành phần nhất, không key, granularity per-KSA | 1, 4 |
| Tổ chức đã chuẩn hóa quyền theo IAM service account | Mô hình impersonation (annotation + workloadIdentityUser) | Tận dụng GSA sẵn có, quản lý quyền tập trung theo GSA | 4 |
| Workload ở project A cần resource ở project B | Cross-project: KSA project A impersonate GSA project B | Pool và GSA có thể ở project khác nhau | 4 |
| CI/CD runner (GitHub Actions) deploy lên GCP | Workload Identity Federation external + attribute condition theo repo | Loại bỏ SA key khỏi CI secret — nơi key lộ nhiều nhất | 5 |
| Workload đa đám mây trên AWS/Azure gọi Google API | Federation từ AWS role / Entra ID qua pool+provider | Không SA key, dùng danh tính cloud sẵn có | 5 |
| Cần cấp quyền cho cả một namespace | principalSet://...namespace/NS | Tiện, nhưng đánh đổi granularity — cân nhắc kỹ | 1, 4 |
| Workload đọc secret cấu hình lúc khởi động | Secret Manager qua ADC + secretmanager.secretAccessor trên đúng secret | Không secret tĩnh trong image/etcd | 6 |
| Pod báo 403 khi gọi API | Debug theo cây: GKE_METADATA → IAM binding → token claims | Mỗi tầng lỗi riêng, điểm điều tra riêng | 7 |
| Chạy Autopilot | Không cần bật gì — Workload Identity luôn on | Autopilot enforce sẵn, không có metadata node để lộ | 4 |
Năm sai lầm xuyên suốt thường gặp ở cấp chương
Đi tìm "key Workload Identity". Tư duy theo mô hình secret cũ, hỏi "key nằm ở đâu để backup/rotate". Hệ quả: hiểu sai bản chất, không debug được khi token exchange lỗi. Đúng: không có key; có một chuỗi token short-lived tự refresh, cái cần "quản lý" là IAM binding và cấu hình pool (file 1–4).
Bật Workload Identity ở cluster nhưng quên một node pool. Cluster có
--workload-poolnhưng một pool cũ vẫnGCE_METADATA. Hệ quả: Pod trên pool đó lấy được token node service account qua metadata Compute Engine — đúng vector mà Workload Identity định cắt. Đúng: mọi pool phảiGKE_METADATA; verify bằnggcloud container node-pools list(file 3, 7).Dùng
hostNetwork: truemà không nhận ra nó bypass metadata server. Pod hostNetwork truy cập thẳng Compute Engine metadata server, không quagke-metadata-server, nên không có Workload Identity. Hệ quả: hoặc workload lỗi xác thực, hoặc tệ hơn, lấy được token node SA. Đúng: tránh hostNetwork cho workload cần WI, hoặc xử lý xác thực riêng (file 3).Cấp
principalSetcấp namespace/cluster cho tiện rồi quên thu hẹp. Bind role GCP cho cảprincipalSet://...namespace/NSthay vì từng KSA. Hệ quả: mọi KSA trong namespace — kể cảdefaultvà các workload tương lai — đều có quyền đó; "identity sameness" còn khiến nó lan sang cluster khác cùng project. Đúng: binding per-KSA principal, dùng IAM condition giới hạn cluster khi cần (file 1, 4).Attribute condition lỏng lẻo khi federate external IdP. Tạo provider GitHub Actions nhưng không giới hạn
assertion.repository_owner/assertion.ref. Hệ quả: confused deputy — bất kỳ repo GitHub nào (kể cả của kẻ tấn công) cũng đổi được token lấy quyền GCP của bạn. Đúng: luôn có attribute condition khóa chặt org/repo/branch (file 5).
Cross-reference với Google Cloud Architecture Framework
- Security pillar: chương là hiện thân của nguyên tắc zero long-lived credential và least-privilege identity trong Well-Architected Framework — danh tính short-lived, gắn workload, audit được (Security pillar).
- Operational excellence: chuyển từ vòng đời key (rotate, phát hiện rò rỉ, thu hồi) sang cấu hình IAM binding khai báo — giảm gánh nặng vận hành và bề mặt lỗi con người (Operational excellence pillar).
- Reliability: token exchange path có các bottleneck thật (500 connection/node, quota STS, metadata server OOM) — hiểu chúng là điều kiện để vận hành xác thực ở quy mô mà không gây outage (Reliability pillar).
References chung của chapter
- Workload Identity Federation for GKE
- Authenticate to Google Cloud APIs from GKE workloads
- Workload Identity Federation (external IdP)
- Configure Workload Identity Federation with deployment pipelines
- Best practices for using service accounts
- Protecting cluster metadata
- Use external identity providers to authenticate to GKE (OIDC)
- Service Account Tokens (Kubernetes)
Bảng thuật ngữ then chốt của chương
| Thuật ngữ | Ý nghĩa ngắn gọn |
|---|---|
| Workload Identity Pool | Không gian tên PROJECT_ID.svc.id.goog để IAM hiểu danh tính Kubernetes (file 1) |
| OIDC issuer | Cluster đóng vai trò OIDC provider, endpoint container.googleapis.com/v1/projects/.../clusters/... (file 1, 2) |
| JWKS | Bộ public key cluster công bố để STS verify JWT offline (file 2) |
| Projected token | KSA JWT short-lived kubelet mount qua projected volume, aud=sts.googleapis.com (file 2) |
| TokenRequest API | API Kubernetes cấp bound token có audience/expiry (file 2) |
| gke-metadata-server | DaemonSet chặn request metadata, thực hiện token exchange (file 3) |
| Security Token Service (STS) | sts.googleapis.com, đổi external JWT lấy federated token (RFC 8693) (file 3, 5) |
| Federated access token | Access token Google short-lived đổi từ JWT, lifetime 1 giờ (file 3) |
| principal:// | Định danh IAM cho một danh tính đơn (một KSA cụ thể) (file 1, 4) |
| principalSet:// | Định danh IAM cho một tập danh tính (namespace/cluster/attribute) (file 1, 4, 5) |
| workloadIdentityUser | Role cho phép KSA impersonate một GSA (file 4) |
| Identity sameness | Cùng tên KSA ở các cluster cùng project = cùng danh tính IAM (file 1) |
| Attribute mapping | CEL ánh xạ claim của external IdP sang attribute Google (file 5) |
| Attribute condition | CEL lọc danh tính được phép, chống confused deputy (file 5) |
| ADC | Application Default Credentials — cách client library tự dò credential (file 6) |
| GKE_METADATA | Chế độ node pool bật metadata server Workload Identity (file 3, 7) |
Kết luận của chapter
Workload Identity là minh chứng rõ nhất cho một dịch chuyển tư duy trong bảo mật đám mây: từ "giữ bí mật một secret" sang "thiết lập niềm tin giữa các danh tính". Mọi cơ chế trong chương — projected token, metadata server, STS exchange, IAM binding, attribute condition — đều phục vụ một mục tiêu duy nhất: cho phép một workload chứng minh nó là ai mà không bao giờ cầm một credential dài hạn nào trong tay. Khi bạn nắm được chuỗi bốn lần biến đổi danh tính và biết mỗi thành phần ký gì, verify gì, hết hạn khi nào, thì Workload Identity thôi là phép thuật và trở thành một hệ thống bạn có thể thiết kế, vận hành, và debug một cách kỷ luật.
Cách dùng chương hiệu quả nhất là biến mỗi file thành một năng lực vận hành cụ thể: hiểu mô hình niềm tin OIDC của cluster (file 1, 2), giải phẫu được token exchange path tới từng bước (file 3), chọn đúng mô hình IAM binding cho từng tình huống tổ chức (file 4), mở rộng cùng mental model ra CI/CD và đa đám mây (file 5), viết code và cấu hình truy cập dịch vụ không-key (file 6), và quan trọng nhất — debug được khi token exchange thất bại ở 3 giờ sáng (file 7). Khi đó xác thực workload chuyển từ "một thứ ai đó đã cấu hình và không ai dám động vào" thành một hệ thống minh bạch, suy luận được, đúng tinh thần zero-trust mà mọi cluster production ở quy mô lớn buộc phải theo.