FR-039 · 分散式檔案 Agent · 認證規格 v2
Cloud ↔ Agent 認證:自我註冊 + 憑證簽發 + 設備指紋 + 心跳
以 CLIENT_SERVER_REGISTRATION.txt 為準重整。agent 帶 token 主動自我註冊、雲端 enroll 時自動簽發憑證、設備指紋綁定、心跳維護 online/offline。資料面沿用 cloud→agent /blob。
版本 v2 · 取代 v1
註冊 agent 自我註冊(token)
憑證 雲端 enroll 自動簽發
資料面 維持 cloud→agent
即時 UI / 封裝 延後
決策
| # | 項目 | 定案 |
| 1 | 註冊方式 | agent 自我註冊(installer/.env 帶 token+endpoint,主動發第一次心跳) |
| 2 | 資料面方向 | 維持 cloud→agent(/blob 沿用);跨外網用 tunnel(另案) |
| 3 | 憑證 | 雲端 enroll 自動簽發(CSR→CA 簽 server 憑證回傳) |
| 4 | 即時 UI | 延後(未來 SocketIO);現階段重新整理看狀態 |
| 5 | 註冊 token | 每 tenant 一組(可重生/撤銷),installer 內建 |
| 6 | 設備指紋 | product_uuid + machine_id + MAC → sha256 = device_uuid;agent 主動送 |
| 7 | 封裝 | 延後(先 Docker+.env;只影響指紋讀取/TLS 終結末端) |
| 8 | 撤銷 | status(active/revoked) + JWT 短效 → 幾乎即時失效 |
1 架構總覽
控制面(agent 主動撥出,避防火牆) 資料面(cloud→agent,沿用已 ship)
agent ──register / heartbeat──▶ 雲端 雲端 ──/blob 上傳·下載·刪·預覽──▶ agent
token + device_uuid enroll: (mTLS + JWT + 指紋 + status 檢查)
+ hardware + version 驗 token→upsert
→簽發 agent 憑證
→last_seen / online
- 控制面(註冊+心跳):agent 主動撥出 → 永遠通。
- 資料面(檔案):維持 cloud→agent(已 ship,含 SHA-256 對帳);跨外網 = tunnel(另案)。
- 認證:bootstrap 用 token+TLS;穩態用雲端簽發的 agent 憑證 + mTLS + JWT + 指紋。
2 設備指紋 / device_uuid
device_uuid = sha256( product_uuid + "|" + machine_id + "|" + primary_mac )
| 識別碼 | 來源 | 綁定維度(重灌 / 換板) |
product_uuid | /sys/class/dmi/id/product_uuid(SMBIOS) | 硬體:重灌不變 / 換板變 |
machine_id | /etc/machine-id(systemd) | OS 安裝:重灌變 / 換板不變 |
primary_mac | 主網卡(Docker 階段:部署腳本寫檔掛入) | 網卡 |
agent 主動收集後送(不再雲端去抓)。三者正交 → 移機/重灌/clone/換網卡 任一就變。副作用:客戶重灌/搬機 → 指紋變 → 被擋 → 需「重新綁定」。
3 註冊 Token — 生命週期 + UI 情境(per-tenant)
何時 / 何處產生
- 何處:雲端 UI「Agent 管理 → 註冊 Token」
- 何時:admin 部署 agent 前手動按產生(on-demand)
- 歸屬:跟著當下登入 tenant(RLS)→ per-tenant
- 儲存:雲端只存 hash;明文只顯示一次(像 API key),弄丟須重產
一組 token → 多台 agent
token 認的是「哪個 tenant」,不是某台機器。同一 tenant token 可裝在該客戶多台 agent;每台真正身分是自己的 device_uuid(指紋),雲端註冊時 per-device 簽憑證。
UI 操作情境
1
admin(manager) → Agent 管理 → 「註冊 Token」
2
還沒有 → 顯示「尚未產生」+【產生註冊 Token】鈕
3
按產生 → 雲端產隨機 token、存 hash、回明文一次 → 可複製框(token + endpoint + 警語「僅顯示一次」)
4
複製 → 填進 agent .env(REGISTRATION_TOKEN + CLOUD_ENDPOINT) 封裝後改內建 installer
5
客戶機器部署 agent → 開機帶 token 自我註冊 → 設備自動出現在清單(重新整理可見)
6
外洩/輪替 → 【重新產生】(舊失效) 或 【撤銷】
定案:① token 先做「一組 active」UX(簡單),但資料表保留 label+enabled → 未來要「多組平滑輪替 / 分批撤銷」不用改 schema,加 UI 即可(多組時每個 enabled token 都能 enroll)。② 新設備自動 enroll、不審核(照附件);可疑設備事後用「撤銷(status=revoked)」處理。
4 憑證自動簽發
1
agent ──HTTPS(雲端 server cert) + token──▶ 雲端 bootstrap:只靠 token + TLS
2
雲端驗 token → tenant 確認 → agent 產 keypair 送 CSR → CA 簽 agent server 憑證(SAN=host/IP) → 回傳
3
之後 agent 用此憑證跑 HTTPS server;資料面走 mTLS + JWT 穩態
雲端側一次性:CA、雲端 client 憑證、JWT 私鑰(放 secret)。每台 agent:憑證自動簽發,不用 ops 手配。
5 完整流程
(1) 安裝/初始化
installer(現階段 Docker+.env)帶雲端 endpoint + 該 tenant token;agent 啟動算 device_uuid。
(2) 第一次心跳 = 註冊
POST /api/1.0/agents/register
{ token, device_uuid, base_url, hardware_info, agent_version, status:"registering" }
(3) 雲端 enroll + 綁定 + 簽憑證
b
Upsert by (tenant_id, device_uuid):有則更新、無則新增一列進 remote_agents
c
回傳簽好的 agent 憑證(+CA);UI 上設備自動出現(重新整理可見)
(4) 後續心跳
每 N 分鐘 POST /api/1.0/agents/heartbeat { device_uuid, status }
→ 雲端更新 last_seen_at;超過門檻(如 30 分)未收到 → offline
即時 UI 延後:online/offline 由 last_seen_at 推算,管理頁重新整理顯示。
(5) 資料面(沿用 cloud→agent)
雲端用 agent 回報的 base_url 打 /blob*:mTLS + JWT(帶 bound device_uuid) + agent 驗指紋 + status != revoked。
(6) 重新綁定 / 撤銷
重灌/搬機 → device_uuid 變 → 對不上 → admin「重新綁定」(manager)。可疑 → 「撤銷」設 status=revoked → 雲端即拒。
6 DB Table 異動
compliance.remote_agents 加欄
| 欄位 | 型別 | 說明 |
device_fingerprint | VARCHAR(64) | = device_uuid Phase1 已加 |
status | VARCHAR(20) | active / revoked Phase1 已加 |
last_seen_at | TIMESTAMP NULL | 最後心跳;online/offline 由此推算 NEW |
agent_version | VARCHAR(50) NULL | agent 回報版本 NEW |
hardware_info | JSONB NULL | agent 回報硬體細節 NEW |
base_url 改由 agent 註冊回報(非 UI 手打);upsert 鍵 = (tenant_id, device_fingerprint)。
新表 compliance.remote_agent_enroll_tokens(per-tenant 註冊 token)NEW
| 欄位 | 說明 |
id / uid | PK / 識別 |
tenant_id | 歸屬租戶 |
token_hash | token 的 sha256(不存明文) |
label / enabled | 備註 / 是否有效(撤銷=false) |
agent 端 DB(fileagent.upload_files)不變。
7 改動範圍(reuse / change / new)
| 內容 |
| ♻️ 重用 | 資料面 /blob(上傳/下載/刪/預覽/SHA-256 對帳)、registry、storage-config、Phase1 的 device_fingerprint/status |
| 🔧 改 | 註冊:UI 手打 → agent 自我註冊 + upsert;憑證:ops 預發 → 雲端 enroll 簽發;指紋:雲端抓 → agent 送 |
| ➕ cloud BE | /agents/register、/agents/heartbeat、token 表+CRUD+重生/撤銷、CA 簽發 util、JWT util(RS256)、last_seen/online 推算、撤銷/重新綁定 |
| ➕ agent | 開機算 device_uuid、自我註冊+心跳迴圈、存雲端回傳憑證、資料面驗 JWT+指紋、TLS |
| ➕ FE | 設備清單(自動出現/狀態欄 online-offline-active-revoked)、token 管理頁、重新綁定/撤銷鈕(manager) —— 加在現有頁旁,不取代 |
| ⏸️ 退場 | 先保留,不做:UI 手動新增 agent、現有測試連線/對帳全留著,自我註冊與其並存 |
8 延後 / 安全上限
延後:即時 UI(SocketIO 推播,未來有需求再做)/ 封裝 .msi.deb(最後做,只影響指紋讀取與 TLS 終結末端)/ 資料面跨外網 tunnel(另案)。
安全上限:指紋為 agent 軟體自報 → 擋一般憑證盜用;擋不住完全控制機器 + 改 agent 偽造指紋。更強需 TPM(未來)。