FR-057 OpenSCAP 掃描工具接入(SSH 連線型態)— 設計文件

狀態:設計定案(D1–D7 已拍板)|建立日期:2026-07-28|FR-056 檢測工具整合平台續作 討論稿(含流程圖):discussion.html

變更紀錄

日期 變更 對應
2026-07-28 初版設計定案,D1–D7 全數拍板 FR-057 母案
2026-07-29 D3 實作澄清:官方 oscap-ssh 腳本只支援「本機 content 推送到遠端」,與 D3「用目標自帶 SSG」矛盾(T-2.2 實作時發現)。定案:connector 自組 SSH 指令直接在目標上執行 oscap 引用目標本地 content(oscap-ssh 本身僅 ~200 行 shell wrapper,自組成本低;取消/逾時本就 connector 自管),report 寫遠端 mktemp 暫存、拉回後清理。D3 核心價值(目標側 content、無平台版本矩陣)不變。 T-2.2 / D3

1. 需求背景與目標

FR-056 檢測工具整合平台第一版只接了 OpenVAS(API 型)。本案新增第二個工具 OpenSCAP——開源組態合規稽核工具(CIS / STIG benchmark),並藉此開出 connector 架構的第三種連線型態 SSH(既有 API / CLI 之外)。

為什麼是 SSH 遠端掃描(設計前提,已查證定案)

  • OpenSCAP(oscap)是純 CLI,無 server API、無 daemon。組態稽核要讀目標主機系統內部(設定檔 / 套件庫 / sysctl),必須以登入身分在目標 OS 上執行——這是物理限制,全業界一致。
  • 官方遠端模式是 oscap-ssh:發起端 SSH 登入目標 → 推送 content → 在目標上執行目標自己的 oscap → 把報告拉回。Red Hat Satellite / Foreman 大規模採用同一模式。
  • Agent 維持 Docker 形態不變:Agent 是掃描發起端(站點調度器),container 內只需 openssh-client + oscap-ssh 腳本;真正的掃描引擎(openscap-scanner 套件)在各目標主機上。
  • Nessus / Qualys 能「零安裝」是因為自造檢查引擎(商業核心資產);OpenSCAP 開源專案沒有這層,目標裝 openscap-scanner 是選用 OpenSCAP 的隨附條件(幾 MB CLI 工具、非常駐、不開 port)。

端到端流程

租戶設定 OpenSCAP(SSH 稽核帳號 + 金鑰/密碼,加密存放)
  → 任務設「檢測工具執行」選 OpenSCAP + 填 hosts/profile
  → 按「開始執行任務」
  → Agent 心跳領到派工(含解密憑證)
  → Agent 內 oscap-ssh 逐台登入目標主機執行掃描
  → 每台一份 HTML 報告拉回 Agent → 上傳 → 回報 result(多檔)
  → 雲端逐檔取回存 job_evidences(source=DETECTION_TOOL)
  → 通知負責人 → 依完成模式收尾

2. 決策定案(D1–D7)

# 決策 定案
D1 SSH 憑證放哪層 租戶工具設定層一組共用稽核帳號(方案 A)。業界標準做法——Tenable 官方《Credentialed Checks on Linux》明文:每台目標建同名專用掃描帳號。沿用 tenant_detection_tool_configs 加密鏈 + D9 派工下發,零新表零新機制。任務層帶憑證(明文落 DB)排除;host inventory 表(每台各自憑證)列未來,資料模型可平滑升級。
D2 認證方式 密碼 / SSH 私鑰二擇一,推薦金鑰(Tenable 同款建議:金鑰更安全、私鑰只存 scanner 端)。另設 use_sudo 布林——完整掃描需 root 級讀取,企業普遍禁 root 遠端登入,「一般帳號 + sudo 提權」是標準模式(oscap-ssh --sudo)。
D3 SCAP content 來源 用目標主機自帶的 SSGscap-security-guide 套件,/usr/share/xml/scap/ssg/content/),天然匹配該機 OS 版本。任務參數 = content 路徑(預設慣例路徑可改)+ profile(常用 CIS/STIG 下拉 + 自由輸入)。平台統一管理 content 列未來(版本矩陣維護成本高、錯配風險)。實作註(2026-07-29):不經 oscap-ssh 官方腳本(其語意為本機 content 推送,與本決策矛盾),connector 自組 SSH 指令在目標上執行 oscap 引用目標本地 content,詳見變更紀錄。
D4 證據格式 HTML 原樣上傳oscap 官方人讀格式,無原生 PDF)。summary 從 stdout 規則統計解析(pass/fail/notapplicable)。不轉 PDF(LibreOffice 轉複雜 HTML 排版易爛);ARF XML 結構化 findings 留未來 FR(同 FR-056 D4 邏輯)。
D5 多目標處理 逐台掃、每台一個證據檔(檔名含主機名),summary 加總。不硬拼單一 HTML。⚠️ 牽動回收鏈:現況 result_ref.upload_uid 是單數,需擴成多檔(見 §5 FR-057.3)。
D6 部署前提呈現 設定頁內建前提說明 + 一鍵複製目標主機準備腳本(裝 openscap-scanner+scap-security-guide、建稽核帳號、佈公鑰、sudoers),加 probe 實地檢查(SSH 上去驗 oscap / SSG content 存在性,缺什麼報什麼)。只寫手冊(被動)不採。
D7 不做範圍(第一版) Push 模式(目標自掃回報,Foreman 式)——與「按開始→即時派工」任務模型衝突;host inventory 表;ARF findings 解析;content 平台管理。

