FR-066 T-4.3 · Windows 可行性評估 · 2026-08-22
D8 裁定「Windows 只出評估文件+前提清單,不實作不承諾」。本文件是那份評估:原三題(指紋/服務形式/工具鏈)+決策者 2026-08-22 追加四項(docker 過渡模式/互動設定對應/兩路線工時/Windows 宿主檢測覆蓋),每項有結論與前提清單,查不死的標「待實測」。
🔴 本文件是可行性評估,不是實作承諾、不是 roadmap。 所有「可行」結論都附前提清單; 任何排程與投入須由決策者另行拍板。查證方式=evidence-agent 實碼(v0.2.x,feature/FR-066 分支現況)+公開來源(附連結);無法純查證確認的項目一律標 待實測,不寫成結論。
對應:design.md D8(含附錄 2026-08-18 初判);本文件為其正式查證版,覆核並修正初判。
| 項目 | 結論 | 卡點等級 |
|---|---|---|
| ①指紋來源 | 可行:WMI Win32_ComputerSystemProduct.UUID+registry MachineGuid 對應現行二源,語意等價;但讀取方式從「讀檔案」變「查 WMI/registry」,需做 D9 當初刻意延後的 OS 抽象層 |
低 |
| ②服務形式 | 可行:service wrapper(WinSW 一系)包 Nuitka 產物是最貼近現行 systemd 模型的做法;NSSM 2.24 已停止維護(2017 最後 release),初判的「NSSM 業界標準」需修正 | 低 |
| ③工具鏈 | 無死路但整備量大:CINC 有 Windows msi、sonar-scanner 有 windows-x64 zip(自帶 JRE)、LibreOffice 有 Windows 版、git 有 portable 版;SSH 類(OpenSCAP/nmap)純 paramiko 不受平台影響。每項要重做一次離線化整備+釘版 | 中 |
| ④docker 過渡模式 | 不建議當正式過渡方案:授權可繞(WSL2 裝 docker engine 免 Docker Desktop 費用),但指紋二源在 WSL2/Docker Desktop 下實質失效(product_uuid 不存在、machine-id 是 VM 的不是 Windows 主機的)——身分穩定性做不到現行設計的要求,要救就得重新引入 D9 已廢除的 collect-host-id 式 workaround | 高(指紋) |
| ⑤互動設定對應 | 可行:全環境變數設定模型(D5)本身跨平台零改;互動三題+SeaweedFS 帳密生成+factory-defaults.env 快照的「流程邏輯」可照搬,但 3000 行 bash 的載體要用 PowerShell 重寫,TOFU 憑證確認等段落是重寫不是翻譯 | 中 |
| ⑥工時 | 原生路線粗估 19–31 人日(不含 code signing 憑證申請的行政 lead time);docker 過渡路線 7–12 人日但有④的指紋硬傷。初判「約 Linux 版 40–60%」方向正確、維持 | — |
| ⑦Windows 宿主檢測覆蓋 | 遠端型全數照常(CINC ssh/winrm、OpenSCAP、nmap、ZAP、OpenVAS、sonar-scanner 打客戶 server);受限項=掃 Windows 宿主自己要繞 WinRM loopback(待實測)、LibreOffice 轉檔待實測;不可用項=無(以現有 connector 清單論) | 低 |
| 新風險 | code signing:SmartScreen/Defender 會攔未簽章 exe。Azure Trusted Signing 現僅開放美加三年以上組織,台灣公司走不了,需買傳統 OV/EV 憑證(年費數百美金級)+簽章進 build 管線 | 中(行政面) |
現行 Linux 實作(core/fingerprint.py+core/host_identity.py): device_uuid = sha256(product_uuid | machine_id),二源皆為讀檔—— /sys/class/dmi/id/product_uuid(主機板 SMBIOS UUID)與 /etc/machine-id(OS 安裝身分)。 缺源 graceful(空字串參與雜湊+log warning),兩源全空記 warning。 host_identity.py docstring 明寫「Linux 專用、不做平台分支」(D9 刻意不預抽抽象層)。
Windows 等價來源(語意一一對應):
| Linux 源 | Windows 等價 | 語意 | 讀取方式 |
|---|---|---|---|
/sys/class/dmi/id/product_uuid |
WMI Win32_ComputerSystemProduct.UUID |
同一個 SMBIOS UUID(硬體主機板身分),同一台機器雙系統下值相同 | WMI 查詢(pywin32/wmi 套件,或 subprocess PowerShell Get-CimInstance) |
/etc/machine-id |
registry HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid |
OS 安裝身分:裝機時生成、重灌會變 | winreg(Python 標準庫,零依賴) |
結論:二源模型不用改,改的只是「怎麼讀」。現行 compute_device_uuid(product_uuid_path, machine_id_path) 吃兩個檔案路徑參數,Windows 版需要把「來源」從路徑抽象成 provider——這正是 D9 說「等 Windows 真要做再抽」的那層,屆時再抽,重構範圍就 fingerprint.py+host_identity.py 兩檔與 config.py 的兩個 path 欄位。
與 Linux 版一致的已知風險(不新增、也不消失):
前提清單:
install.sh 內的 shell 版指紋複刻(guidant-agent-ctl fingerprint,D11 實作註②的雙實作教訓)在 Windows 版要有對應物(PowerShell 複刻或呼叫 agent binary),且同樣受「改演算法要同步兩份」紀律管。FFFFFFFF-FFFF-...(SMBIOS 未填)的比例與 graceful 行為——現行「空值參與雜湊」邏輯需驗證對這種佔位值的處理(佔位值非空,會被當有效源,兩台同 OEM 機可能撞)。現行 Linux 模型:Nuitka standalone 產物由 systemd unit 拉起,EnvironmentFile=/etc/guidant-agent/agent.env 餵設定,journald 收 log。
Windows 三條路比較:
| 方案 | 說明 | 評估 |
|---|---|---|
| **A. service wrapper(建議方向) | WinSW/Shawl/Servy 等工具把任意 exe 包成 Windows Service:XML/設定檔宣告執行檔、環境變數、log 輪替、自動重啟 | 最貼近 systemd 模型**:agent 程式零改(跟現在被 systemd 拉起一樣是普通進程)、環境變數注入對應 EnvironmentFile、wrapper 自帶 log 檔輪替對應 journald。WinSW 出身 Jenkins 專案、MIT 授權、單檔 <1MB,隨包出貨無授權疑慮 |
| B. pywin32 原生 service | 程式自己實作 Windows service 介面 | Nuitka 與 pywin32 service 框架相容性差(pythonservice.exe 要 import .py 檔,與編譯產物衝突,pywin32#1302);社群 fork Nuitka-winsvc 可解但引入非官方編譯器 fork——build 管線信任基礎不該押在小眾 fork 上 |
| C. NSSM | 初判寫「業界標準(Wazuh 等同款)」 | 初判需修正:NSSM 2.24 是 2017 年最後 release,社群普遍視為 abandoned(比較文、alternatives 盤點)。功能上仍可用(很多產品確實還在用),但 2026 年新做的產品不該選一個近十年沒維護的元件當常駐層 |
結論:方案 A(wrapper,首選 WinSW 一系)。「哪一支 wrapper」屬實作期選型(WinSW 自身維護活躍度也有爭議,Shawl/Servy 較新),評估層結論是:wrapper 模式成立、候選不只一家、無授權障礙,不卡可行性。
前提清單:
sc stop 優雅停止(對應 systemd 的 SIGTERM 寬限)。--windows-console-mode 選項需實測。依 scripts/build/tools-manifest.txt(Linux bundle 的單一真相來源)逐項對應。「離線化」是每項的共同前提:Linux 版每個工具都經歷過「官方形式→離線可裝→釘版+sha256→Nexus 第二來源」的整備,Windows 版要對等重做一輪。
| 工具 | Linux bundle 現況 | Windows 對應 | 狀態 |
|---|---|---|---|
| CINC Auditor 7.x | ubuntu/20.04 deb(三家族通吃裁示) | 官方有 Windows msi(omnitruck 亦支援 PowerShell 安裝)。⚖️ 授權紅線不變:CINC 社群版,絕不可換官方 Chef InSpec 商業 binary | ✅ 有原生形式;待實測:msi 離線 silent install(msiexec /qn)與安裝後路徑 |
| sonar-scanner | linux-x64 zip 自帶 JRE | 官方有 windows-x64 zip 自帶 JRE(同一 binaries.sonarsource.com 命名模式) | ✅ 形式對等,解壓即用 |
| LibreOffice | TDF deb tarball dpkg-deb -x 解成 /opt 自足樹(Q1 定案:不碰套件系統) |
Windows 有官方 msi;「不碰系統」的對等形式是社群 LibreOffice Portable(PortableApps 打包,非 TDF 直營)。msi 可 silent install 但會註冊進系統 | 🟡 兩條路都存在,Q1 的 Windows 版要重跑一次實測選型(判準同款:離線可裝/字型能落/體積可接受) |
| Noto Sans CJK 字型 | ttc 直落 /usr/share/fonts |
Windows 字型安裝=複製進 C:\Windows\Fonts+registry 登記(或 per-user 字型目錄);LibreOffice 也吃自帶字型目錄 |
🟡 機制不同但單純;待實測:headless 轉檔吃哪個字型目錄 |
| xsltproc | 已退場——nmap XML→HTML 改 lxml 程式內轉換(T-2.1.2,見 nmap.py 檔頭) |
純 Python(lxml),零平台工作 | ✅ 初判列的 🟡 已被 Linux 版自己消掉 |
| git | 系統 git(sonar-scanner clone 模式用,AGENT_GIT_BIN 可覆寫) |
Git for Windows portable(MinGit) 免安裝形式 | ✅ |
| SSH 掃描(OpenSCAP/nmap connector) | paramiko 純 Python,agent 端不裝任何引擎(引擎在受測機/執行主機) | 純 Python,跨平台零改 | ✅ |
| ZAP/OpenVAS | 不 bundle(客戶自備 daemon,API 連線) | 純 Python API client,零平台工作 | ✅ |
Nuitka 編譯本體:官方支援 Windows(MSVC;MinGW64 不支援 Python 3.13+,本案 3.11 無此顧慮但仍建議 MSVC)。dependency-injector 私房 wheel(rebuild_wheels.sh)要在 Windows 上用 MSVC 重編一次——腳本本身是 bash,Windows build 環境下的對應載體屬實作項。
前提清單:
cinc-auditor.bat 的呼叫路徑——AGENT_CINC_BIN 預設值要換)。_CINC_BIN=/usr/bin/cinc-auditor、_SONAR_SCANNER_BIN、_GIT_BIN 等預設值都是 Linux 路徑,env 覆寫機制已存在(零架構改動),但預設值與 install 落點要成套定義。卡片問的是:原生 Windows 版做出來之前,Windows 客戶先用 docker 跑現有 compose 形態 agent 是否可行。分三子題查證,結論先講:技術上「跑得起來」,但指紋子題是硬傷,作為正式過渡交付形態不建議;僅適合標成「PoC/demo 限定、身分不保證穩定」的權宜形態。
wsl --shutdown 後服務不自起、Windows 更新對 WSL 的影響)——把「裝 agent」變成「先當半個 Linux 管理員」,與落地版「一線工程師/業務可裝」的受眾設定(D15)相悖。小結:授權面可繞(WSL2+Engine),但繞的代價是維運複雜度轉嫁客戶。
現行 compose 設計(deploy/docker-compose.yml:142-143)唯讀掛載宿主的 /sys/class/dmi/id/product_uuid 與 /etc/machine-id。這個設計的前提是「宿主是一台真 Linux 機」。Windows 上兩種 docker 承載都打破前提:
| product_uuid | machine-id | |
|---|---|---|
| WSL2(含 Docker Desktop WSL2 backend) | 不存在——WSL2 utility VM 不曝露 SMBIOS/DMI,/sys/class/dmi/id/ 整目錄缺(microsoft/WSL#6347 為此開的 feature request 至今未實作) |
讀得到,但那是 WSL distro 的 machine-id,不是 Windows 主機身分:wsl --unregister 重裝 distro 就換一個;標準 Ubuntu/Debian distro 下重開機會保留(存 ext4),但 NixOS-WSL 等已有 tmpfs 掛載每次重開就變的實例(NixOS-WSL#574) |
| Docker Desktop(Hyper-V backend) | 同樣讀不到 Windows 主機的值(容器所在 VM 的 DMI,非主機) | 是 Desktop utility VM 的,Desktop reset/重灌即變 |
後果鏈:product_uuid 缺 → compose 對不存在的來源做檔案掛載時 docker 會自動建一個空目錄頂在掛載點上 → agent _read_source() 對目錄 open 失敗 → graceful 回空字串 → 指紋退化成只剩 machine-id 單源,而那個 machine-id 又是「VM 的」不是「這台 Windows 機的」——重灌 WSL distro/reset Docker Desktop 就漂移,正是 FR-064 時期「容器 machine-id 空檔指紋漂移」事故的同族問題。
要救得動的做法只有一種形狀:在 Windows host 側(PowerShell)讀 MachineGuid/WMI UUID,寫成檔案掛進容器——這就是 D9 已明文廢除的 collect-host-id.sh workaround 的 Windows 復刻(人工抄值、會過期、靜默錯,D11 排除方案②的理由原文照搬適用)。為一個過渡形態重新引入被兩個決策(D9/D11)連續否決的機制,設計上說不過去。
小結:此子題單獨足以否決「docker 過渡當正式交付形態」。若決策者仍要 PoC 用途的過渡形態,前提是明文標注「agent 身分綁定不穩定,WSL/Desktop 重置後需重新綁定」。
deploy/install.sh(1895 行 bash)的內容是 docker CLI 操作(load image、digest 比對、compose up、volume 管理)+互動問答+SeaweedFS 帳密生成。在 WSL2 distro 內執行技術上可行(bash、docker CLI、openssl rand 都在),不需 PowerShell 重寫——這是 docker 過渡路線工時便宜的主因。待實測項:ip route get 自動偵測本機對外位址在 WSL2 NAT 網路下會偵測到 WSL 內部 IP(172.x),必錯,第三題預設值在此環境不可信;雲端連回 agent 8443 要靠 Windows 側 port forwarding(netsh interface portproxy 或 WSL 新版 mirrored networking),這段是新增的 Windows 專屬安裝步驟,現行腳本完全沒有。
Linux 版設定鏈實況(ground 自 scripts/install/install.sh+config/config.py):
ip route get 自動偵測預設值+重裝時沿用舊值;/etc/guidant-agent/agent.env(systemd EnvironmentFile);openssl rand -hex 24 自動生成+factory-defaults.env 出廠快照(600、落資料目錄、跨版本存活)+configure-storage 恢復預設(T-6.7)。核心結論:設定「模型」跨平台零改,設定「載體」要重寫。 逐層對應:
| 層 | Linux 現況 | Windows 原生版對應 | Windows docker 過渡版 |
|---|---|---|---|
| 設定模型 | 全環境變數(config.py 全部 os.getenv,D5) |
零改——這是 D5 的跨平台紅利 | 零改 |
| 設定檔落點 | /etc/guidant-agent/agent.env |
C:\ProgramData\GuidantAgent\agent.env(ProgramData 是 Windows 慣例的機器級設定落點);由 service wrapper 的環境變數宣告餵進程,或 agent 啟動時自讀 |
.env 留在 WSL 內安裝目錄(現行機制原樣) |
| 互動問答載體 | bash read -r |
PowerShell 互動腳本(建議首版)或 Inno Setup/MSI 精靈表單(體驗更好但工時更高、且 TOFU 憑證確認這種「印指紋等人讀」的流程在精靈表單裡要重新設計)。流程邏輯(三題、驗證、沿用舊值)照搬 | WSL 內跑現行 bash(§2.3) |
| 第三題自動偵測 | ip route get <雲端IP> 取 src |
PowerShell 等價:Find-NetRoute / Get-NetIPConfiguration 可得同語意答案(往雲端方向的出口 IP)——邏輯可移植,載體重寫 |
WSL 內偵測值必錯(§2.3),需改問 Windows 主機 IP |
| TOFU 憑證確認 | bash+openssl | PowerShell+.NET SslStream 或內建 openssl(Git for Windows 附帶)——重寫不是翻譯,是本段工時的主要來源 |
現行 bash 原樣 |
| SeaweedFS 帳密生成 | openssl rand -hex 24 |
過渡版才有 SeaweedFS(原生 Windows 版首階段不含 compose/SeaweedFS,儲存走 local/自有 MinIO) | 現行機制原樣 |
| factory-defaults.env 快照+恢復 | 資料目錄、600、configure-storage 讀回 |
機制照搬(檔案+權限改 Windows ACL);guidant-agent-ctl 維運腳本整支是 bash,Windows 對應物=PowerShell 版 ctl 或 agent binary 子命令化 |
現行機制原樣(在 WSL 內) |
前提清單:
估算基準:Linux 版對應項的實際規模(build 管線+smoke 約 4 棒卡、install.sh 3069 行+compose 版 1895 行、工具 bundle 整備含三家族實測)。粗估僅供「先過渡 vs 直接原生」取捨,非排程承諾。 不含:code signing 憑證申請行政 lead time(週級)、Windows build 機採購、決策與驗收往返。
| 層 | 工作 | 粗估(人日) |
|---|---|---|
| Nuitka Windows build 管線 | build 機建置(MSVC+Python 3.11+Nexus)、dependency-injector wheel 重編、build 腳本 Windows 載體、smoke 對應 | 3–5 |
| 指紋 OS 抽象層 | provider 化+WMI/winreg 實作+佔位值處理 | 1–2 |
| 常駐服務 | wrapper 選型實測+service 打包+停啟/崩潰重啟/log 驗證 | 2–3 |
| 安裝程式 | PowerShell 版七步+三題+TOFU+agent.env+維運子命令 | 4–6 |
| 工具 bundle 離線化 | CINC msi/sonar-scanner zip/LibreOffice(Q1-Windows 選型)/字型/MinGit:下載整備+釘版+silent 安裝+斷網驗證 | 4–7 |
| code signing 接入 | 憑證選型採購(行政另計)+簽章進 build 管線+SmartScreen 實測 | 2–3 |
| 乾淨機驗收 | 乾淨 Windows 機端到端(裝→enroll→跑 CINC+SSH 型任務→證據回收)+斷網驗證 | 3–5 |
| 合計 | 19–31 |
初判「約 Linux 版 40–60%」覆核:Linux 版 .1–.4 全 arc 規模對照下,本估算落在同區間,初判維持。源碼層(enroll/mTLS/connector/SQLite)確實幾乎零改,工時集中在 build/安裝/整備三個「載體層」。
| 項 | 工作 | 粗估(人日) |
|---|---|---|
| WSL2+Engine 安裝指引 | 客戶側文件(WSL 安裝、docker-ce、systemd 啟用、開機自起)+port forwarding(netsh portproxy)步驟 | 2–3 |
| 指紋權宜解 | 「PoC 限定、身分不穩」的邊界文件化;或做 host 值注入 workaround(不建議,做了 +2–3 人日且違反 D9/D11) | 1–3 |
| install.sh WSL 適配 | 第三題偵測修正+WSL 環境檢查項+實測 | 2–3 |
| 驗收 | Windows 機 WSL2 端到端一輪(含重開機自起、wsl --shutdown 復原行為) |
2–3 |
| 合計 | 7–12 |
過渡版省 12–19 人日,但買到的是一個身分綁定不穩+客戶要自管 WSL 的形態;且過渡版的產出(WSL 文件、portproxy 指引)對原生版幾乎零複用——兩條都走=總工時近乎相加。若 Windows 需求時點允許,直接原生一步到位的總成本更低;過渡版只在「商務上急需 Windows 可 demo、可接受 PoC 級穩定度」時值得做。
逐 connector 盤(ground 自 core/task_executor_connectors/ 各檔實作機制)。關鍵分野:connector 是「本機 shell out」還是「純 Python 連出去」——後者跟宿主 OS 幾乎無關。
| Connector | 執行機制(實碼) | Windows 宿主可用性 |
|---|---|---|
| **CINC 掃遠端(SSH) | shell out cinc-auditor exec -t ssh://…(inspec.py),transport 由任務參數決定 |
✅ 照常**——CINC Windows 版含 Train SSH transport,掃 Linux 目標與現在完全同款 |
| CINC 掃遠端(WinRM) | 同上,-t winrm://…(connector 已實作 winrm_* 憑證組) |
✅ 照常;Windows 宿主掃 Windows 目標反而是這形態的主場 |
| CINC 掃本機(Windows 宿主自己) | connector 無 local transport(實碼只有 ssh/winrm 兩值,未知值直接拒),掃自己=winrm 連 localhost | 🟡 待實測——需目標機(即宿主自己)開 WinRM;「掃 Windows 主機的 profile 支援度」屬 profile 內容問題非平台問題(CIS Windows benchmark 的 InSpec profile 生態存在) |
| sonar-scanner(scan/upload 模式) | 本機 subprocess 跑 sonar-scanner+git clone(sonarqube.py) |
✅ windows-x64 zip 自帶 JRE+MinGit;路徑預設值要 Windows 化(§1.3 前提 4) |
| sonar-scanner(pull 模式) | 純 API 拉快照 | ✅ 零平台因素 |
| **OpenSCAP(SSH 遠端型) | paramiko SSH 到目標機、在目標機上跑目標自帶的 oscap(openscap.py:agent 端零引擎) |
✅ 照常**——引擎在受測機,agent 只是 SSH client。⚠️ 注意這與「掃 Windows 目標」是兩回事:OpenSCAP 官方已於 2022 停止 Windows 支援(官方聲明),Windows 目標本來就掃不了,Linux agent 也一樣——非 Windows 宿主新增的限制 |
| nmap(SSH 執行主機型) | paramiko SSH 到執行主機跑 nmap、lxml 本機轉 HTML(nmap.py) |
✅ 照常(lxml 純 Python) |
| ZAP | API 連客戶自備 daemon(zap.py) |
✅ 零平台因素 |
| OpenVAS | python-gvm TLS 連 GVMd(openvas.py) |
✅ 零平台因素 |
| **LibreOffice 轉檔(證據預覽) | jedi-file-upload convert_to_pdf shell out LibreOffice headless(api/blob/routes/blob_route.py) |
🟡 待實測**——LibreOffice Windows 版存在,headless 轉檔+中文字型(Noto CJK 落地)+soffice.exe 路徑設定需實測一輪 |
結論句(回答卡片的問法):Windows agent 蓋得住的檢測範圍=現有全部 connector。其中六成五(SSH 遠端型+API 型+pull 型)因為引擎根本不在 agent 機上,宿主換 OS 零影響;本機 shell out 型(CINC、sonar-scanner、LibreOffice)依賴工具鏈 Windows 化(§1.3),無不可用項。「掃 Windows 機」的能力上限(OpenSCAP 不支援 Windows 目標)是目標側限制,與宿主是誰無關,Windows 宿主不會更差、也不會因此更好——真正補「掃 Windows 目標」能力的是 CINC WinRM(已存在)。
Windows SmartScreen/Defender 對無簽章陌生 exe 的攔阻是交付層必過的關(Microsoft SmartScreen reputation 文件)。查證後的路線現況:
前提:憑證採購(含 lead time 與年費預算)是原生路線的行政前置;建議實作定案時最先啟動。
| # | 項目 | 出處 |
|---|---|---|
| 1 | WMI UUID 佔位值(FFFFFFFF-…)機型比例與現行空值邏輯的相容性 |
§1.1 |
| 2 | Nuitka MSVC standalone 產物在 Session 0 service 環境的啟動行為 | §1.2 |
| 3 | CINC Windows msi 離線 silent 安裝與安裝後呼叫路徑 | §1.3 |
| 4 | LibreOffice Windows 離線形式選型(msi silent vs Portable)+headless 中文轉檔 | §1.3/§5 |
| 5 | 字型落地機制(系統字型 vs LibreOffice 自帶目錄) | §1.3 |
| 6 | CINC WinRM loopback 掃宿主自己 | §5 |
| 7 | WSL2 mirrored networking/netsh portproxy 下雲端連回 agent 8443 | §2.3 |
| 8 | Windows ACL 對 agent.env/私鑰檔的 600 等價保護 | §3 |