Skip to Content
概念逐操作存取

逐操作存取

以 builder 政策 department-worker-project-v2.8 或更新版本建置的 release(截至後端 5.22.0,每次新提交都以 department-worker-project-v2.10 建置)上,部門管理者可以針對每個 manifest operationId 覆寫存取模式與 IP 允許清單,也能讓每個操作擁有自己的 API 金鑰。Worker 層級政策仍是各操作繼承的預設值。逐操作存取首次隨後端 v5.13.0 推出。上線 release 早於 v2.8 的 Worker 只有一份 Worker 層級政策;在重新上傳專案並部署之前,操作設定路由一律回 409 operation_settings_require_supported_release(各政策版本的能力對照表在提交管線)。操作步驟見管理逐操作存取。

一個 Worker 服務不同對象時就用它:public 的讀取操作旁邊放需要金鑰的寫入操作、只允許發送端 CIDR 的 webhook 接收端、維持 teamsync_internal 的操作,或每個整合各發一把金鑰,撤銷其中一把不影響其他整合。

設定模型

僅限部門管理者的 GET/PUT /worker/operation-settings 路由讀取與替換每個 release 的一張表:

欄位意義
operations[].operation_idmanifest 的 operationId(1–64 字元,^[A-Za-z][A-Za-z0-9_]{0,63}$)
operations[].accessnull = 繼承 Worker 層級政策;或覆寫值 {mode, ip_allowlist},使用同樣五種模式
operations[].service_account_id此操作 context.teamsync.authHeaders() 的出站身分 — 見服務帳號
default_service_account_id沒有自身綁定的操作所用的出站身分
revision此 release generation 那張表的 CAS 權杖
statelegacy、reconciled 或 pending(見下表)
狀態意義公開通道
legacyDurable Object 從未替任何 release 儲存過操作設定;revision 為 0每個操作都用 Worker 層級政策(v2.8 之前的行為)
reconciled此 release generation 已有設定表各操作的有效政策
pending其他 release generation 有設定,這一個卻沒有;revision 為 0失敗即關閉:403 operation_settings_pending

檢視對 manifest 的每個操作各回一筆,依 operation_id 排序,含 method、path、儲存的 access 覆寫值,以及 effective_access {mode, ip_allowlist_configured, api_key_configured, source}。操作有一列覆寫了模式、或該操作現有或曾有自己的金鑰時,source 為 operation,否則為 worker。已知的後端不一致:沒有列、但曾擁有金鑰的操作,在這個檢視中讀到 source: "worker",在生成的 OpenAPI 中卻是 "operation"。操作金鑰的明文、摘要與後四碼提示永遠不會被回傳。

依 release generation 儲存

設定存在部門 Worker 的 Durable Object 裡、與 Worker 層級政策並列,以 release generation(由版本的專案摘要、依賴摘要與 builder 政策推導)為鍵。每個 generation 的表有自己的 CAS revision:PUT 以 base_revision 送出目前的值,成功時恰為 base_revision + 1。

  • 部署會在新 release 開始服務之前,先為目標 generation 暫存設定表,並把上線中的列帶過去(規則見管理逐操作存取)。暫存的表從自己的 revision 起算,所以每次部署後、下一次 PUT 之前都要重新讀取設定。
  • PUT 與操作金鑰輪替只保留上線中 generation 的表,其他 generation 的表都會刪除;部署暫存則保留上線中與目標 generation 的表,其餘刪除。部署票證處於 pending、leased 或 uncertain 時,PUT 與輪替都會被拒絕,所以暫存的表不會在部署途中被丟棄。
  • 撤銷操作金鑰會在每個已儲存的 generation 中清除該操作的金鑰。

有效政策

在公開通道上,生成的 runtime 針對每個比對到的操作,計算正在服務的 release generation 的政策:

情況模式與 IP 允許清單檢查的金鑰
狀態 legacyWorker 層級Worker 層級金鑰
reconciled,該操作沒有列Worker 層級Worker 層級金鑰 — 若該操作曾擁有自己的金鑰則不接受任何金鑰
列的 access: nullWorker 層級的模式與 CIDR操作現有或曾有自己的金鑰時用它自己的,否則用 Worker 層級金鑰
列帶覆寫值覆寫值的模式與它自己的 CIDR(不與 Worker 層級清單合併)操作現有或曾有自己的金鑰、或覆寫為 api_key/api_key_and_ip 時用它自己的,否則用 Worker 層級金鑰
  • 金鑰擁有權是永久的。 操作一旦擁有過金鑰,即使撤銷後也不會再退回 Worker 層級金鑰;有效模式為 api_key 或 api_key_and_ip 時,在輪替出新的操作金鑰之前不接受任何金鑰。
  • api_key 或 api_key_and_ip 覆寫若沒有自己的金鑰,在為該操作輪替金鑰之前會拒絕所有公開呼叫。
  • CIDR 處理與 Worker 層級政策相同:項目會正規化(with_prefixlen)、不可重複並排序;ip_allowlist 與 api_key_and_ip 至少要一條 CIDR,其他模式與繼承的列都不帶 CIDR。
  • 各模式的拒絕狀態碼不變:api_key → 401 access_denied(Unauthorized);ip_allowlist、api_key_and_ip 與 teamsync_internal → 403 access_denied(Forbidden)。

