siriusscan--sirius
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
186 行
7.4 KiB
Markdown
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
|