3. 現況接入點盤點(FR-056 已鋪好的軌道)

元件 現況 FR-057 動作
config.detection_tools OpenVAS(available) / Nessus / SonarQube(coming_soon);connection_type 註解只列 API/CLI seed 第 4 筆 openscapconnection_type='SSH',新型態值)+ config_field_schema
config.detection_tool_param_schemas OpenVAS 一筆(hosts/timeout_sec/...) seed OpenSCAP param schema
tenant_detection_tool_configs + Fernet 加密 完備 直接沿用(private_key 進 credentials 密文)
派工鏈(心跳夾帶 + 憑證解密下發) 完備(D9) 直接沿用
Agent DetectionConnector base run() / probe() / cancel_event 新增 openscap.py 實作
Agent factory _TOOL_ID_TO_CODE 1=openvas, 2=nessus, 3=sonarqube 固定映射 4: "openscap"(seed 順序須對齊)
Agent Dockerfile LibreOffice + curl openssh-client + openscap-utils(拿 oscap-ssh)
result 回收鏈 result_ref.upload_uid 單數detection_result_handler 取單檔寫 job_evidences 擴多檔upload_uids 陣列 + 逐檔迴圈(向下相容單數 key)
FE 設定頁 / 任務參數 schema 驅動動態渲染 欄位型態需擴:textarea(私鑰)、select_or_text(profile)、條件顯示(auth_method 切換)、說明區塊 + 複製腳本

4. 詳細設計

4.1 租戶設定欄位(config_field_schema)

key label type required secret 說明
username 稽核帳號 text 各目標主機同名帳號(業界慣例)
auth_method 認證方式 select(password/private_key) 驅動下兩欄條件顯示
password SSH 密碼 password 條件 auth_method=password 時必填
private_key SSH 私鑰 textarea 條件 auth_method=private_key 時必填(OpenSSH PEM)
ssh_port SSH 連接埠 number 預設 22
use_sudo 使用 sudo 提權 boolean 預設 true(完整掃描建議)

secret 欄位(password/private_key)進 credentials_encrypted 密文;其餘進 field_values

4.2 任務參數(param_schema)

key label type required 說明
hosts 掃描目標 text 逗號/空白分隔多台(同 OpenVAS 慣例,connector 邊界正規化)
content_path SCAP content 路徑 text 預設 /usr/share/xml/scap/ssg/content/(目標主機上的 SSG 慣例路徑),可填完整檔案路徑
profile 掃描 Profile select_or_text 下拉常用(CIS L1/L2 Server、STIG)+ 自由輸入 xccdf profile id
timeout_sec 逾時秒數 number 預設 3600,逐台計

content_path 語意:填目錄時 connector 依目標 OS 推斷 ssg-<os><ver>-ds.xml;填檔案路徑時直接用。第一版先實作「必填完整檔案路徑或用預設推斷」中較簡單的一種,plan 階段定案。

