Định Danh Workload Cho Droplets Dựa Trên Ứng Dụng OAuth

Bài viết này là phần đầu tiên trong chuỗi ba phần về liên kết định danh workload:

  • Phần 1: Kiến trúc (bài viết này)
  • Phần 2: Triển khai và Cấu hình
  • Phần 3: Sử dụng từ Droplets và GitHub Actions

Phần này sẽ đề cập đến khái niệm liên kết định danh workload và cách thức triển khai bằng cách tận dụng API OAuth của DigitalOcean. Trong các phần tiếp theo của chuỗi bài, chúng ta sẽ triển khai một Bằng chứng Khái niệm (PoC) mã nguồn mở, cấu hình các vai trò và chính sách để kiểm soát truy cập định danh workload, khởi chạy một Droplet, viết một quy trình GitHub Actions, và truy cập cơ sở dữ liệu cũng như khóa của Spaces từ các tài nguyên này bằng cách sử dụng token định danh workload tương ứng.

Khái niệm Liên kết Định danh Workload (Workload Identity Federation)

Định danh workload được sử dụng nhằm giảm thiểu số lượng thông tin bí mật (secrets) liên quan đến việc triển khai và quản trị các hệ thống phần mềm. Thay vì xác thực dựa trên thứ mà workload biết (ví dụ: mật khẩu hoặc API token), cơ chế này sẽ xác thực dựa trên bản chất của workload đó.

Cốt lõi của liên kết định danh workload chính là mật mã hóa bất đối xứng. Bằng cách tận dụng các cặp khóa công khai/riêng tư (public/private key pairs), hệ thống có thể cấp phát token cho các workload (ví dụ như Droplets). Các token này sau đó được sử dụng để xác thực và ủy quyền khi truy cập vào các API do máy chủ tài nguyên cung cấp. Token định danh workload sẽ được quy đổi lấy các token truy cập đặc thù của miền, hoặc dùng để cấp quyền truy cập tài nguyên trực tiếp.

Loạt bài này trình bày cách chúng ta có thể sử dụng API OAuth của DigitalOcean và các phạm vi phân quyền chi tiết để triển khai và tận dụng cơ chế liên kết định danh workload thông qua token theo giao thức OpenID Connect (OIDC). Chúng ta sẽ kích hoạt khả năng truy cập không cần bí mật vào các cơ sở dữ liệu và Spaces bucket do DigitalOcean lưu trữ, thực hiện từ Droplets và các quy trình của GitHub Actions. Điều này giúp loại bỏ nhu cầu cấp phát các thông tin xác thực tĩnh, tồn tại lâu dài cho cơ sở dữ liệu và Spaces bucket trong các môi trường đó.

Workload identity RBAC

Các thuộc tính bảo mật

Việc xác thực dựa trên “bản chất của workload” (what the workload is) đòi hỏi hạ tầng chịu trách nhiệm điều phối (orchestrating) workload phải có khả năng đưa ra các thông tin xác nhận (claims) có thể kiểm chứng được (verifiable) về thuộc tính của workload đó. Để làm được điều này, hạ tầng vận hành workload sẽ cho phép phát hành các token đặc thù (dành riêng) cho workload, trong đó chứa các thông tin xác nhận này.

Tính bảo mật của định danh workload phụ thuộc chủ yếu vào việc xác thực (validation) các token này một cách chính xác theo đặc tả giao thức OIDC, các thông tin xác nhận (claims) được định nghĩa trong mỗi token, và cấu hình RBAC (Kiểm soát truy cập dựa trên vai trò) dùng để xác thực token dựa trên các thông tin xác nhận đó.

Token OIDC chính là các Token JWT (JSON Web Tokens). Các token này được ký bằng mật mã (cryptographically signed) sử dụng một khóa riêng tư (private key). Khóa công khai (public key) tương ứng với khóa riêng tư đó sẽ được cung cấp thông qua định dạng JSON Web Key (JWK) tại một “URI well-known” (URI được biết đến rộng rãi) theo chuẩn RFC 8615.

URI của khóa công khai này sau đó được tham chiếu bởi một tệp Cấu hình OpenID (OpenID Configuration) định dạng JSON, vốn được lưu trữ tại một URI “well-known” khác.

