项目文件夹

文件
wehub-resource-sync 161ef94b4f
Check engine pin consistency / Dockerfile / CI pin consistency (push) Successful in 8s
Sirius CI/CD Pipeline / Detect Changes (push) Successful in 23s
Validate Docker Configuration / Validate Docker Compose Configuration (push) Successful in 47s
Sirius CI/CD Pipeline / Build API (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build UI (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Engine Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge API Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge UI Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Build Engine (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build Infra (${{ matrix.service }}, ${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-postgres) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-rabbitmq) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-valkey) (push) Has been cancelled
Sirius CI/CD Pipeline / Integration Test (push) Has been cancelled
Sirius CI/CD Pipeline / Public Stack Contract (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Deployment (sirius-demo branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Canary (main branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Guard Registry Namespace (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:25 +08:00

186 行
7.4 KiB
Markdown

---
title: "Sub-Scans Architecture - Modular Scan Methods"
description: "Independent scan methods (network, agent) running in parallel, their data structure, lifecycle, progress aggregation, and cancellation."
template: "TEMPLATE.custom"
version: "1.0.0"
last_updated: "2025-02-07"
author: "Sirius Team"
tags: ["scanner", "sub-scan", "architecture", "progress", "cancellation"]
categories: ["architecture", "scanner"]
difficulty: "intermediate"
prerequisites: ["README.scanner.md"]
related_docs:
- "documentation/dev/apps/scanner/README.scanner.md"
- "documentation/dev/apps/scanner/ARCHITECTURE.scanner-data-flow.md"
- "documentation/dev/apps/scanner/ARCHITECTURE.host-deduplication.md"
dependencies: []
llm_context: "high"
search_keywords:
- "sub-scan"
- "sub_scans"
- "scan progress"
- "network agent parallel"
- "scan cancellation"
- "SubScan"
---
# Sub-Scans Architecture
The Sirius scanner uses a **sub-scan architecture**: each scan method (e.g. network, agent) is an independent **sub-scan** with its own status and progress. Sub-scans run in parallel and are tracked in a single `ScanResult` via a registry map.
## What Are Sub-Scans?
**Sub-scans** are independent scan methods that contribute to one logical “scan”:
- **network** – Traditional network scanning (e.g. Nmap, RustScan, Naabu) triggered via RabbitMQ and executed by app-scanner.
- **agent** – Agent-based scanning: templates run on remote hosts via app-agent over gRPC.
A scan can have zero, one, or both enabled. Each sub-scan has its own:
- Lifecycle state (e.g. dispatching → running → completed/failed/cancelled)
- Progress (e.g. completed/total hosts or agents)
- Optional metadata (e.g. agent list, per-agent status for agent sub-scan)
The overall scan state is the union of all sub-scan states and their results (hosts/vulnerabilities are merged at the scan level).
---
## Sub-Scan Data Structure
### Go (go-api / shared types)
```go
// SubScanProgress tracks completion progress for a sub-scan.
type SubScanProgress struct {
Completed int `json:"completed"`
Total int `json:"total"`
Label string `json:"label,omitempty"` // e.g. "hosts", "agents"
}
// SubScan represents a modular scanner contribution to a scan.
// Metadata is json.RawMessage so other scanners preserve it on read-modify-write.
type SubScan struct {
Type string `json:"type"` // "network", "agent"
Enabled bool `json:"enabled"`
Status string `json:"status"` // see Lifecycle states
Progress SubScanProgress `json:"progress"`
Metadata json.RawMessage `json:"metadata,omitempty"`
}
// ScanResult holds the top-level scan and a registry of sub-scans.
type ScanResult struct {
ID string
Status string
Targets []string
Hosts []HostEntry
HostsCompleted int
Vulnerabilities []VulnerabilitySummary
StartTime string
EndTime string
SubScans map[string]SubScan `json:"sub_scans,omitempty"`
}
```
### TypeScript (sirius-ui)
```ts
interface SubScanProgress {
completed: number;
total: number;
label?: string;
}
interface SubScan {
type: string;
enabled: boolean;
status: "pending" | "dispatching" | "running" | "completed" | "failed";
progress: SubScanProgress;
metadata?: Record<string, unknown>;
}
// ScanResult.sub_scans: Record<string, SubScan>
```
Agent-specific metadata in `SubScan.metadata` can include `mode`, `dispatched_agents`, `agent_statuses` (per-agent status, hosts/vulns found, etc.).
---
## Sub-Scan Registry Pattern
Sub-scans are stored in a **map keyed by scanner identifier**:
- `map[string]SubScan` in Go (`sub_scans` in JSON)
- `Record<string, SubScan>` in TypeScript
Common keys:
- `"network"` – Network scan (app-scanner).
- `"agent"` – Agent scan (app-agent).
Only enabled methods are present. When starting a scan, the UI (or API) builds this map (e.g. `subScans["network"]`, `subScans["agent"]`) and writes the initial `ScanResult` to ValKey. Consumers (app-scanner, go-api/agent path) update only their own key when merging back into `currentScan`, preserving other keys and `metadata` they don’t understand.
---
## Lifecycle States
Each sub-scan moves through a small set of states:
| State | Meaning |
|---------------|--------|
| `pending` | Not yet started (optional; may go straight to dispatching). |
| `dispatching` | Work is being dispatched (e.g. message to RabbitMQ, or gRPC dispatch to agents). |
| `running` | Actively running (targets being scanned, agents executing templates). |
| `completed` | Finished successfully. |
| `failed` | Finished with error. |
| `cancelled` | Stopped by user or system. |
The **overall scan** `status` is typically derived from sub-scans (e.g. “running” if any sub-scan is dispatching or running, “completed” when all are completed/failed/cancelled).
---
## Progress Aggregation
- **Per sub-scan:** `progress.completed`, `progress.total`, and optional `progress.label` (e.g. "hosts", "agents"). Each scanner updates its own sub-scan’s progress when writing to ValKey.
- **Overall scan:** The UI (or API) can compute an aggregate, for example:
- Total progress = sum of `completed` across sub-scans, divided by sum of `total` (or 0 if no total).
- Or: “running” if any sub-scan has `status === "running"` or `"dispatching"`, and overall completion when all sub-scans are in a terminal state.
The UI displays per–sub-scan progress (e.g. in `ScanStatus`) and can show an overall progress bar or status from these fields.
---
## Cancellation Handling
When the user cancels a scan:
1. UI/API calls the cancel endpoint (e.g. `POST /api/v1/scans/cancel` with optional `scan_id`).
2. go-api (or the component that owns the scan) sets the overall scan and/or sub-scans to a terminal state (e.g. `cancelled`) and writes the updated `ScanResult` back to ValKey.
3. **Network:** Cancellation can be implemented by app-scanner checking a shared “cancelled” flag (e.g. from ValKey or a separate key) or by receiving a cancel message, then stopping workers and updating its sub-scan status to `cancelled` in `currentScan`.
4. **Agent:** go-api (or agent coordinator) can signal agents to stop and then set `sub_scans.agent.status` to `cancelled` when updating ValKey.
So: **cancelling the scan** means ensuring all sub-scans are stopped and their status (and optionally the overall scan status) is set to `cancelled` in the same `currentScan` document.
---
## Summary
- **Sub-scans** = independent scan methods (network, agent) with their own status and progress.
- **Data structure:** `SubScan { type, enabled, status, progress, metadata }` in a `map[string]SubScan` (`sub_scans`).
- **Lifecycle:** dispatching → running → completed | failed | cancelled.
- **Progress:** per–sub-scan `completed`/`total`; overall progress can be aggregated from all sub-scans.
- **Cancellation:** cancel request stops all sub-scans and updates their status (and overall scan) in ValKey `currentScan`.
- **Registry:** Use a single `sub_scans` map; each scanner only updates its own key and preserves others’ `metadata`.
---
**Related Documentation**
- [ARCHITECTURE.scanner-data-flow.md](./ARCHITECTURE.scanner-data-flow.md) – How sub-scan results flow into ValKey and to the UI
- [ARCHITECTURE.host-deduplication.md](./ARCHITECTURE.host-deduplication.md) – How hosts from different sub-scans are merged by IP
---
**Last Updated:** 2025-02-07
**Version:** 1.0.0
**Maintainer:** Sirius Team