4.3 Agent connector(core/task_executor_connectors/openscap.py

  • run():解析 hosts → 逐台自組 SSH 指令執行 ssh <user>@<host> [sudo] oscap xccdf eval --profile <p> --report <遠端 mktemp 暫存> <目標上的 content 路徑> → 拉回 HTML 報告 bytes(scp/cat)→ 清理遠端暫存 → 解析 stdout 規則統計 → 回傳多檔 ScanResult(見 4.5)。不經 oscap-ssh 官方腳本(其語意為本機 content 推送,與 D3 矛盾,見變更紀錄 2026-07-29)。私鑰認證:憑證中的 private_key 寫入記憶體型暫存(/dev/shm 或 tmpfile 0600),掃完即刪,不落地持久化。
  • probe():SSH 連線 + 認證 → 遠端執行 command -v oscap + SSG content 路徑存在性檢查 → 缺什麼在錯誤訊息中明確分類(連不上 / 認證失敗 / 缺 oscap / 缺 content)。與 run() 共用連線參數解析(單一真相,同 OpenVAS 模式)。
  • 取消 / 逾時:SSH 指令是子行程——輪詢 cancel_event,取消時 terminate 子行程 raise ScanCancelledError;逾時逐台計時 raise TimeoutError。
  • oscap 退出碼0=全 pass、2=有 fail(掃描成功,報告有效)、1=執行錯誤。2 不可誤判為失敗。

4.4 exit code 與 summary

stdout 每條規則一行 Result: pass/fail/notapplicable/...,彙總成:

{"findings": <fail數>, "pass": n, "fail": n, "notapplicable": n, "error": n, "hosts_scanned": n}

解析失敗不拖垮派工(同 OpenVAS _parse_summary 原則:證據到手 summary 可缺)。

4.5 多檔證據回收鏈擴充(跨 agent + BE)

  • Agent task_executor:逐檔上傳 blob → result_ref{"upload_uid": x} 擴為 {"upload_uids": [{"uid": x, "filename": f}, ...]}保留單數 key 讀取相容(OpenVAS 路徑不動也不壞)。
  • BE detection_result_handler:讀 upload_uids(fallback upload_uid)逐檔 mTLS GET /blob/{uid} → 逐檔寫 job_evidences。單檔失敗記 warning 續處理其餘(部分成功優於全失敗)。
  • 檔名:OpenSCAP掃描報告_<host>_<日期>.html

4.6 部署前提(設定頁說明 + 準備腳本)

detection_toolssetup_guide 欄位(TEXT,markdown),FE 設定頁渲染 + 腳本區塊一鍵複製。腳本內容(範例,deb/rpm 雙版):

# 每台目標主機執行一次(Ubuntu/Debian)
sudo apt install -y openscap-scanner ssg-base ssg-debderived   # RHEL 系: openscap-scanner scap-security-guide
sudo useradd -m -s /bin/bash audit-scan
echo '<公鑰>' | sudo tee /home/audit-scan/.ssh/authorized_keys  # 目錄權限步驟略,見完整腳本
echo 'audit-scan ALL=(root) NOPASSWD: /usr/bin/oscap' | sudo tee /etc/sudoers.d/audit-scan

5. 拆分(3 子需求 × 8 子任務)

依賴鏈:FR-057.1(BE 地基)→ FR-057.2(Agent connector)∥ FR-057.3(多檔回收鏈),.2/.3 可並行(.3 不依賴 openscap connector 本身,用假多檔即可測)。

FR-057.1 BE:SSH 型態 + OpenSCAP 目錄與設定頁 — 依賴:無

# 子任務 驗收 依賴 Repo
T-1.1 migration:seed openscap(connection_type='SSH' + config_field_schema)+ param_schema seed + detection_tools.setup_guide 欄位與內容 三環境可套;設定頁清單出現 OpenSCAP(available) BE
T-1.2 FE 設定頁欄位型態擴充:textarea / 條件顯示(auth_method 切換)/ setup_guide 渲染 + 腳本複製 OpenSCAP 設定頁可完整填寫送出,憑證密文落庫 T-1.1 FE
T-1.3 FE 任務參數型態擴充:select_or_text(profile 下拉+自由輸入) 任務可選 OpenSCAP 並填參數發佈 T-1.1 FE

FR-057.2 Agent:OpenSCAP connector — 依賴:FR-057.1

# 子任務 驗收 依賴 Repo
T-2.1 Dockerfile(openssh-client + openscap-utils)+ factory 註冊 + connector 骨架(SSH 參數解析、私鑰暫存管理) image build 過;unit test 綠 T-1.1 evidence-agent
T-2.2 run():逐台 oscap-ssh + HTML 報告收取 + stdout summary + exit code 2 正確處理 + 取消/逾時 手塞派工 → 掃真實主機 → 報告回收全鏈通 T-2.1 evidence-agent
T-2.3 probe():連線/認證/oscap/SSG 四段檢查與錯誤分類 測試連線在四種缺件情境回清楚訊息 T-2.1 evidence-agent

FR-057.3 多檔證據回收鏈 — 依賴:FR-057.1(可與 .2 並行)

# 子任務 驗收 依賴 Repo
T-3.1 Agent:task_executor 多檔上傳 + result_ref.upload_uids(向下相容單數) 多檔派工回報結構正確;OpenVAS 單檔路徑迴歸綠 evidence-agent
T-3.2 BE:detection_result_handler 多檔迴圈取回 + 逐檔寫 job_evidences + 部分失敗續處理 多檔證據逐檔入池;單檔 fallback 迴歸綠 T-3.1 BE

6. 驗收(端到端)

  1. 管理員在檢測工具管理頁設定 OpenSCAP(金鑰認證)→ 測試連線通過(含前提檢查)
  2. 任務選 OpenSCAP、填 2 台 hosts + CIS profile → 開始執行 → 每台各一份 HTML 報告進證據池
  3. 任一台缺 openscap-scanner → probe/掃描回明確錯誤訊息(非神祕失敗)
  4. OpenVAS 既有全鏈迴歸不受影響(factory / result 單檔路徑 / FE 動態渲染)