/.well-known/openid-configuration

/.well-known/jwks

Chính các URI well-known này là yếu tố then chốt giúp hiện thực hóa cơ chế liên kết định danh workload.

Liên kết trong bối cảnh này có nghĩa là các dịch vụ riêng biệt có khả năng tương tác với nhau. Mục đích là để các dịch vụ (không phải bên đã phát hành token) có thể xác nhận định danh của một workload.

Ở phần sau của bài viết, chúng ta sẽ tận dụng khả năng tương tác này để xác minh tính hợp lệ của các token OIDC được cấp cho các quy trình do GitHub Actions thực thi. Trong trường hợp này, chính quy trình được xem là workload.

Các URI well-known liên quan của GitHub Actions như sau:

Giải pháp Bằng chứng Khái niệm (PoC) mà chúng ta sắp triển khai cũng sẽ sử dụng các đường dẫn được biết đến rộng rãi tương tự, điểm khác biệt duy nhất là tên miền của bên phát hành.

Các token JWT được phát hành kèm theo một tập hợp các thông tin xác nhận. Khi một token được cấp phát với một claim cụ thể, điều đó có nghĩa là bên phát hành đang khẳng định rằng token đó đại diện cho một giá trị nhất định. Bằng cách dùng khóa riêng tư của mình để ký token, bên phát hành đang đưa ra sự chứng thực về tính hợp lệ của thông tin xác nhận đó.

Do đó, nếu chúng ta tin tưởng một bên phát hành cụ thể và token OIDC đó vượt qua được bước xác minh chữ ký mật mã, chúng ta biết rằng mình có thể tin tưởng các thông tin xác nhận bên trong token đó.

Tập hợp các thông tin xác nhận mà chúng ta quan tâm trong PoC này (và cũng là các claims mà dịch vụ của chúng ta sẽ dùng để phát hành token) bao gồm:

Bên phát hành (issuer) được chứa trong claim ”iss”. Chúng ta sẽ nối thêm ”/.well-known/openid-configuration” vào (địa chỉ của issuer) để tìm tệp JSON Cấu hình OpenID. Sau khi giải mã tệp này, chúng ta sẽ tìm thấy các Khóa JSON Web Công khai (Public JWKs) cần thiết để thực hiện xác minh chữ ký mật mã (cryptographic signature verification) của token.

Đối với tính bảo mật của liên kết định danh workload, hai thông tin xác nhận (claims) có tầm quan trọng then chốt khác là audience và subject. Claim “audience” được máy chủ tài nguyên sử dụng để xác định xem token có hợp lệ cho các tài nguyên của mình hay không. Trong trường hợp của chúng ta, “audience” chính là API mà chúng ta đang xác thực (cụ thể là “DigitalOcean”).

Claim subject sẽ thay đổi tùy thuộc vào môi trường workload mà chúng ta thực hiện xác thực. “Subject” định danh chính bản thân workload—trả lời cho câu hỏi “Nó là gì?”.

Trong PoC, việc thiết lập “subject” thông qua các thẻ của Droplet là một thành phần then chốt trong luồng tin cậy (trust flow). Việc tạo một Droplet với các thẻ nhất định, kết hợp với các vai trò RBAC (Kiểm soát truy cập dựa trên vai trò) của chúng ta, sẽ xác định quyền truy cập của Droplet đó. Chúng ta đang cho phép bất kỳ thành viên/vai trò nào có quyền tạo Droplet cũng đồng thời có quyền thiết lập “subject” cho nó. Do đó, đây là một yếu tố bắt buộc phải được xem xét kỹ lưỡng khi định nghĩa và gán các vai trò RBAC. Khi chúng ta truy cập tài nguyên từ GitHub Actions, chúng ta biết câu trả lời cho câu hỏi “Nó là gì?” dựa trên cách mà bộ điều phối của GitHub Actions định dạng “subject”: ”org/repo/.github/workflows/name.yml”.

Kiến trúc Giải pháp Định danh Workload