操作 API 金鑰

  • POST /worker/operation-settings/{operation_id}/api-key 產生 tsw_ + 43 個 URL-safe 字元(secrets.token_urlsafe(32),共 47 字元),並且只回傳一次,附 header_name: "X-TeamSync-Worker-Key" — 與 Worker 層級金鑰用同一個 header。送到 Durable Object 的只有 SHA-256 摘要與後四碼。
  • 任何管理回應與 OpenAPI 文件都不會顯示操作金鑰的後四碼提示,只有 effective_access.api_key_configured。請自行記錄哪把金鑰交給了哪個整合。
  • 輪替要求上線中的表為 reconciled(legacy 的 Worker 要先寫一次設定),會立即取代該操作先前的金鑰、把 revision 推進 1,且不改變模式:只有在操作的有效模式為金鑰模式時才會檢查金鑰。
  • 撤銷會在每個已儲存的 generation 中清除金鑰並推進 revision;重複撤銷回 revoked: false,且不推進 revision。

與 Worker 層級政策的組合

  • /worker/access-policy 上的 Worker 層級政策仍適用於 legacy 的 Worker、沒有覆寫值的操作,以及比對不到的路徑。
  • 上線 release 以政策 v2.8 或更新版本建置時,Worker 層級金鑰輪替僅限舊版:POST /worker/access-policy/api-key 回 409 {"code":"worker_wide_key_legacy_only","message":"Rotate an operation key instead"},且只要存在任何操作設定表,Durable Object 也會拒絕。撤銷 Worker 層級金鑰在每個 release 上都仍可用(管理存取政策)。
  • 在舊版 release 下產生的 Worker 層級金鑰會跨部署保留,仍可讓從未擁有金鑰的繼承操作通過。第一次部署就是 v2.8 或更新版本的 Worker 永遠無法產生 Worker 層級金鑰,因此 Worker 層級的 api_key 或 api_key_and_ip 模式會拒絕所有沒有自己金鑰的繼承操作。

公開通道的回應

驗證完 dispatch context 並載入呼叫狀態後,依序檢查:

  1. 退役鎖定(兩條通道)→ 403 worker_retired(Forbidden)— 見退役。
  2. 路由比對。公開通道上路徑比對不到或方法不符時:狀態 pending → 403 operation_settings_pending;Worker 層級准入 → 401/403 access_denied;接著才是 404 operation_not_found 或 405 method_not_allowed。
  3. 公開通道上比對到操作:狀態 pending → 403 operation_settings_pending(Forbidden);否則以該操作的有效政策准入 → 401/403 access_denied。
  4. 執行 handler。

簽章通道(/worker/invoke 與其他 TeamSync 呼叫端)從不依模式或操作設定准入;它只受退役鎖定影響。

生成的 OpenAPI

  • 根層級的 x-teamsync-operation-settings-state {state, revision} 一律存在(v2.8 之前的 release 為 legacy、0)。根層級的 security、servers[0].url 與 x-teamsync-access-policy 仍描述 Worker 層級政策。
  • 只有狀態為 reconciled 時:每個有設定列或曾擁有金鑰的操作,都帶自己的 x-teamsync-access-policy {mode, ipAllowlistConfigured, apiKeyConfigured, source}。若其有效模式與 Worker 層級模式不同、或 source 為 operation,還會帶操作層級的 security(teamsync_internal 為 TeamSyncBearer、金鑰模式為 TeamSyncWorkerApiKey、public/ip_allowlist 為 []),且當其 base URL 與根層級不同時,帶操作層級的 servers(teamsync_internal 為後端 invoke base,其他為公開 URL)。每個操作也都帶 x-teamsync-service-account(未綁定帳號時為 null)。
  • components.securitySchemes 最多兩個機制:Worker 層級機制與各操作機制的聯集。TeamSyncWorkerApiKey header 帶操作自己的金鑰;沒有自己金鑰的繼承操作則帶 Worker 層級金鑰。
  • 設定變更時 ETag 就會改變,不需重新部署。產生用戶端的工具必須遵循操作層級的 security 與 servers。

限制

限制值
每張設定表/每個請求的操作數64
每個操作覆寫值的 CIDR 數64
所有操作加總的 CIDR 數256
任何 /worker/operation-settings 路由的請求本體64 KiB(65 536 B)→ 413 Worker operation settings request exceeds limit
base_revision0 – 9 007 199 254 740 990
部門層級的設定鎖600 秒後過期

稽核

PUT 寫入 operation_settings.replaced、部署暫存寫入 operation_settings.staged、輪替寫入 operation_settings.api_key.rotated、撤銷寫入 operation_settings.api_key.revoked 或 operation_settings.api_key.revoke_noop — resource type 為 edge_worker_operation_settings,只記摘要(輪替記錄金鑰的 SHA-256,絕不記錄金鑰本身)。這些都走耐久的控制面稽核 outbox;見稽核。

Last updated on