file_access_agent/README.md
2026-04-24 18:21:28 +09:00

12 KiB
Raw Blame History

File Access Agent

File Access Agent 是檔案存取代理服務,用來控管 bucket / file space 裡檔案的上傳、下載、metadata 讀取與刪除權限。

本專案已決定使用 C# / ASP.NET Core。目標與授權模型依 ../member_center 最新文件整理,後續實作會以此為準落地。

已確認決策

  • 部署模型採 single-tenant instance一個 File Access Agent instance 只服務一個 tenant。
  • tenant_id 仍是 token 與授權邊界的一部分,但服務端會驗證其必須等於本 instance 的固定 tenant。
  • 服務預設為無 DB、stateless access gateway。
  • 每個 request 只處理單檔upload/download/metadata/delete不提供結構化查詢。
  • 版本管理由上游服務負責;不同版本在 bucket 中視為不同單檔(不同 object_key 或等價識別)。
  • Agent 可只以 object_keyfile_id 作為單檔識別,不保存完整 metadata。

專案目的

此服務位於業務服務與實際檔案儲存 bucket 之間,負責檔案存取的安全邊界。

核心目的:

  • 驗證由 Member Center 簽發的 OAuth2/JWT access token。
  • scopetenant_idaud、檔案識別與 HTTP method 判斷是否允許存取。
  • 讓後端服務可以用 S2S token 上傳檔案。
  • 讓後端服務在完成自身商業規則檢查後,向 Member Center 取得可給 client 使用的短效下載授權。
  • 避免把一般 S2S access token 直接暴露給 client。
  • 將 bucket provider 的直接存取權限集中在此服務或其 storage adapter 內。

Agent 角色定義

File Access Agent 是 access permission gateway不是檔案主資料服務。