Mục tiêu của PoC này là cho phép người dùng dễ dàng cấp quyền cho Droplet truy cập vào các tài nguyên của nhóm như Khóa của Spaces và Cơ sở dữ liệu. Việc này giúp loại bỏ nhu cầu cấp phát bí mật ngoài luồng hoặc nhúng nóng các giá trị nhạy cảm vào cloud-init. Trong ví dụ của chúng ta, chúng ta sẽ sử dụng các workload của GitHub Actions để triển khai các Droplet của DigitalOcean. Các Droplet này được cấu hình để truy cập vào Managed Database và Spaces bucket mà không cần nhúng nóng bất kỳ token bí mật nào.

PoC của chúng ta bao gồm các khía cạnh sau:

  • Một Ứng dụng Client OAuth tuân theo Luồng Ứng dụng Web OAuth của DigitalOcean.
  • Một cơ chế đánh giá dựa trên chính sách để xác định quyền kiểm soát truy cập (hỗ trợ tải lên policy).
  • Cấp phát và phát hành các token định danh workload.
  • Các URI .well-known phục vụ việc xác thực token OIDC.
  • Các bộ xử lý để can thiệp và bọc các route (API) do DigitalOcean API cung cấp:
  • Tạo một Droplet Mới.
  • Truy xuất Cụm Cơ sở dữ liệu Hiện có.
  • Tạo Khóa Truy cập Spaces Mới.

Để liên kết các khía cạnh này lại với nhau và cho phép cả người dùng cuối lẫn các dịch vụ (như Droplets và GitHub Actions) truy cập chúng, PoC này tận dụng Caddy như một reverse proxy cho API của DigitalOcean. Sau đó, chúng ta có thể viết một tệp Caddyfile để cấu hình Caddy thực hiện các việc sau:

  • Hiển thị route OAuth cho người dùng.
  • Cho phép truyền qua các API của DigitalOcean đến người dùng và các workload.
  • Kích hoạt các trình bọc của chúng ta xung quanh các route (API) mà chúng ta sẽ sửa đổi để bật tính năng định danh workload.

Solution High Level Flow

Caddy cho phép chúng ta dễ dàng định nghĩa các route mà chúng ta muốn (tự) xử lý và các route chúng ta muốn bọc lại. Mã nguồn xử lý xác thực đặc thù của ứng dụng—chính là tệp callback.py—sẽ chuyển hướng người dùng khi họ truy cập vào đường dẫn gốc của máy chủ. Tệp này sẽ đưa họ đến trang lựa chọn nhóm và phê duyệt OAuth của DigitalOcean.

Sau khi phê duyệt, callback.py sẽ đảm nhiệm việc lưu trữ an toàn token của người dùng (tương ứng với nhóm) đã được chọn.

Initial OAuth Web Flow for Team Level Token

Khi người dùng gửi yêu cầu tạo Droplet, ứng dụng proxy sẽ can thiệp vào yêu cầu này và gọi đến trình bọc của chúng ta.

Trình bọc này sẽ tạo ra một token cấp phát – đây là một token JWT. Token này có trường “subject” (chủ thể) chứa một giá trị nonce (giá trị ngẫu nhiên dùng một lần) và trường “audience” (đối tượng) chứa UUID của nhóm vốn được liên kết với DigitalOcean Personal Access Token (PAT) đã gửi đến endpoint (điểm cuối) tạo Droplet.

Sau đó, trình bọc sẽ chèn token cấp phát này vào Droplet bằng cách sửa đổi trường user_data của cloud-init.

Cuối cùng, yêu cầu tạo Droplet đã được sửa đổi và PAT sẽ được chuyển tiếp đến API thượng nguồn để thực hiện việc tạo Droplet.

Part 2: Workload Identity Token Provisioning for Droplet

Ứng dụng sẽ bổ sung token định danh workload vào Droplet sau khi quá trình ký và xác thực token cấp phát được hoàn tất thành công thông qua cloud-init.

Trong lần khởi động đầu tiên, cloud-init sẽ thực thi user_data, qua đó ràng buộc token cấp phát vào Droplet bằng cách dùng khóa riêng tư SSHD của Droplet để ký.

