檢測工具管理(Detection Tool Management)
事實基準:2026-07-29 從 FE
src/views/plugin/ToolPluginManage.vue(566 行)+ BEapp/detection_tools/全模組掃出(FR-056 檢測工具整合平台 T-1.1~T-1.5 + FR-057 OpenSCAP SSH 連接器)
變更紀錄
| 日期 | FR | 內容 |
|---|---|---|
| 2026-07-29 | FR-057 | 上線第二款檢測工具
OpenSCAP(connection_type='SSH',第三種連線型態);config_field_schema
的 type 擴充
textarea/boolean/select_or_text,新增
condition(欄位依賴顯示)與
default(預設值)語意;新增
setup_guide(部署前提說明 + 一鍵複製準備腳本,工具卡片
overflow menu 開 Dialog);SSH
型工具測試連線改為先輸入測試主機、逐台彙總結果 |
| 2026-07-27 | FR-056 | 全面改寫:本頁自 T-1.5 起已從前端 mock
占位頁改為完整接後端功能——工具目錄(config.detection_tools)+
租戶設定 CRUD(含加密憑證)+ 測試連線(雲端直推 Agent)+ 動態參數 schema
+ D6 引用計數軟提醒 + 重置金鑰;舊版「hardcoded 工具清單、無
API」的紀錄已完全過時 |
1. 功能描述
檢測工具管理是租戶層級的外部資安檢測工具設定介面:管理平台工具目錄中已啟用的檢測工具(目前已上線 OpenVAS 弱點掃描、OpenSCAP 組態合規稽核兩款),供租戶填寫連線資訊(主機位址、帳密、SSH 憑證等)、測試連線、並在 任務配置 頁把工具綁定到「檢測工具執行」型任務上。
平台維護的「工具目錄」(config.detection_tools)是
DB
驅動而非程式寫死:每筆工具定義代碼、顯示名稱、連線類型(API/CLI/SSH)、設定欄位結構(config_field_schema,動態表單
JSON)、部署前提說明(setup_guide)與平台層
status(available/coming_soon)。本頁的設定表單、任務配置頁的掃描參數表單,皆完全依
BE 回傳的 schema 動態渲染——FE
對工具型別零硬編,新增工具(如未來 Nessus/SonarQube 轉正)只需目錄補資料
+ Agent 端補 connector,前端不用改代碼。OpenSCAP 的加入證明了這個
schema-driven 架構可平滑擴充:新增
textarea/select_or_text 型態、條件顯示、SSH
第三種連線型態,皆未動到本頁核心邏輯。
主要使用者:租戶層級管理者(過渡期以帳號層
super_admin 守門,見 §3)。
角色速覽:
| 角色 | 一句話 |
|---|---|
| 租戶 admin(過渡期=帳號 super_admin) | 本頁唯一使用者——新增/修改工具設定、測試連線、停用、重置金鑰 |
| (Agent 本身) | 不是本頁使用者,而是「測試連線」與真實掃描的實際執行者;透過雲端 mTLS 直推指令運作,不經過本頁 UI |
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 工具目錄清單 | 卡片呈現平台工具目錄(GET /detection-tools,僅回
available 者,coming_soon
由目錄本身標記過濾邏輯在 BE) |
主畫面 Card grid | §6.2 |
| 2 | 搜尋工具 | 依工具名稱前端本地過濾(searchedTool) |
搜尋框 | 純前端 |
| 3 | 待啟用工具灰化 | status==='coming_soon' 的工具卡片降低透明度 +
顯示「敬請期待」Tag,動作按鈕全部隱藏 |
工具卡片 | §5 |
| 4 | 設定 / 編輯連線資訊 | 開 Dialog,依 config_field_schema 動態渲染欄位(含
secret 遮罩);首次設定按鈕文案「設定」,已有設定後文案「編輯」 |
Dialog | UC-TPM-01 |
| 5 | 測試連線 | 以已存檔設定值,透過雲端直推內網 Agent 實際連線工具端驗證;SSH 型工具(如 OpenSCAP)先彈輸入框要求填測試主機,可填多台、逐台並發彙總結果 | 工具卡片按鈕(僅已設定才顯示) | UC-TPM-02 |
| 6 | 啟用 / 停用 | 已有設定的工具可切換
status(enabled/disabled);停用前查詢引用任務數(D6
軟提醒,不擋) |
工具卡片 overflow menu | UC-TPM-03 |
| 7 | 重置金鑰 | 清空該工具設定的加密憑證,需重新輸入才能再用 | 工具卡片 overflow menu(僅已設定才顯示) | UC-TPM-04 |
| 8 | 部署前提說明(FR-057) | 有 setup_guide 的工具卡片 overflow menu
出現「部署前提說明」,開 Dialog 渲染 markdown(前提說明 +
目標主機準備腳本),並提供「複製腳本」一鍵抽取 fenced code block
合併純文字複製 |
工具卡片 overflow menu → Dialog | §5 |
UC(§2)展開本頁所有具實質後端寫入/呼叫邏輯的功能:新增/編輯設定(4,UC-TPM-01)、測試連線(5,UC-TPM-02)、停用(6,UC-TPM-03)、重置金鑰(7,UC-TPM-04)。純顯示/前端過濾類(1 目錄清單、2 搜尋、3 灰化、8 部署前提說明)於 §5 說明。
2. Use Case
角色速覽:見 §1。
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-TPM-01 新增 / 編輯工具連線設定
| 項目 | 內容 |
|---|---|
| 角色 | 租戶 admin(過渡期=帳號 super_admin) |
| 前置條件 | 該工具目錄項 status==='available'(非
coming_soon) |
| 產出 / 後置條件 | 新增:config.tenant_detection_tool_configs
新增一列;編輯:更新既有列(secret 欄位留空=不動既有密文) |
流程:開 Dialog(依 config_field_schema 動態渲染)→
必填欄位未填且已 touched → 顯示「{欄位名} 為必填」→ 送出時 secret
欄位分流進 credentials(有值才帶)、其餘進
field_values → POST(新增)或
PUT(編輯)→ 成功關閉 Dialog 並重整清單。
UC-TPM-02 測試連線
| 項目 | 內容 |
|---|---|
| 角色 | 租戶 admin |
| 前置條件 | 該工具已有設定(config 非 null)且已存檔 |
| 產出 / 後置條件 | 無寫入設定內容;僅更新 last_tested_at /
last_test_result |
流程:按「測試連線」→(SSH 型工具如
OpenSCAP:先彈輸入框要求填一或多台測試主機,因租戶層憑證不含 host,見
§12)→ BE 解密該租戶已存憑證 →
挑一台本租戶啟用中、capabilities 含
detection_scan 的 Agent → 透過既有 FR-039 mTLS 通道推送
POST /detection/probe(帶解密後憑證,SSH 型另帶
host)→ Agent 用與真實掃描相同的連線方式(OpenVAS 為
python-gvm GMP over TLS;OpenSCAP 為 SSH 連線 + 認證 +
oscap 指令存在性 + SCAP content 存在性四段檢查)實連驗證 →
結果同步回傳 → 記錄
last_tested_at/last_test_result。三種失敗原因分開呈現:①未設定憑證
②本租戶無可用 detection_scan Agent ③Agent
連得到但工具端連不通/帳密錯(訊息由 Agent
回傳原樣顯示)。多台測試(FR-057 T-2.3-fix):FE
拆開並發,每台各發一次 POST test-connection(body 帶單台
host),BE 逐台呼叫 probe 並各自回傳,FE
逐列即時更新狀態(testing/ok/fail),不互等。
UC-TPM-03 停用工具設定
| 項目 | 內容 |
|---|---|
| 角色 | 租戶 admin |
| 前置條件 | 該工具已有設定且目前為 enabled |
| 產出 / 後置條件 | status 改為
disabled;停用後任務配置頁該工具仍列在下拉(下拉來源未过滤
status,見 §12 坑 3) |
流程:按「停用」→ 先查詢
count_referencing_tasks(該工具目錄項被幾個
job_execution_detection_tools 綁定引用)→ 引用數 >0 時
confirm 訊息加註「有 {count} 個任務正使用此工具設定,仍要停用嗎?」,=0
時純確認訊息 → 不論引用數多少,確認後一律直接停用(D6
軟提醒,非阻擋)→ PUT 更新 status。
UC-TPM-04 重置金鑰
| 項目 | 內容 |
|---|---|
| 角色 | 租戶 admin |
| 前置條件 | 該工具已有設定(config 非 null) |
| 產出 / 後置條件 | credentials_encrypted 清空為
NULL;field_values(非機敏欄位)不受影響 |
流程:按「重置金鑰」→ confirm(「確定要重置 {name}
的憑證嗎?重置後需重新設定才能使用。」)→ 確認 →
POST /detection-tools/configs/{uid}/reset →
成功後重整清單,該工具的機敏欄位回到未設定狀態(下次開 Dialog 不再顯示
•••• 遮罩)。
3. 權限矩陣
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 進入本頁 | ui_routes web-menu 可見性 |
N/A(僅 JWT) | — |
| 讀工具目錄 / 讀租戶設定清單 | 無 | 僅 @jwt_required() |
api/detection_tools/routes/detection_tool_route.py::DetectionToolsRoute
/ TenantDetectionToolConfigsRoute |
| 新增 / 編輯 / 重置金鑰 | 無額外前端角色判斷 | ⚠️ 帳號層
require_super_admin()(過渡期)——非租戶層角色,是帳號是否為系統層
super_admin |
app/detection_tools/service/detection_tool_service.py::create_tenant_config
/ update_tenant_config /
reset_tenant_config_key |
| 測試連線 / 停用 / 查引用數 | 無 | 僅 @jwt_required()(無角色守門) |
test_connection /
update_tenant_config(停用走同一 update 端點)/
count_referencing_tasks |
⚠️ 已知過渡設計(非遺漏):新增/編輯/重置走帳號層
require_super_admin(),是因為本模組的租戶層 capability(detection-tools-manage.*)尚未 seed,過渡期先用帳號層守門頂著(見detection_tool_service.py:73-75註解引用 D6 附註 + implementation-plan Task 3 Step 9)。這與本群其餘管理頁「僅 JWT 無角色守門」的既有基調不同——本頁反而是「守太緊」而非「沒守」,日後 capability seed 完成後應改為租戶層權限模型,勿誤以為現況是終態設計。測試連線 / 停用兩個動作目前完全無角色檢查,只靠 RBAC 選單擋入口。
4. 狀態機與前置條件
本頁無輪次 / 階段狀態機,僅有工具目錄與租戶設定各自獨立的狀態:
| 條件 | 效果 | 出處 |
|---|---|---|
detection_tools.status === 'coming_soon' |
工具卡片灰化(opacity-60),動作按鈕全部隱藏(v-if="tool.status !== 'coming_soon'") |
ToolPluginManage.vue:377,395 |
detection_tools.status === 'available' |
才可新增設定(create_tenant_config 檢查,否則
DETECTION_TOOL_NOT_AVAILABLE) |
detection_tool_service.py:76-78 |
tenant_detection_tool_configs.status |
enabled:可被任務綁定使用;disabled:下拉未過濾,仍可能被選中(見
§12 坑 3) |
— |
Dialog:currTool.config 存在 |
「設定」按鈕文案變為「編輯」;onOpenConfigDialog 用既有
field_values/has_credentials
預填表單(無值則帶 field.default,FR-057) |
ToolPluginManage.vue:95-106 |
欄位 field.secret && hasExistingValue |
該欄位 placeholder 顯示「••••(已設定,留空不變更)」,不回顯明文 | DetectionConfigField.vue:33-38 |
欄位 field.condition(FR-057) |
該欄位只在「另一欄位(condition.field)目前值等於
condition.value」時才顯示;不可見時跳過必填驗證(不可見的分支不該擋送出) |
DetectionConfigField.vue:20-31、ToolPluginManage.vue::isFieldVisible:143-147 |
tool.connection_type === 'SSH'(FR-057) |
按「測試連線」不直接打 API,先彈輸入測試主機的 Dialog(見 UC-TPM-02) | ToolPluginManage.vue::onTestConnectionCard:211-221 |
5. UI 設計
版面骨架(Card grid + 設定 Dialog):
📸 實機截圖待補:工具卡片 grid(含 OpenSCAP)、設定 Dialog(含 secret 遮罩 + textarea 私鑰欄 + auth_method 條件顯示)、測試連線成功/失敗 toast、部署前提說明 Dialog。
狀態呈現:每張工具卡片右上角狀態 Tag——coming_soon
顯示「敬請期待」(secondary);有設定則依 config.status
顯示綠色「啟用」或紅色「停用」。設定 Dialog
標題固定為「啟用檢測工具」(t('lang.plugin_manage.active_plugin'),即使是編輯既有設定也沿用此標題,屬既有文案非新坑)。無
socket;所有動作後重打 fetchAll()
重新整理整頁資料(未做局部 state 更新)。
卡片動作配置(FR-057 改版):常用動作(設定 /
編輯、測試連線)留在卡面;次要 / 危險動作(部署前提說明、啟用 /
停用、重置金鑰)收進卡片右下角 overflow menu(pi-ellipsis-v
按鈕開 PrimeVue Menu
popup),避免多按鈕擠壓換行跑版(ToolPluginManage.vue::getCardMenuItems:320-350)。
部署前提說明
Dialog(FR-057,setup_guide
欄位驅動):工具目錄項有
setup_guide(TEXT,markdown)時,overflow menu
出現「部署前提說明」項,開 Dialog 用 marked 解析 markdown
後經 DOMPurify.sanitize() 才 v-html
渲染(信任來源仍過濾,防禦性一致);Dialog
內另有「複製腳本」按鈕,用正則
/```[a-zA-Z]*\n([\s\S]*?)```/g 抓出所有 fenced code
block(不含前後說明文字)合併成純文字寫入剪貼簿(navigator.clipboard.writeText),供使用者直接貼到目標主機終端機執行。出處:ToolPluginManage.vue::renderSetupGuide:20-23、extractScript:27-31、copySetupScript:33-43。
6. API 規格
Envelope:成功 {"code": 1, "data": …}、失敗
{"code": 0, "msg": "…"}(return_response)。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 目錄 | GET /detection-tools |
工具目錄清單(僅回平台層啟用者) | §6.2 |
| 目錄 | GET /detection-tools/{uid} |
單筆工具目錄項(本頁未直接用,供他頁/除錯) | GAI-SD-02 |
| 目錄 | GET /detection-tools/{uid}/param-schema |
取工具當前生效版本的任務參數 schema(本頁不用,供 任務配置頁 動態渲染掃描參數) | GAI-SD-02 |
| 租戶設定 | GET /detection-tools/configs |
本租戶所有工具設定清單 | §6.2 |
| 租戶設定 | POST /detection-tools/configs |
新增租戶工具設定(含加密憑證) | §6.3 |
| 租戶設定 | PUT /detection-tools/configs/{uid} |
更新租戶工具設定(含停用切換) | §6.3 |
| 租戶設定 | POST /detection-tools/configs/{uid}/reset |
重置憑證(清空為 NULL) | §6.4 |
| 租戶設定 | POST
/detection-tools/configs/{uid}/test-connection |
測試連線(雲端直推 Agent) | §6.4 |
| 租戶設定 | GET
/detection-tools/configs/{uid}/referencing-tasks-count |
停用/重置前查引用任務數(D6 軟提醒) | §6.4 |
任務執行相關端點(
/detection-tools/jobs/{job_uid}/execute、.../executions)屬 任務執行抽屜 功能,非本頁呼叫,列在該頁 spec。
6.2 工具目錄 / 租戶設定清單
[GET] /detection-tools
無 query。Response
data[](DetectionToolResponse):
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid / code / name / description | string | 工具識別與顯示資訊 |
| connection_type | string | API / CLI /
SSH(FR-057 新增;CLI
尚未實際使用,見 §12) |
| config_field_schema | array | 動態表單欄位定義:[{key, type, label, secret, required, options?, condition?, default?}]——type
為
text/password/number/select/textarea/boolean/select_or_text(後三者
FR-057 新增,見下方型態說明) |
| setup_guide | string|null | (FR-057 新增)部署前提說明 + 目標主機準備腳本,markdown 格式;FE
渲染成 Dialog + 一鍵複製腳本(見 §5)。null
或空字串=該工具不顯示「部署前提說明」選單項 |
| status | string | available / coming_soon |
| enabled | bool | 平台層總開關 |
config_field_schema 各欄位屬性:
| 屬性 | 型別 | 說明 |
|---|---|---|
| key / label / type | string | 欄位鍵 / 顯示標籤 / 渲染型態 |
| required | bool | 是否必填——不受 condition
隱藏影響時才生效:欄位因 condition
不符而不可見時一律跳過必填驗證(不可見分支不該擋送出) |
| secret | bool | true 進
credentials(加密存放);false 進
field_values |
| options | array|undefined | 僅 select/select_or_text
用:[{label, value}] 下拉選項 |
| condition | object|undefined | (FR-057 新增){field, value}——此欄只在「另一欄位
field 目前值等於 value」時才顯示(如
private_key 只在 auth_method==='private_key'
時出現) |
| default | any|undefined | (FR-057 新增)欄位預設值,開 Dialog 時若無既有值則帶入(如
ssh_port 預設 22) |
型態渲染對照(DetectionConfigField.vue):text→InputText、password→Password(toggleMask)、number→InputNumber、select→Dropdown、textarea→Textarea(autoResize,OpenSCAP
私鑰欄用)、boolean→InputSwitch、select_or_text→PrimeVue
editable Dropdown(可選常用選項、也可直接輸入清單外的自由字串,如
profile 欄的 xccdf profile id)。
出處:api/detection_tools/serializers/detection_tool.py:4-14(DetectionToolResponse,含
setup_guide = fields.String(allow_none=True))、route
DetectionToolsRoute、service
detection_tool_service.py::list_tools(get_tools(enabled=True))。現況種子資料(DEV
實查 config.detection_tools,取自
scripts/sql/2026-07-28-fr057-1-openscap-seed.sql):
openvas(API,available,4 欄位:base_url/username/password(secret)/port)openscap(SSH,available,6 欄位:username(text)/auth_method(select: password|private_key)/password(password 型, secret, condition=auth_method=password)/private_key(textarea 型, secret, condition=auth_method=private_key)/ssh_port(number, default 22)/use_sudo(boolean, default true);password/private_key皆required=true——條件必填語意,配合condition由 FE 判斷是否套用驗證)nessus(coming_soon,空 schema)、sonarqube(coming_soon,空 schema)
[GET] /detection-tools/configs
無 query。Response
data[](TenantDetectionToolConfigResponse):
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | string | 設定識別碼 |
| detection_tool_id | int | → config.detection_tools.id |
| detection_tool_code | string|null | 服務層補算(list_tenant_configs 依
detection_tool_id 對照目錄),供 FE 依 code
合併進工具卡片 |
| field_values | object | 非機敏欄位值(如 base_url) |
| status | string | enabled / disabled |
| has_credentials | bool | 是否已設定機敏欄位——絕不回傳憑證明文/密文,只回布林 |
| last_tested_at / last_test_result | datetime|null / string|null | 最近一次測試連線時間與結果 |
出處:api/detection_tools/serializers/detection_tool.py:17-40(TenantDetectionToolConfigResponse.dump_entity
手動補 has_credentials)、service
detection_tool_service.py:58-69::list_tenant_configs。FE
合併邏輯:ToolPluginManage.vue::tools computed:57-67(依
detection_tool_code === tool.code 配對)。
6.3 新增 / 更新設定
[POST] /detection-tools/configs
Request:
{
"tool_uid": "<detection_tools uid>",
"credentials": {"password": "..."},
"field_values": {"base_url": "https://...", "username": "...", "port": 9390},
"status": "enabled"
}| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| tool_uid | string | 是 | 目標工具目錄項 |
| credentials | object | 否 | 機敏欄位(field.secret===true)→ 加密後存
credentials_encrypted;FE 全部留空則整個 key 省略 |
| field_values | object | 否 | 非機敏欄位(如 base_url) |
| status | string | 否 | 預設 disabled |
工具目錄項 status !== 'available' →
DETECTION_TOOLS_400002(DETECTION_TOOL_NOT_AVAILABLE)。出處:api/detection_tools/serializers/detection_tool.py:43-47(TenantDetectionToolConfigCreateRequest)、route
TenantDetectionToolConfigsRoute.post、service
detection_tool_service.py:71-90::create_tenant_config。
[PUT] /detection-tools/configs/{uid}
Request(全部選填,partial-update
語意——None 欄位不更新):
| 欄位 | 型別 | 說明 |
|---|---|---|
| credentials | object | 有值才加密覆寫;FE 不帶(機敏欄位皆留空)→ None → repo
update()
skip,保留既有密文(幽靈覆寫防護) |
| field_values | object | 覆寫非機敏欄位 |
| status | string | 單獨送 {status: "disabled"}
即可只切換啟用狀態(本頁「停用」按鈕即此用法) |
出處:api/detection_tools/serializers/detection_tool.py:50-53(TenantDetectionToolConfigUpdateRequest)、service
detection_tool_service.py:92-105::update_tenant_config。
FE
送出邏輯(ToolPluginManage.vue::buildPayload:121-140):遍歷
config_field_schema,先依
isFieldVisible()(condition
判斷)跳過不可見欄位(FR-057,避免未選分支殘留值送出),值為
null/undefined/空字串一律跳過(不塞進
payload);secret 欄位分流進
credentials,其餘進
field_values;credentials 物件若無任何 key
則整個欄位設為 undefined(axios
序列化時省略),確保「全部留空=不動既有密文」。
6.4 重置 / 測試連線 / 引用計數
[POST] /detection-tools/configs/{uid}/reset
無 body。Response
data:{"success": true}。清空
credentials_encrypted 為 NULL(專用
clear_credentials 方法,區別於 update() 的
None=skip 語意——重置要的正是清空,不能被 skip
邏輯擋住)。出處:service
detection_tool_service.py:107-112::reset_tenant_config_key。
[POST] /detection-tools/configs/{uid}/test-connection
Request(全部選填,FR-057 新增):
| 欄位 | 型別 | 說明 |
|---|---|---|
| host | string|undefined | SSH 型工具(如 OpenSCAP)指定測試主機——租戶層憑證不含 host(D1 決策),probe 需另外指定。可填多台(逗號/空白/分號分隔),BE 逐台各發一次 probe 並彙總(全部成功才算成功,訊息逐台列出);API 型工具(OpenVAS)不需帶此欄 |
Response
data:{"success": bool, "message": string}。
三種失敗訊息(皆 success=false,非 HTTP 錯誤):
| 情境 | message(i18n key) |
|---|---|
| 該設定未存憑證 | detection_probe_no_credentials |
本租戶無 detection_scan capability 的 Agent |
detection_probe_no_agent |
| Agent 連得到但工具端連不通/帳密錯 | Agent 回傳的原始訊息(透傳)——OpenSCAP 分四段(連線失敗 / 認證失敗 / 未安裝 openscap-scanner / 缺少 SCAP content),任一段失敗即回該段訊息不續探 |
出處:route
TenantDetectionToolConfigTestConnectionRoute、service
detection_tool_service.py::test_connection:116-(host
參數解析與逐台 probe 彙總邏輯,FR-057
擴充);憑證合併邏輯(field_values + 解密後的
credentials)於 :143-144;實際 mTLS 直推見
infra/detection_tools/connector/agent_probe_client.py(PROBE_PATH = "/detection/probe")。
[GET] /detection-tools/configs/{uid}/referencing-tasks-count
無 query。Response data:{"count": int}——D6
軟提醒,不擋停用/重置動作,僅供 FE
組確認訊息文案。出處:service
detection_tool_service.py:144-155::count_referencing_tasks(解出
tenant_config → detection_tool_id 後查
job_execution_detection_tools 引用數)。
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/plugin/ToolPluginManage.vue |
主檢視(566 行):目錄+設定合併、搜尋、設定
Dialog、啟用/停用、測試連線(FR-057:SSH 型工具多台測試主機輸入 +
逐台結果彙總)、重置金鑰、部署前提說明 Dialog +
複製腳本(FR-057,setup_guide 驅動)、卡片 overflow menu
收納次要動作 |
src/components/detection-tools/DetectionConfigField.vue |
動態欄位渲染元件(123 行):依 field.type 渲染
InputText/Password/InputNumber/Dropdown/Textarea/InputSwitch/editable
Dropdown(後三者 FR-057 新增,對應
textarea/boolean/select_or_text),secret
遮罩邏輯 + condition
依賴顯示(FR-057:visible computed
判斷另一欄位值,不可見欄位 showError 恆 false
跳過驗證) |
src/service/DetectionToolService.js |
API 包裝(70 行):listTools / listConfigs
/ createConfig / updateConfig /
testConnection / getReferencingTaskCount /
resetConfig / getParamSchema |
src/config/router/index.js:614-627 |
route tool-plugin-manage,path
/plugin/tool-plugin-manage |
src/config/api/api.js:341-347 |
DETECTION_TOOLS / DETECTION_TOOL_CONFIGS /
DETECTION_TOOL_TEST_CONNECTION /
DETECTION_TOOL_REF_COUNT /
DETECTION_TOOL_RESET /
DETECTION_TOOL_PARAM_SCHEMA 常數 |
src/config/locales/i18n/{zh-tw,en}/pages.json(plugin_manage
namespace) |
頁面
i18n:title/setup/coming_soon/field_required/secret_placeholder/reset_confirm/disable_with_refs
等 + 各工具說明(openvas_desc 等) |
src/config/locales/i18n/{zh-tw,en}/menu.json |
選單標題「檢測工具管理」——選單本身已完全啟用,非停用狀態(動態依帳號
permissions 顯示,非硬編停用清單) |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 工具目錄 | api/detection_tools/routes/detection_tool_route.py::DetectionToolsRoute(GET)/
DetectionToolDetailRoute |
app/detection_tools/service/detection_tool_service.py::list_tools
/ get_tool |
domain/detection_tools/service/detection_tool_domain_service.py
→
infra/detection_tools/repository/detection_tool_repo_impl.py |
| 租戶設定 CRUD | TenantDetectionToolConfigsRoute(GET/POST)/
TenantDetectionToolConfigDetailRoute(PUT) |
DetectionToolService.list_tenant_configs /
create_tenant_config /
update_tenant_config(皆 @transaction) |
domain/detection_tools/service/tenant_detection_tool_config_domain_service.py
→
infra/detection_tools/repository/tenant_detection_tool_config_repo_impl.py |
| 重置金鑰 | TenantDetectionToolConfigResetRoute |
DetectionToolService.reset_tenant_config_key |
同上 repo clear_credentials |
| 測試連線 | TenantDetectionToolConfigTestConnectionRoute |
DetectionToolService.test_connection |
infra/detection_tools/connector/agent_probe_client.py::AgentProbeClient(mTLS
+ 短效 JWT,直推 Agent) |
| 引用計數 | TenantDetectionToolConfigRefCountRoute |
DetectionToolService.count_referencing_tasks |
domain/detection_tools/service/job_execution_detection_tool_domain_service.py |
| 參數 schema | DetectionToolParamSchemaRoute(本頁不用,任務配置頁用) |
DetectionToolService.get_param_schema |
domain/detection_tools/service/detection_tool_param_schema_domain_service.py |
DDD 提醒:route 不碰 DB、app service 全數
@transaction、domain service 不依賴 infra、repo
遵循既有分層。唯一偏離常態的是新增/編輯/重置走帳號層
require_super_admin()(過渡期設計,見 §3
說明),測試連線/停用則完全無角色守門——兩者是不同方向的偏離,改動時務必分開看待。
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
| 表 | 讀/寫 | 說明 | 欄位詳述 |
|---|---|---|---|
| config.detection_tools | 讀 | 平台工具目錄(種子資料,本頁不寫) | §9.3 |
| config.tenant_detection_tool_configs | 寫 | 租戶工具連線設定(加密憑證 + 非機敏欄位 + 狀態) | §9.3 |
| config.detection_tool_param_schemas | 讀(間接,供 任務配置頁) | 工具任務參數 schema(版本化,is_current
標記生效版) |
§9.3 |
| config.job_execution_detection_tools | 讀(供引用計數) | 任務↔︎工具綁定(本頁不寫,寫入在 任務配置頁) | 任務配置頁 §9.3 |
9.3 核心表欄位(取自 DEV DB dump)
config.detection_tools — 平台工具目錄
| 欄位 | 型別 | 說明 |
|---|---|---|
| id | bigint | 內部主鍵(config.job_execution_detection_tools.detection_tool_id
FK 目標;Agent factory _TOOL_ID_TO_CODE 固定映射
1=openvas, 2=nessus, 3=sonarqube, 4=openscap,新增工具必須依
seed 順序自然拿到對齊的 id,見 FR-057 migration 註解) |
| uid | varchar(36) | 對外識別碼 |
| code | varchar(50) | 工具代碼(openvas/nessus/sonarqube/openscap),FE
用來比對合併租戶設定 |
| name / description | varchar / text | 顯示名稱 / 說明 |
| connection_type | varchar(20) | API / CLI / SSH(FR-057
新增,決定 Agent executor 走哪條,DB comment 已更新) |
| config_field_schema | jsonb | 動態設定表單欄位定義:[{key, type, label, secret, required, options?, condition?, default?}](condition/default
FR-057 新增) |
| setup_guide | text|null | (FR-057 新增)部署前提說明 + 目標主機準備腳本,markdown |
| status | varchar(20) | available / coming_soon |
| enabled | boolean | 平台層總開關 |
config.tenant_detection_tool_configs — 租戶工具連線設定
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | varchar(36) | 對外識別碼 |
| tenant_id | bigint | 租戶(RLS 隔離) |
| detection_tool_id | bigint | →
config.detection_tools(uq_tdtc_tenant_tool
唯一約束:每租戶每工具僅一筆設定) |
| credentials_encrypted | text|null | 機敏欄位加密後 JSON(對稱加密,金鑰
DETECTION_TOOL_ENCRYPTION_KEY 環境變數,不進版控) |
| field_values | jsonb | 非機敏欄位值(如 base_url) |
| status | varchar(20) | enabled / disabled(預設
disabled) |
| last_tested_at | timestamp|null | 最近一次測試連線時間 |
| last_test_result | varchar(20)|null | success / fail |
config.detection_tool_param_schemas — 工具任務參數 schema(版本化)
| 欄位 | 型別 | 說明 |
|---|---|---|
| detection_tool_id | bigint | →
config.detection_tools(uq_dtps_tool_version
唯一約束:(detection_tool_id, version)) |
| version | int | 版本號,遞增(如 OpenVAS v1→v2 新增 port_list_id
欄位) |
| param_schema | jsonb | 任務掃描參數欄位定義(供 任務配置頁 動態渲染) |
| is_current | boolean | 是否為當前生效版本(get_current_schema 依此篩選) |
與
config_field_schema的差異:detection_tools.config_field_schema是連線設定欄位(本頁用,如帳密/主機),detection_tool_param_schemas.param_schema是任務掃描參數欄位(任務配置頁用,如 hosts/timeout_sec)——兩者是不同層次的 schema,命名相近容易混淆。
10. 頁面邏輯與資料對應
載入時序:onMounted 平行觸發
listTools() + listConfigs(),FE 端依
detection_tool_code === tool.code 合併成 tools
computed(工具卡片資料來源)。
關鍵欄位對應(畫面 ↔︎ API):
| 畫面元素 | FE state | API 欄位 |
|---|---|---|
| 工具卡片清單 | tools(computed,目錄+設定合併) |
GET /detection-tools +
GET /detection-tools/configs |
| 設定 Dialog 欄位 | form[field.key] |
依 tool.config_field_schema 動態產生,預填
tool.config.field_values |
| secret 欄位遮罩 | DetectionConfigField 的 hasExistingValue
prop |
config.has_credentials |
| 狀態 Tag | 直接綁定 | tool.config?.status(無設定 = 不顯示) |
| 測試連線結果 | toast | test-connection 回傳
{success, message} |
儲存流程:onSaveConfig 先做 client
端必填檢查(略過已有憑證的 secret 欄位)→ buildPayload()
分流 credentials/field_values →建立走 POST、既有走 PUT → 成功後關閉
Dialog + fetchAll() 整頁重新整理(非局部更新)。
錯誤對應:BE error envelope → toast
顯示;本頁常見碼:DETECTION_TOOLS_400002(工具非 available
不可新增設定)、DETECTION_TOOLS_404002(設定不存在)。測試連線刻意不用例外,而是回
{success:false, message},避免整頁被連線失敗中斷。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 通知 | 無——本頁不觸發、也不消費任何通知 |
| Socket | 無 socket / 輪詢;動作後皆整頁 fetchAll() |
| mTLS / Agent 直推 | 測試連線走 FR-039 既有 mTLS
通道(AgentProbeClient,mode=full 時 mTLS
client 憑證 + 短效 JWT;mode=none 裸 HTTP
demo),與真實掃描派工共用同一認證機制;OpenSCAP probe 走同一通道,僅
payload 多帶 host |
| 憑證加密 | DETECTION_TOOL_ENCRYPTION_KEY(BE
部署環境變數,非資料庫值,不進版控)——對稱加密租戶填寫的機敏欄位(含
OpenSCAP 的 password/private_key);api_log
對本模組請求 body 遮罩憑證欄位,不落明文(D9,e2eb1c2c
修正) |
| jedi-* 套件 | 無直接依賴(本模組為 FR-056 全新自研,未借用既有 jedi-* 套件) |
| 系統參數 | DETECTION_TOOL_ENCRYPTION_KEY(環境變數,非 DB feature
flag) |
12. 邊界情況與已知坑
- 新增/編輯/重置走帳號層
require_super_admin(),非租戶層權限:本模組租戶層 capability(detection-tools-manage.*)尚未 seed,過渡期直接卡帳號是否為系統層 super_admin——這與「租戶 admin」的直覺角色定位不完全一致(見 §3),日後 capability seed 完成需改為租戶層權限模型。 - 測試連線 / 停用完全無角色守門:僅
@jwt_required(),任何登入者理論上都能對已知 config uid 呼叫測試連線或停用——與新增/編輯的「守太緊」形成不一致的守門粒度,改動時勿混為一談。 - 停用後任務配置頁下拉未過濾
status:config.tenant_detection_tool_configs.status='disabled'後,任務配置頁的工具下拉來源是GET /detection-tools(工具目錄,非租戶設定),本身不檢查租戶設定狀態——理論上使用者仍可能選到一個已停用設定的工具,實際派工時會因缺憑證(_resolve_credentials找不到enabled設定)失敗。此為現況行為,未做前端過濾。 config_field_schema(連線設定)與param_schema(任務參數)是兩層不同 schema:命名相近但用途、消費頁面都不同(見 §9.3 附註),維護時勿混淆——改一邊不會影響另一邊。- 憑證合併邏輯:測試連線時
field_values(如base_url)與解密後的credentials(如password)需合併才是完整連線資訊(test_connection:143-144),單看其中一邊資訊不全——早期版本曾漏合併(b26f83f1修正)。 credentials全空時整個欄位省略,非傳空物件:FEbuildPayload()若無任何 secret 欄位有值,credentials設為undefined(非{})——若改成送空物件{},BEcreds = payload.get("credentials")會判定為 truthy(非 None)而觸發加密覆寫,把既有密文洗成加密後的空字串,是需要留意的坑(現況實作正確,記錄供未來重構參考)。coming_soon工具無法被選為連線設定或任務綁定:create_tenant_config明確擋status != 'available'(DETECTION_TOOLS_400002),FE 也把按鈕全部隱藏——nessus/sonarqube目前只是目錄佔位,尚無 Agent connector 實作。- OpenSCAP 是 connector
架構第三種連線型態(FR-057):
connection_type='SSH',與 OpenVAS 的API型態行事邏輯完全不同——OpenVAS 走 python-gvm GMP over TLS 對接遠端服務;OpenSCAP 純 CLI 無 daemon,connector 直接 SSH 登入目標主機在其本機執行oscap指令。另有CLI型態值(本機執行、不經 SSH)已定義於 comment 但尚未有任何工具實際使用,屬未來擴充預留。 - OpenSCAP
憑證=租戶層一組共用稽核帳號:所有目標主機須用同名帳號(
config_field_schema.username)+ 同一把私鑰/密碼登入(Tenable 業界慣例),非每台各自帳密——host inventory(每台各自憑證)是明列的未來範圍,本版不支援。
13. 開發與驗證
- 跑起來:BE
python main_socketio.py(port 8000,log 在log/app.log);FE 在compliance-manager-fe/起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload) - 測試帳號:dev 環境系統層 super_admin 帳號(密碼見
.env/ 部署文件)——新增/編輯/重置需此權限 - 導航路徑:登入 → 合規稽核 →
「檢測工具管理」(
/plugin/tool-plugin-manage) - 前置資料:
config.detection_tools需已 seed(scripts/sql/2026-07-26-fr056-1-detection-tools-config-schema.sql+scripts/sql/2026-07-28-fr057-1-openscap-seed.sql);測試連線需本租戶已部署具detection_scancapability 的 Agent(見 檔案 Agent 管理 §12 坑 10——capabilities 欄位目前僅能直接改 DB 設定);測試 OpenSCAP 另需目標主機已裝openscap-scanner+ SSG content、建稽核帳號並佈公鑰(見setup_guide或 使用手冊 SSH 遠端掃描部署說明) - E2E:
compliance-manager-test/repo(Cucumber + Playwright);以檢測工具/detection-tool/tool-plugin搜尋 - 相關文件:完整使用手冊見
docs/features/FR-056-2607-detection-tool-integration/user-manual.html(已擴充涵蓋 OpenSCAP);任務綁定與掃描參數見 任務配置與啟動;執行歷史與重新執行/取消機制見 任務執行抽屜;Agent capabilities 設定見 檔案 Agent 管理;FR-057 設計決策見docs/features/FR-057-2607-openscap-ssh-connector/design.md