負責:

  • 驗證 token 與 request 邊界(tenant_idscopeaudmethodobject_key/file_id
  • 代理單檔 upload/download/metadata/delete
  • 呼叫 Member Center delegated token validation endpoint

不負責:

  • delegated token 簽發(由 Member Center 負責)
  • 商業規則與版本管理(由上游服務負責)
  • 結構化查詢、報表或資料分析
  • metadata 主資料治理(預設不落地 DB

與 Member Center 的關係

Member Center 是 OAuth2/OIDC issuer 與 JWKS 提供者。File Access Agent 不負責會員登入、OAuth client 管理或長效 access token 簽發。

../member_center 目前已規劃並落地下列 File Access 相關授權設定:

  • audience / resourcefile_access_api
  • OAuth client usagefile_api
  • scopes
    • files:upload.write
    • files:download.read
    • files:download.delegate
    • files:metadata.read
    • files:delete

最新版 member_center 文件已明確把 File Access 納入同一套租戶授權模型:file_api client 必須綁定 tenant_idupload token 與 delegated download token 也都必須帶 tenant_id

File Access Agent 應驗證:

  • upload 的 S2S JWT透過 Member Center JWKS 驗 issaud=file_access_apiexpscopetenant_id
  • download 的 delegated token以 Member Center validation endpoint 線上驗證
  • token 中的 tenant_id 是否符合實際 request
  • token 中的 object_keyfile_id 是否符合實際 request
  • token 中的 method 是否符合實際 request

待確認的檔案邊界 claim

  • user_iddelegated download token 目前由 Member Center 文件定義為必帶,用於對應業務服務已驗過的使用者身分。
  • owner_id / subject / client_id:可用於紀錄或限定上傳者。
  • bucket / namespace / object_prefix:若 storage 需要多 bucket 或 prefix 隔離,應優先明確化。
  • file_id / object_key:下載 token 必須綁定其中一種檔案識別。

預期流程

Upload: service to File Access Agent

  1. 業務服務以 client_credentials 向 Member Center 取得 access token。
  2. token 需包含 aud=file_access_apitenant_idfiles:upload.write
  3. 業務服務帶 Bearer token 呼叫 File Access Agent 上傳檔案。
  4. File Access Agent 驗 token、tenant_id 與檔案邊界後,寫入 bucket / file space。

Download: service to client to File Access Agent

  1. client 向業務服務要求下載檔案。
  2. 業務服務自行驗證商業規則與檔案權限。
  3. 業務服務以 files:download.delegate 呼叫 Member Center POST /file-access/download-tokens 取得短效 download token。
  4. download token 至少綁定 tenant_iduser_idobject_keyfile_idmethod=GET、短效 exp
  5. client 帶短效 token 直接向 File Access Agent 下載檔案。
  6. File Access Agent 以 files:download.read 呼叫 Member Center POST /file-access/download-tokens/validate,帶上 token 與實際 GET request 邊界,驗證通過後放行。

責任邊界已確認:

  • Member Center簽發 upload 用的 S2S JWT、簽發 delegated short-lived download token、提供 download token validation endpoint。
  • File Access Agent驗證 upload JWT、呼叫 validation endpoint 驗 delegated download token、控管實際 bucket / file space 的讀寫。
  • 業務服務:先驗商業規則與使用者檔案權限,再向 Member Center 申請 delegated download token。

初步 API 邊界

實際路由可在實作時調整,但能力邊界應維持清楚:

  • PUT /files/{object_key}:上傳檔案,需 files:upload.write
  • GET /files/{object_key}:下載檔案,需 files:download.read
  • HEAD /files/{object_key}GET /files/metadata/{object_key}:讀 metadatafiles:metadata.read
  • DELETE /files/{object_key}:刪除檔案,需 files:delete

本服務不負責提供 POST /download-tokens。該責任已在 Member Center

  • POST /file-access/download-tokens
  • POST /file-access/download-tokens/validate

非目標

  • 不負責會員註冊、登入、OAuth consent 或 OAuth client 管理。
  • 不取代 Member Center 的 token issuer 職責。
  • 不把 bucket credentials 發給 client。
  • 不由 File Access Agent 判斷完整商業規則;業務服務仍需先判斷使用者是否可存取指定檔案。
  • 不在語言與 storage provider 尚未決定前鎖死特定 SDK 或框架。

上傳命名與重複策略

  • Agent 不做複雜命名規則;object_key 由介接服務決定。
  • 相同 object_key 再次上傳時Agent 視為覆蓋overwrite不自動版本化。
  • 若要避免檔名重複,介接服務應自行把 timestamp/uuid/業務主鍵 放入 object_key
  • 若要版本管理,介接服務需為每個版本使用不同 object_key(例如 v0001, v0002)。
  • 詳細命名建議請見 docs/API.md 的 Upload 區段。

待決策

  • bucket / object storage provider例如 S3、GCS、Cloudflare R2、MinIO 或本機檔案系統。
  • 是否需要「可選」持久化token jti、審計紀錄或特殊索引(預設不啟用)。
  • object key 命名規則與 bucket / namespace / prefix 隔離策略。
  • 檔案大小限制、content-type allowlist、病毒掃描與保留期限。
  • 是否支援 presigned URL或所有流量都經由 access agent proxy。

Storage 設定

API 支援兩種 provider

  • Storage:Provider=local:使用本機檔案系統(Instance:StorageRoot
  • Storage:Provider=minio:使用 MinIOS3 compatible

MinIO 設定(src/FileAccessAgent.Api/appsettings.json

  • Minio:Endpoint:例如 localhost:9000
  • Minio:AccessKey
  • Minio:SecretKey
  • Minio:BucketName
  • Minio:UseSsltrue|false
  • Minio:Region:可空

實作語言

本專案已決定使用 C# / ASP.NET Core。

C# / ASP.NET Core

  • member_center 同語言,跨專案概念與維運一致。
  • ASP.NET Core 對大檔串流、middleware、auth policy、DI、設定管理很成熟。
  • 編譯期檢查較強,適合安全邊界服務。
  • 可直接沿用 member_center 的設定、OpenAPI、JWT / OAuth 與部署習慣。

目前實作方向會以 ASP.NET Core Web API 為主,並保留 storage adapter 抽象,避免過早綁死特定 bucket provider。

文件維護規則

每次改動功能、流程、API、scope、設定或部署方式時都要同步更新文件。

優先更新順序:

  1. README.md:專案目的、目前決策、執行方式與重要限制。
  2. docs/若後續建立更細文件放設計、API、流程、部署、決策紀錄。
  3. API 規格:一旦路由與 payload 穩定,補 OpenAPI 或等價規格。

如果程式碼與文件不一致,應先修正 README 或在 README 標示尚未決定,避免讓文件變成過期假設。

目前文件:

  • docs/API.mdFile Access Agent API 規格與 Member Center 整合契約
  • docs/openapi.yaml:本專案 OpenAPI 草案
  • docs/DATA_MODEL.md:可選持久化擴充(非預設)

測試專案

  • src/FileAccessAgent.TestSiteRedirect login 測試站OIDC Authorization Code + PKCE
  • 目的:透過 Member Center web_login client 登入,取得並顯示 token/claims並直接測試 Agent APIupload / download / head / metadata / delete / health
  • 測試站採雙 token 模式:
    • web_login token只用於身份展示claims / user context
    • file_api service tokenclient credentials用於呼叫 Agent 與 Member Center delegated token API

最小設定(src/FileAccessAgent.TestSite/appsettings.json

  • MemberCenter:Authority
  • MemberCenter:WebBaseUrlMember Center Web預設 http://localhost:5080,供 redirect logout 使用)
  • MemberCenter:ClientIdweb_login
  • MemberCenter:ClientSecretweb_login public client 可留空)
  • MemberCenter:CallbackPath(需與 Member Center OAuth client redirect URI 一致)
  • MemberCenter:SignedOutCallbackPathOIDC middleware callback建議保留預設 /signout-callback-oidc,不要與 direct logout callback 共用)
  • MemberCenter:Scopes(建議 openid email profile
  • MemberCenter:ServiceClientIdfile_api
  • MemberCenter:ServiceClientSecretfile_api
  • MemberCenter:ServiceScopes(至少 files:upload.write files:metadata.read files:delete files:download.delegate
  • FileAccessAgent:BaseUrl
  • FileAccessAgent:TenantId

啟動:

  • dotnet run --project src/FileAccessAgent.TestSite/FileAccessAgent.TestSite.csproj
  • 進入首頁後點 Login,會導到 Member Center再 redirect 回測試站
  • Logout 會走 Member Center Web GET /account/logout?returnUrl=...,再 callback 回 TestSite /auth/logout-callback
  • 若 logout 後未回到 TestSite而停在 Member Center需在 Member Center Web 設定:
    • Auth__AllowedLogoutReturnUrlPrefixes=http://localhost:5091/
  • 登入後可在同一頁直接執行 UploadDownloadHeadGet MetadataDeleteHealth
  • Upload 改為檔案挑選上傳;Object Key 可選填(留空會自動產生 demo/uploads/<timestamp>-<filename>
  • 上傳成功後會保留回傳的 object_key 供後續 Metadata/Head/Download/Delete 直接測試
  • 另提供 Download (Invalid Token) 測試,故意帶錯 token 驗證 Agent 拒絕邏輯
  • Download 會先呼叫 Member Center POST /file-access/download-tokens 申請 delegated token再帶 token 呼叫 Agent 下載
  • Download File 走 sample 的直連模式TestSite 僅向 Member Center 取 delegated token接著把 client 轉址到 Agent 下載 URL含短效 access_token),下載流量不經 TestSite

目前狀態

  • 專案目標已依 ../member_center 文件整理。
  • 已確認使用 C# / ASP.NET Core。
  • tenant_id 與 delegated download token 分工已依最新版 member_center 文件校正。
  • 目前目錄中的 .NET skeleton 可作為正式起點,但仍需依最新流程補上 Member Center validation 串接。