Token cấp phát và chữ ký sau đó được trao đổi để lấy token định danh workload. Dịch vụ của chúng ta sẽ tra cứu địa chỉ IP của Droplet, sử dụng token OAuth của nhóm nhận được từ luồng OAuth.

Dịch vụ sẽ kết nối đến cổng SSHD đang lắng nghe của Droplet và truy xuất khóa SSH công khai của Droplet. Khóa này được dùng để xác minh chữ ký trên token cấp phát. Sau khi xác minh thành công, dịch vụ sẽ trả về token định danh workload cho Droplet để lưu trữ và sử dụng sau này.

Token định danh workload là một token RSA JWT tuân thủ giao thức OIDC. Token này có trường ”subject” chứa thông tin từ các thẻ của Droplet, đồng thời chứa UUID của nhóm trong trường ”audience”.

Bằng cách đưa UUID của nhóm vào trường “audience”, chúng ta cho phép ánh xạ các token định danh workload với token của nhóm vốn được cung cấp bởi luồng OAuth web ban đầu.

Workload ID Token Provisioning Flow

Từ Droplet, token định danh workload có thể được gửi đến ứng dụng proxy của chúng ta. Tại đây, các trình bọc (wrappers) cho chức năng tạo Khóa Spaces và truy xuất thông tin Cơ sở dữ liệu sẽ tra cứu token OAuth tương ứng của nhóm.

Trước khi proxy thực hiện yêu cầu đến API thượng nguồn, chính sách liên quan (được tham chiếu bởi trường ”subject” của token định danh workload) sẽ được sử dụng để xác thực dữ liệu yêu cầu từ workload. Token OAuth của nhóm (với phạm vi đã định) sau đó được sử dụng để thực hiện yêu cầu đến API thượng nguồn.

Cách tiếp cận này cho phép chúng ta hoạt động một cách hiệu quả như API của DigitalOcean đối với các client được cấu hình đúng, chẳng hạn như doctl. Người dùng thiết lập URL API của doctl trong tệp cấu hình doctl trỏ đến tên miền đầy đủ (FQDN) mà họ đã triển khai ứng dụng API proxy.

Bất kỳ lệnh doctl nào sau đó sẽ bị logic của proxy can thiệp và bọc lại, hoặc được chuyển tiếp nguyên vẹn. Các yêu cầu POST (để Tạo Droplet và Tạo Khóa Spaces) cũng như các yêu cầu GET (đến các endpoint của Cơ sở dữ liệu) đều bị can thiệp và xử lý bởi các script bên trong ứng dụng proxy. Các script này sẽ bọc các yêu cầu và phản hồi bằng logic tùy chỉnh của ứng dụng.

Tất cả các yêu cầu khác đều được chuyển tiếp thẳng đến API thượng nguồn của DigitalOcean.

Part 3: Use of Workload Identity Token by Droplet to Access Resources

Các bước tiếp theo

Sau khi đã xem xét cách thức hoạt động của Bằng chứng Khái niệm (PoC) mã nguồn mở, chúng ta sẽ triển khai ứng dụng này lên DigitalOcean App Platform.

Sau khi triển khai, chúng ta sẽ viết cấu hình HCL tùy chỉnh để định cấu hình các vai trò và chính sách, cho phép các token định danh workload được quy đổi lấy các token truy cập đặc thù của API.

Việc quy đổi token là một mô hình thực hành tốt nhất. Tài liệu “PyPI Docs: Internals and Technical Details” có nhiều thông tin hơn về việc quy đổi token trong một bối cảnh khác, có thể giúp người đọc hiểu rõ hơn về khái niệm này.

Cuối cùng, chúng ta sẽ sử dụng token định danh workload của Droplet để tạo các khóa Spaces và truy xuất các URI kết nối Cơ sở dữ liệu. Chúng ta cũng sẽ cấu hình các vai trò và chính sách để kích hoạt khả năng tương tự từ các quy trình của GitHub Actions thông qua cơ chế liên kết định danh workload.

Đọc thêm: 

GPU Autoscaling Cho AI: Từ Thiết Lập Đến Tối Ưu Hóa Chi Phí

Hướng Dẫn Chọn GPU Droplet Tối Ưu cho AI/ML 2025

Chức năng này đã bị chặn