FR-057 · Detection Tool Integration — OpenSCAP
在 FR-056 檢測工具整合平台上新增第二個工具 OpenSCAP(CIS / STIG 組態合規稽核),並藉此開出 connector 架構的第三種連線型態 SSH。Agent 維持 Docker 形態不變,作為掃描發起端遠端掃描站內目標主機。
這一節回答討論過程中的兩個核心疑問:「OpenSCAP 有沒有 API?」「目標主機要裝東西是正常的嗎?」——兩者都已查證定案。
oscap 是純 CLI——無 server、無 daemon。組態稽核要讀目標主機系統內部(設定檔 / 套件庫 / sysctl / 稽核規則),必須以登入身分在目標 OS 上原生執行。「遠端讀主機內部=需要登入身分」全業界一致:連 OpenVAS 做授權掃描(authenticated scan)一樣要存目標 SSH 憑證。
發起端 SSH 登入目標 → 推送 content → 在目標上執行目標自己的 oscap → 把報告拉回。Red Hat Satellite / Foreman 大規模採用同一模式。目標主機需一次性安裝 openscap-scanner(幾 MB CLI、非常駐、不開 port、不吃資源)——這是選用 OpenSCAP 的隨附條件。
它們自造檢查引擎(商業核心資產):SSH 登入後只跑通用指令,把原始輸出拉回 scanner 端自行判定。OpenSCAP 開源專案沒有這一層。真正零安裝的組態稽核是商用掃描器的能力,未來接 Nessus 時自然取得。
Agent container 只需 openssh-client + oscap-ssh 腳本(Dockerfile 加一行 apt);掃描引擎在各目標主機上。一站一個 Agent、掃站內 N 台目標——與 Rapid7 / Qualys 官方 Containerized Scan Engine 同一模型,部署形態零改動。
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
graph LR
subgraph cloud["雲端 Guidant AI"]
CFG["租戶工具設定
(SSH 憑證加密存放)"]
TASK["任務: 檢測工具執行
(hosts + profile)"]
EV["job_evidences
(source=DETECTION_TOOL)"]
end
subgraph site["客戶站點"]
AGENT["evidence-agent
(Docker, 掃描發起端)"]
H1["目標主機 1
openscap-scanner + sshd"]
H2["目標主機 2
openscap-scanner + sshd"]
H3["目標主機 N ..."]
end
TASK -->|"心跳派工 (mTLS)
含解密憑證"| AGENT
AGENT -->|"oscap-ssh"| H1
AGENT -->|"oscap-ssh"| H2
AGENT -->|"oscap-ssh"| H3
H1 -->|"HTML 報告"| AGENT
H2 -->|"HTML 報告"| AGENT
AGENT -->|"result (多檔)"| EV
CFG -.->|"派工時解密下發"| TASK
classDef cloudBox fill:#E2F0F1,stroke:#0E7C86,color:#14201F;
classDef siteBox fill:#FFFFFF,stroke:#C7D1D2,color:#14201F;
classDef hostBox fill:#E4F1EA,stroke:#2E7D5B,color:#14201F;
class CFG,TASK,EV cloudBox;
class AGENT siteBox;
class H1,H2,H3 hostBox;
style cloud fill:#FBFCFC,stroke:#E4EAEB,color:#4A5A5C;
style site fill:#FBFCFC,stroke:#E4EAEB,color:#4A5A5C;
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
participant U as 管理員 / 稽核員
participant BE as 雲端 BE
participant AG as Agent (Docker)
participant T as 目標主機
U->>BE: 設定 OpenSCAP(帳號 + 金鑰/密碼)
BE->>BE: 憑證 Fernet 加密存放
U->>BE: 測試連線
BE->>AG: probe 派工
AG->>T: SSH 認證 + 檢查 oscap / SSG content
AG-->>BE: 四段檢查結果(缺什麼報什麼)
U->>BE: 任務開始執行(hosts + profile)
AG->>BE: 心跳
BE-->>AG: pending_tasks(含解密憑證, mTLS)
loop 逐台目標
AG->>T: oscap-ssh xccdf eval --profile ... --report ...
T->>T: 在目標 OS 上原生執行 oscap
T-->>AG: HTML 報告 + stdout 統計
end
AG->>BE: result(upload_uids 多檔 + summary 加總)
BE->>AG: 逐檔 mTLS GET /blob/{uid}
BE->>BE: 逐檔寫 job_evidences + 通知負責人
七項決策皆已拍板。設計立場:不自創做法,逐項對齊業界標準(Tenable 官方文件為主要參照)。
D1 · 已拍板 — SSH 憑證放租戶工具設定層(一組共用稽核帳號)
Tenable《Credentialed Checks on Linux》官方建議原文即此模式:每台目標主機建立同名專用掃描帳號。完全沿用 tenant_detection_tool_configs 加密鏈 + FR-056 D9 派工下發,零新表零新機制。任務層帶憑證(明文落 DB)排除;host inventory 表(每台各自憑證)列未來,資料模型可平滑升級。
D2 · 已拍板 — 密碼 / SSH 私鑰二擇一,推薦金鑰 + sudo 提權選項
Tenable 同款建議:金鑰更安全、私鑰只存 scanner 端、可隨時在主機端撤銷公鑰。完整掃描需 root 級讀取而企業普遍禁 root 遠端登入 → use_sudo 布林(oscap-ssh --sudo),「一般帳號 + sudo 提權」是業界標準模式。
D3 · 已拍板 — SCAP content 用目標主機自帶的 SSG
目標裝 scap-security-guide 套件,content 在 /usr/share/xml/scap/ssg/content/,天然匹配該機 OS 版本。任務參數=content 路徑(預設慣例路徑可改)+ profile(常用 CIS/STIG 下拉 + 自由輸入)。平台統一管理 content 列未來(跨發行版版本矩陣維護成本高、錯配掃出整片 notapplicable)。
D4 · 已拍板 — 證據=HTML 原樣上傳,summary 從 stdout 解析
oscap 官方人讀格式就是 HTML(無原生 PDF)。不轉 PDF——LibreOffice 轉複雜 HTML 排版易爛,轉壞的報告比原檔更難看。ARF XML 結構化 findings 留未來 FR(同 FR-056 D4「第一版只存報告」邏輯)。
D5 · 已拍板 — 多目標逐台掃、每台一個證據檔
檔名含主機名、summary 加總,不硬拼單一 HTML。⚠️ 牽動回收鏈:現況 result_ref.upload_uid 是單數,需擴成多檔陣列(獨立子需求 FR-057.3,向下相容 OpenVAS 單檔路徑)。
D6 · 已拍板 — 部署前提:設定頁內建說明 + 準備腳本 + probe 實地檢查
detection_tools 加 setup_guide 欄位,設定頁渲染前提清單 + 一鍵複製的目標主機準備腳本(裝套件 / 建帳號 / 佈公鑰 / sudoers)。probe 測試連線時 SSH 上去實地驗 oscap 與 SSG content 存在性——錯誤分類四段:連不上 / 認證失敗 / 缺 oscap / 缺 content。
D7 · 已拍板 — 第一版不做
Push 模式(目標自掃回報,Foreman 式——與「按開始→即時派工」任務模型衝突);host inventory 表;ARF findings 解析;content 平台統一管理。
| 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 欄位進 credentials_encrypted 密文;其餘進 field_values。FE 需擴的欄位型態:textarea、條件顯示(auth_method 切換)。
| key | label | type | required | 說明 |
|---|---|---|---|---|
hosts | 掃描目標 | text | 必填 | 逗號/空白分隔多台(同 OpenVAS 慣例,connector 邊界正規化) |
content_path | SCAP content 路徑 | text | — | 預設 SSG 慣例路徑,可填完整檔案路徑 |
profile | 掃描 Profile | select_or_text(新型態) | 必填 | 下拉常用(CIS L1/L2 Server、STIG)+ 自由輸入 xccdf profile id |
timeout_sec | 逾時秒數 | number | — | 預設 3600,逐台計 |
# 每台目標主機執行一次(Ubuntu/Debian;RHEL 系換 dnf + scap-security-guide)
sudo apt install -y openscap-scanner ssg-base ssg-debderived
sudo useradd -m -s /bin/bash audit-scan
echo '<公鑰>' | sudo tee -a /home/audit-scan/.ssh/authorized_keys
echo 'audit-scan ALL=(root) NOPASSWD: /usr/bin/oscap' | sudo tee /etc/sudoers.d/audit-scan
新增 core/task_executor_connectors/openscap.py,實作既有 DetectionConnector 介面(run / probe / cancel_event),factory 加 4: "openscap",Dockerfile 加 openssh-client + openscap-utils。
解析 hosts → 逐台執行 oscap-ssh [--sudo] user@host port xccdf eval --profile … --report … → 收 HTML bytes + stdout 統計 → 回多檔結果。私鑰寫入記憶體型暫存(0600),掃完即刪不落地。
SSH 連線 → 認證 → command -v oscap → SSG content 存在性。缺什麼在錯誤訊息明確分類,與 run() 共用連線參數解析(單一真相,同 OpenVAS 模式)。
0=全 pass;2=有 fail 但掃描成功(報告有效,最常見結果);1=執行錯誤。2 絕不可誤判為失敗。
{"findings": fail數, "pass": n, "fail": n, "notapplicable": n, "error": n, "hosts_scanned": n}。解析失敗不拖垮派工(證據到手 summary 可缺,同 OpenVAS 原則)。
D5 的連鎖工程:一任務掃 N 台=N 份報告,但現況 result 鏈是單檔設計。擴充需跨 agent 與 BE 兩端,且必須向下相容 OpenVAS 單檔路徑。
| 端 | 現況 | 擴充 |
|---|---|---|
| Agent task_executor | result_ref: {"upload_uid": x} 單數 | 逐檔上傳 blob → {"upload_uids": [{"uid","filename"}, …]};保留單數 key 讀取相容 |
| BE detection_result_handler | 取單檔 mTLS GET /blob/{uid} 寫一筆證據 | 讀 upload_uids(fallback upload_uid)逐檔取回逐檔寫入;單檔失敗記 warning 續處理其餘(部分成功優於全失敗) |
檔名慣例:OpenSCAP掃描報告_<host>_<日期>.html(content_type=text/html)。
依賴鏈:.1 是地基;.2 / .3 可並行(.3 用假多檔即可測,不等 openscap connector)。每子任務=一張 Notion 子卡。
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
graph LR
A["FR-057.1
BE 地基
SSH 型態 + seed + FE 欄位型態"] --> B["FR-057.2
Agent OpenSCAP connector"]
A --> C["FR-057.3
多檔證據回收鏈"]
B -.->|"端到端驗收匯合"| D["E2E 驗收"]
C -.-> D
classDef base fill:#E2F0F1,stroke:#0E7C86,color:#14201F;
classDef par fill:#E4F1EA,stroke:#2E7D5B,color:#14201F;
classDef fin fill:#F6EBD5,stroke:#9C6B12,color:#14201F;
class A base;
class B,C par;
class D fin;
| # | 子任務 | 驗收 | 依賴 | Repo |
|---|---|---|---|---|
| T-1.1 | migration:seed openscap(SSH 型態 + config_field_schema)+ param_schema + setup_guide 欄位與內容 | 三環境可套;設定頁清單出現 OpenSCAP(available) | — | BE |
| T-1.2 | FE 設定頁欄位型態擴充:textarea / 條件顯示 / setup_guide 渲染 + 腳本複製 | OpenSCAP 設定頁可完整填寫送出,憑證密文落庫 | T-1.1 | FE |
| T-1.3 | FE 任務參數型態擴充:select_or_text(profile) | 任務可選 OpenSCAP 並填參數發佈 | T-1.1 | FE |
| # | 子任務 | 驗收 | 依賴 | Repo |
|---|---|---|---|---|
| T-2.1 | Dockerfile + factory 註冊 + connector 骨架(SSH 參數解析、私鑰暫存管理) | image build 過;unit test 綠 | T-1.1 | agent |
| T-2.2 | run():逐台 oscap-ssh + HTML 收取 + stdout summary + exit code 2 處理 + 取消/逾時 | 手塞派工 → 掃真實主機 → 報告回收全鏈通 | T-2.1 | agent |
| T-2.3 | probe():連線/認證/oscap/SSG 四段檢查與錯誤分類 | 四種缺件情境回清楚訊息 | T-2.1 | agent |
| # | 子任務 | 驗收 | 依賴 | Repo |
|---|---|---|---|---|
| T-3.1 | Agent:task_executor 多檔上傳 + result_ref.upload_uids(向下相容單數) | 多檔回報結構正確;OpenVAS 單檔迴歸綠 | — | agent |
| T-3.2 | BE:detection_result_handler 多檔迴圈取回 + 逐檔寫證據 + 部分失敗續處理 | 多檔證據逐檔入池;單檔 fallback 迴歸綠 | T-3.1 | BE |
| # | 情境 | 預期 |
|---|---|---|
| 1 | 管理員設定 OpenSCAP(金鑰認證)→ 測試連線 | probe 通過(含 oscap / SSG 前提檢查) |
| 2 | 任務選 OpenSCAP、2 台 hosts + CIS profile → 開始執行 | 每台各一份 HTML 報告進證據池,summary 加總正確 |
| 3 | 任一台缺 openscap-scanner | probe / 掃描回明確分類錯誤(非神祕失敗) |
| 4 | OpenVAS 既有全鏈迴歸 | factory / result 單檔路徑 / FE 動態渲染不受影響 |