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
157 lines
7.4 KiB
Markdown
157 lines
7.4 KiB
Markdown
---
|
||
title: "Scanner Data Flow - End-to-End Architecture"
|
||
description: "End-to-end data flow from UI scan initiation through network/agent scans to result display and persistence."
|
||
template: "TEMPLATE.custom"
|
||
version: "1.0.0"
|
||
last_updated: "2025-02-07"
|
||
author: "Sirius Team"
|
||
tags: ["scanner", "data-flow", "architecture", "valkey", "rabbitmq", "grpc"]
|
||
categories: ["architecture", "scanner"]
|
||
difficulty: "intermediate"
|
||
prerequisites: ["README.scanner.md"]
|
||
related_docs:
|
||
- "documentation/dev/apps/scanner/README.scanner.md"
|
||
- "documentation/dev/apps/scanner/ARCHITECTURE.sub-scans.md"
|
||
- "documentation/dev/apps/scanner/ARCHITECTURE.host-deduplication.md"
|
||
- "documentation/dev/architecture/README.architecture.md"
|
||
dependencies: []
|
||
llm_context: "high"
|
||
search_keywords:
|
||
- "scanner data flow"
|
||
- "scan initiation"
|
||
- "ValKey currentScan"
|
||
- "network scan flow"
|
||
- "agent scan flow"
|
||
- "scan persistence"
|
||
---
|
||
|
||
# Scanner Data Flow – End-to-End Architecture
|
||
|
||
This document describes the end-to-end data flow of the Sirius scanner system from the moment a user starts a scan in the UI until results are displayed and optionally persisted.
|
||
|
||
## Overview
|
||
|
||
The scanner system uses a **single live scan state** stored in ValKey under the key `currentScan`. The UI initiates scans via tRPC, triggers one or more sub-scans (network and/or agent), and polls ValKey for progress. When scans complete, results can be persisted from ValKey through go-api into PostgreSQL.
|
||
|
||
**Components involved:**
|
||
|
||
- **sirius-ui** (Next.js): Initiates scans, polls for results, displays hosts and vulnerabilities
|
||
- **go-api** (Go): REST API and persistence; can proxy queue/store or be called for cancel/persist
|
||
- **app-scanner** (Go): Network scanning; consumes from RabbitMQ, updates ValKey
|
||
- **app-agent** (Go): Agent-based scanning via gRPC; runs templates on remote hosts, results flow to ValKey
|
||
- **ValKey**: Stores live scan result as `currentScan` (base64-encoded JSON)
|
||
- **RabbitMQ**: Message queue between API/UI and app-scanner for network scan requests
|
||
|
||
---
|
||
|
||
## Network Scan Flow
|
||
|
||
1. **UI** – User configures targets and scan options, clicks “Start Scan”.
|
||
2. **tRPC** – UI calls `queue.sendMsg` (and optionally scanner/start endpoints) and `store.setValue` with key `currentScan` to write initial `ScanResult` (id, status, targets, empty hosts/vulnerabilities, `sub_scans.network`).
|
||
3. **go-api / Queue** – Scan request (id, targets, options, priority) is published to the **RabbitMQ** `scan` queue (either via go-api or via tRPC router in sirius-ui that publishes to RabbitMQ).
|
||
4. **app-scanner** – Consumes the message from the `scan` queue, expands targets to IPs, runs the scan pipeline (e.g. enumeration → discovery → vulnerability), and for each host/vulnerability discovered:
|
||
- Reads current `currentScan` from ValKey (or receives it in context),
|
||
- Merges new hosts/vulnerabilities and updates progress,
|
||
- Writes updated `ScanResult` back to ValKey key `currentScan`.
|
||
5. **UI polling** – `useScanResults` polls `store.getValue({ key: "currentScan" })` (e.g. every 3s). The tRPC store router reads from ValKey and returns the value; UI decodes the base64 JSON and updates hosts/vulnerabilities for display.
|
||
|
||
So: **UI → tRPC → go-api (or tRPC) → RabbitMQ → app-scanner → ValKey → UI polling (tRPC store.getValue → ValKey).**
|
||
|
||
---
|
||
|
||
## Agent Scan Flow
|
||
|
||
1. **UI** – Same scan start; if agent scan is enabled, UI builds `sub_scans.agent` (status `dispatching`, progress 0/0) and writes initial `ScanResult` to ValKey via `store.setValue` with key `currentScan`.
|
||
2. **tRPC** – UI calls `agentScan.dispatchAgentScan` with scan id and agent scan config.
|
||
3. **go-api / gRPC** – go-api (or backend invoked by tRPC) uses **gRPC** to communicate with **app-agent** to dispatch template scans to connected agents.
|
||
4. **app-agent** – Runs templates on remote hosts, collects results, and reports back (e.g. via gRPC or callback to API). The component that holds the “current scan” state (e.g. go-api or a worker) updates the `currentScan` value in **ValKey**: merges agent-discovered hosts and vulnerabilities, updates `sub_scans.agent` status and progress.
|
||
5. **UI polling** – Same as network: UI polls `store.getValue("currentScan")`, decodes the result, and displays agent-origin hosts and vulnerabilities (with source attribution).
|
||
|
||
So: **UI → tRPC → go-api → gRPC → app-agent → (results) → ValKey → UI polling.**
|
||
|
||
---
|
||
|
||
## Persistence: ValKey (Live) → go-api → PostgreSQL
|
||
|
||
- **Live state** – The only source of truth during an active scan is ValKey key `currentScan`. All sub-scans (network, agent) read-modify-write this key to add hosts, vulnerabilities, and progress.
|
||
- **Persistent state** – After a scan completes (or on demand), the API layer can:
|
||
- Read the final `ScanResult` from ValKey (`currentScan`),
|
||
- Map hosts and vulnerabilities to the persistent model,
|
||
- Write to **PostgreSQL** via go-api (hosts, vulnerabilities, scan_sources, etc.).
|
||
|
||
So: **ValKey (live) → go-api → PostgreSQL (persistent).** The UI can show live data from ValKey and, for history/reporting, data from go-api/PostgreSQL.
|
||
|
||
---
|
||
|
||
## Sequence Diagram (Mermaid)
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant UI as sirius-ui
|
||
participant tRPC as tRPC (Next.js)
|
||
participant API as go-api
|
||
participant RMQ as RabbitMQ
|
||
participant Scanner as app-scanner
|
||
participant Valkey as ValKey
|
||
participant gRPC as gRPC
|
||
participant Agent as app-agent
|
||
participant DB as PostgreSQL
|
||
|
||
UI->>tRPC: Start scan (targets, options)
|
||
tRPC->>Valkey: setValue("currentScan", initial ScanResult)
|
||
tRPC->>API: (optional) start / queue
|
||
API->>RMQ: Publish scan message (network)
|
||
tRPC->>API: dispatchAgentScan (if agent enabled)
|
||
API->>gRPC: Dispatch to agents
|
||
gRPC->>Agent: Run templates on hosts
|
||
|
||
loop Network scan
|
||
Scanner->>RMQ: Consume scan message
|
||
Scanner->>Scanner: Expand targets, run phases
|
||
Scanner->>Valkey: Get currentScan
|
||
Scanner->>Valkey: Set currentScan (merge hosts/vulns)
|
||
end
|
||
|
||
loop Agent scan
|
||
Agent->>Agent: Execute templates
|
||
Agent->>API: Report results (or via gRPC)
|
||
API->>Valkey: Get currentScan
|
||
API->>Valkey: Set currentScan (merge agent results)
|
||
end
|
||
|
||
loop UI polling (e.g. every 3s)
|
||
UI->>tRPC: getValue("currentScan")
|
||
tRPC->>Valkey: GET currentScan
|
||
Valkey-->>tRPC: base64 ScanResult
|
||
tRPC-->>UI: ScanResult
|
||
UI->>UI: Decode, update hosts/vulnerabilities
|
||
end
|
||
|
||
note over API,DB: On completion or on demand
|
||
API->>Valkey: GET currentScan
|
||
Valkey-->>API: ScanResult
|
||
API->>DB: Persist hosts, vulnerabilities, sources
|
||
```
|
||
|
||
---
|
||
|
||
## Key Data Structures
|
||
|
||
- **ValKey key:** `currentScan` (string value = base64-encoded JSON).
|
||
- **ScanResult (JSON):** `id`, `status`, `targets`, `hosts` (array of `HostEntry` with `id`, `ip`, `hostname`, `sources`), `hosts_completed`, `vulnerabilities`, `start_time`, `end_time`, `sub_scans` (map of sub-scan key → `SubScan`).
|
||
- **SubScan:** `type`, `enabled`, `status`, `progress` (`completed`, `total`, `label`), `metadata` (optional). Used for both network and agent sub-scans.
|
||
|
||
---
|
||
|
||
## Related Documentation
|
||
|
||
- [ARCHITECTURE.sub-scans.md](./ARCHITECTURE.sub-scans.md) – Sub-scan lifecycle and progress aggregation
|
||
- [ARCHITECTURE.host-deduplication.md](./ARCHITECTURE.host-deduplication.md) – How hosts from multiple sources are merged and displayed
|
||
- [README.scanner.md](./README.scanner.md) – Scanner engine details (message format, strategies, ValKey usage)
|
||
|
||
---
|
||
|
||
**Last Updated:** 2025-02-07
|
||
**Version:** 1.0.0
|
||
**Maintainer:** Sirius Team
|