Files
vulncheck/ARCHITECTURE.md
T
vulncheck 0c34321a00 docs: refresh ARCHITECTURE / DATABASE_SCHEMA / PROJECT_OVERVIEW
Previous docs dated Feb 1-2 — pre multi-provider auth, pre Nessus,
pre compliance/URS. Full rewrite covering dev-branch state at
migration 022:

- ARCHITECTURE.md: current stack table, scheduler job list, auth
  strategy diagram, OWASP mitigation matrix, deployment + perf notes.
- DATABASE_SCHEMA.md: all 20+ tables with columns, indexes, enums,
  FK CASCADE semantics, full migration 001-022 history.
- PROJECT_OVERVIEW.md: feature list (5 threat-intel sources, multi-
  scanner, multi-auth, compliance/URS), workflow examples, debugging
  commands, current limitations.

README.DEV.md still ahead of these — keeps the long-form feature
deep-dives.
2026-05-24 13:54:47 +02:00

19 KiB
Raw Blame History

VulnCheck — Architecture Overview

Stand: Mai 2026 (dev-Branch, post-Migration 022). Diese Doku spiegelt den dev-Branch wider. Stable main ist eine Teilmenge — siehe README.md vs. README.DEV.md.


1. System Architecture

                       ┌──────────────────────────────────────┐
                       │            Browser (UI)              │
                       │   Next.js 14 App Router (SSR + CSR)  │
                       └──────────────────┬───────────────────┘
                                          │ HTTPS/JSON + JWT (Cookie+Bearer)
                                          ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                       Backend — FastAPI (Python 3.12)                    │
│                                                                          │
│   ┌──────────────┐  ┌─────────────────┐  ┌─────────────────────────┐    │
│   │  Routers     │  │  Services       │  │  Integrations (clients) │    │
│   │  (HTTP API)  │──▶ (Business Logic)│──▶ Wazuh / Nessus / NVD /  │    │
│   └──────────────┘  └─────────────────┘  │ EPSS / KEV / EUVD /      │    │
│                                          │ Vulnrichment / cvelistV5  │    │
│                                          └─────────────────────────┘    │
│                                                                          │
│   ┌──────────────────────────────────────────────────────────────────┐   │
│   │  APScheduler — Background Jobs                                   │   │
│   │  - sync_schedules (every 60s, picks up DB changes)               │   │
│   │  - SLA breach checker (hourly)                                   │   │
│   │  - Daily threat-intel refresh (EPSS + KEV)                       │   │
│   │  - Nightly compliance SCA refresh (02:00 UTC)                    │   │
│   │  - Nightly Vulnrichment cascade (03:00 UTC)                      │   │
│   │  - Nightly URS recompute + snapshot prune (04:00 UTC)            │   │
│   │  - User-defined scan schedules (Wazuh or Nessus, cron/interval)  │   │
│   └──────────────────────────────────────────────────────────────────┘   │
└────────────────────┬──────────────────────────────┬──────────────────────┘
                     │                              │
              SQLAlchemy 2.x                  httpx clients
                     ▼                              ▼
        ┌────────────────────────┐       ┌────────────────────────┐
        │  PostgreSQL 16         │       │  External Sources      │
        │  - alembic-managed     │       │  - Wazuh Indexer/API   │
        │  - 22 migrations live  │       │  - Nessus REST API     │
        │  - JSON columns:       │       │  - NVD REST API        │
        │    sources, refs,      │       │  - FIRST.org EPSS      │
        │    enrichment_sources  │       │  - CISA KEV feed       │
        │  - Settings KV store   │       │  - ENISA EUVD          │
        └────────────────────────┘       │  - cisagov/vulnrichment│
                                         │  - cveproject/cvelistV5│
                                         │  - SMTP server (mails) │
                                         │  - LDAPS / OIDC / SAML │
                                         └────────────────────────┘

Stack

Layer Tech
Frontend Next.js 14 App Router, React 18, TypeScript, Tailwind CSS, Heroicons
Backend FastAPI 0.115, Pydantic v2, Uvicorn
ORM SQLAlchemy 2.x + Alembic
Database PostgreSQL 16
Scheduler APScheduler 3.x (interval + cron triggers)
Auth Local (bcrypt + TOTP), LDAPS (ldap3), OIDC (authlib + JWKS), SAML 2.0 (python3-saml)
AI Infomaniak AI proxy (configurable via env)
HTTP client httpx (sync + async)
Container Docker Compose (backend, frontend, postgres)

2. Security Architecture (OWASP Top 10 Mitigation)

OWASP risk Defence in VulnCheck
A01 Broken Access Control RBAC enforced via require_role() dependency on every router; admin / editor / viewer scopes. Asset-ownership filter on vuln listings.
A02 Cryptographic Failures TOTP secrets encrypted at rest with AUTH_PROVIDER_CRYPTO_KEY (Fernet). LDAP bind password same. bcrypt cost-12 for local passwords. JWT secret rotated per deployment.
A03 Injection SQLAlchemy parameterised queries everywhere. CVE-IDs and search inputs sanitised. Wazuh-Indexer queries built via OpenSearch DSL, not string interpolation.
A04 Insecure Design Strategy-Pattern auth (LocalAuthStrategy, LdapStrategy, OidcStrategy, SamlStrategy) — single orchestrator, single JWT path. JIT provisioning + role mapping configurable, no hard-coded admins.
A05 Security Misconfiguration verify_ssl=True default for upstream integrations. CORS restricted to configured frontend host. CSP header on Next.js.
A06 Vulnerable Components pip-audit + npm audit in CI. Dependabot on dev.
A07 Auth Failures Failed-login counter on users table, lockout after threshold. Constant-time bcrypt verify for unknown usernames (pre-computed dummy hash). MFA gate before JWT issue. SAML strict signature + XSW check.
A08 Data Integrity created_at/updated_at mixin on every audit-relevant row. AuditLog row per security event. Alembic migrations idempotent.
A09 Logging & Monitoring Structured logger across backend, NotificationLog table, AuditLog table, /api/v1/audit/logs admin view.
A10 SSRF All outbound integrations whitelist-URL; no user-controllable URLs.

3. Component Details

3.1 Routers (app/routers/)

Each router groups a logical resource. All require JWT except /auth/* login endpoints.

Router Resource Key endpoints
auth.py Local login + MFA /auth/login, /auth/verify, /auth/mfa/{setup,activate,disable}, /auth/providers
auth_admin.py Provider config + role mapping /auth/admin/role-mappings, /auth/admin/{ldap,oidc,saml}/test
auth_oidc.py OIDC SSO /auth/oidc/login, /auth/oidc/callback
auth_saml.py SAML 2.0 SSO /auth/saml/login, /auth/saml/acs, /auth/saml/metadata
vulnerabilities.py Vulns, enrichment, overrides, sync /vulnerabilities, /vulnerabilities/sync/wazuh, /vulnerabilities/enrich/*, /vulnerabilities/override/*
nessus.py Tenable Nessus /vulnerabilities/nessus/{test,scans,sync,scan-host,cleanup-pseudo-cves}
assets.py Asset CRUD + assignment /assets, /assets/{id}, /assets/bulk-update, /assets/{id}/assign
scans.py Scan history + schedules /scans, /scans/summary, /scans/clear, /scans/autoscan, /scans/schedules
compliance.py SCA + URS /compliance/summary, /compliance/assets, /compliance/{asset_id}, /compliance/refresh, /compliance/impacts/{import,stats}, /compliance/urs[/...]
policies.py Security policies (SLA) /policies, /policies/{id}, /policies/bulk-update
groups.py User groups /groups, /groups/{id}, /groups/default
settings.py Key-value config /settings, /settings/{key}
notifications.py Mail log + test /notifications/log, /notifications/test, /notifications/notify-critical
reports.py CSV / PDF exports /reports/csv, /reports/pdf
audit.py Security audit trail /audit/logs

3.2 Services (app/services/)

Pure business logic, no FastAPI imports. Reusable from scheduler + routers.

Service Role
enrichment_service.py EPSS / KEV / EUVD enrichment per CVE, with 24h cache in settings
vuln_override_service.py 3-stage CVSS / SSVC / fixed_version cascade (Vulnrichment → NVD → cvelistV5)
override_jobs.py Async job tracker for the long-running "Correct CVSS" button
nessus_sync.py Per-scan import, asset matching cascade, pseudo-CVE handling
compliance_service.py Wazuh SCA pull + weighted-score computation per policy
compliance_impact_import.py CIS-Benchmark CSV importer with loose-header matching
urs_service.py AVS + ASS → URS formula, snapshot writes, daily prune
email_service.py SMTP send, per-recipient templates, digest + single modes

3.3 Integrations (app/integrations/)

Thin HTTP clients, no DB writes.

Client Purpose
wazuh_client.py OpenSearch indexer DSL — paginated vuln + SCA fetch
nessus_client.py REST API + plugin output parsing (fixed_version, VPR, host UUID)
ai_client.py LLM dispatcher (currently routes to Infomaniak)
infomaniak_ai_client.py Infomaniak chat-completion proxy

3.4 Auth Stack — Strategy Pattern

   POST /auth/login (username + password)
              │
              ▼
   ┌────────────────────────────┐
   │ AuthOrchestrator           │  chain = AUTH_LOOKUP_ORDER
   │ (env: local,ldap)          │
   └──┬─────────────────────────┘
      │  on success
      ▼
   ┌────────────────────────────┐
   │ MFA gate (if totp_enabled) │
   └──┬─────────────────────────┘
      │  OK
      ▼
   JWT (httpOnly cookie + bearer in response body)

   GET  /auth/oidc/login    ── PKCE redirect ── IdP
   POST /auth/oidc/callback ── JWKS-validated id_token → orchestrator.complete_sso_login()

   GET  /auth/saml/login    ── python3-saml AuthnRequest
   POST /auth/saml/acs      ── strict signature + XSW check → orchestrator.complete_sso_login()

JIT provisioning (auth.jit_provisioner) auto-creates User rows on first SSO/LDAP login. RoleMapper re-evaluates role on every login from external_groups, so AD-side membership changes apply immediately.

3.5 Scheduler (app/scheduler.py)

Job ID Cadence What it does
scheduler_sync every 60 s Picks up DB changes to scan_schedules and re-registers jobs
sla_breach_check every 1 h SLA-overdue scan; honors sla_breach_enabled toggle + PolicyStatus.DISABLED skip; digest or single mode
threat_intel_refresh every 24 h Refreshes EPSS, KEV, EUVD across all open vulns
compliance_sca_nightly 02:00 UTC Wazuh SCA pull for every linked asset
vulnrichment_nightly 03:00 UTC 3-stage CVSS/SSVC/fixed_version cascade
urs_nightly 04:00 UTC URS recompute + asset_risk_snapshots prune (>90d)
user-defined per schedule Per-scan_schedules row, routes to run_wazuh_vulnerability_sync or run_nessus_sync based on scanner_type

4. Data Model

See DATABASE_SCHEMA.md for column-level detail. High-level entities and their main relationships:

   User ─┐                            Policy ── 1:N ──┐
         │ M:N (user_groups)                          │
   Group ┴── 1:N ──┐                                  │
                   │                                  │
                   ▼ M:N (asset_groups)               ▼
                Asset ──── 1:N ────► Vulnerability ──── 1:N ──► AIAnalysis
                  │                       │
                  │ 1:N                   │ 1:N
                  ▼                       ▼
                Scan                  NotificationLog
                  │
                  └── 1:N ──► ComplianceResult ── 1:N ──► ComplianceCheck

   ComplianceImpact  (cis_id, benchmark)   ◄── lookup for weighted_score
   AssetRiskSnapshot (asset_id, snapshot_date, avs, ass, urs, severity)

   AuditLog          (user_id, event_type, …)
   Setting           (key, value)         ◄── KV store: smtp, nessus_config,
                                              enrichment flags, sla toggle,
                                              cache for EPSS/KEV/EUVD JSON,
                                              role-mapping JSON, etc.

Vulnerabilities carry a sources JSON list (["wazuh","nessus"]) so one row holds the union per (cve_id, asset_id). Non-CVE Nessus plugins land under pseudo-IDs NESSUS-PLUGIN-{plugin_id}.


5. API Endpoints (summary)

Full reference: see Router section above + Swagger UI at /docs. JWT auth required on everything except /auth/login, /auth/oidc/*, /auth/saml/*, /auth/setup-admin.

Group Examples
Auth POST /auth/login, POST /auth/verify (MFA), POST /auth/mfa/setup, POST /auth/oidc/login
Vulnerabilities `GET /vulnerabilities?source=wazuh
Assets GET /assets, POST /assets/{id}/assign, POST /assets/{id}/rescan
Scans GET /scans/summary, POST /scans/autoscan, POST /scans/schedules
Compliance / URS POST /compliance/refresh, POST /compliance/impacts/import (multipart), GET /compliance/urs?avs_mode=hybrid
Nessus POST /vulnerabilities/nessus/test, POST /vulnerabilities/nessus/sync
Settings PUT /settings/{key} (admin)

Query parameters of note on GET /api/v1/vulnerabilities:

status, severity, source, cross_confirmed, kev_only, euvd_only, eu_critical, in_any_catalog, in_both_catalogs, epss_min, assigned_to_me, host, package, cve_id, sort_by (cve_id|priority_score|cvss_score|cpr_score|detected_at|published_date|updated_at), sort_order, limit, offset.


6. Deployment Architecture

   docker-compose.yml
   ├── postgres     (volume: pgdata)
   ├── backend      (FastAPI + APScheduler)  ── alembic upgrade head on start
   └── frontend     (Next.js standalone build, served via node)

Environment configuration via .env (gitignored). Required keys:

DATABASE_URL=postgresql://vulnmanager:…@postgres/vulnmanager
JWT_SECRET=…                # rotate per deployment
AUTH_PROVIDER_CRYPTO_KEY=…  # Fernet, encrypts TOTP + LDAP bind pw

# Wazuh
WAZUH_API_URL=https://…:55000
WAZUH_INDEXER_URL=https://…:9200
WAZUH_API_USER=…
WAZUH_API_PASS=…

# Optional
DASHBOARD_URL=http://localhost:3000          # used in mail links
INFOMANIAK_API_KEY=…                          # AI analysis
LDAP_BIND_PASSWORD_BOOTSTRAP=…                # first-start LDAP setup
HTTPS_PROXY=…                                 # for outbound enrichment

Optional outbound HTTPS endpoints (firewall whitelist if locked-down):

  • https://api.first.org (EPSS)
  • https://www.cisa.gov (KEV)
  • https://euvdservices.enisa.europa.eu (EUVD)
  • https://raw.githubusercontent.com (Vulnrichment per-CVE + ZIPs)
  • https://github.com (cvelistV5 ZIP)
  • https://services.nvd.nist.gov (NVD REST)
  • https://nessus.your-internal/... (Nessus)

Upgrade flow

git pull origin dev
docker compose build backend frontend
docker compose up -d backend frontend
docker compose exec backend alembic upgrade head
docker compose exec backend alembic current   # expect: 022 (head)

7. Performance & Scaling

  • Wazuh-Indexer pagination beyond the OpenSearch 10 000-hit cap: search-after / scroll in WazuhClient.get_vulnerabilities.
  • Vulnrichment cascade auto-routes to ZIP snapshot when > 25 CVEs requested — avoids 25 × N raw fetches.
  • cvelistV5 ZIP (~557 MB) is on-disk-cached 12 h at /tmp/vulncheck-cvelistv5-cache.zip.
  • NVD stage caps at 100 CVEs per run (rate limit). >100 missing → falls through to cvelistV5 directly.
  • sources / enrichment_sources JSON columns avoid table-join chatter for per-vuln source filtering.
  • Indexed columns: cve_id, asset_id, cvss_score, severity, epss_score, kev_listed, euvd_listed, exploitation_status, ssvc_technical_impact, ssvc_automatable, nessus_vpr_score, nessus_plugin_id, package_name, detected_at.
  • "Correct CVSS" runs as an async job (override_jobs.py) so the UI returns immediately with a job_id and a polling progress card — full-DB corrections take 5-20 min.

8. Monitoring & Observability

  • Structured logger to stdout; docker compose logs backend is the primary view.
  • AuditLog captures security-relevant events (login success / failure, role change, MFA reset, password change, deletes).
  • NotificationLog records every mail attempt (status, error, recipient).
  • /scans/summary surfaces sync history with per-run vuln deltas.
  • /notifications/log lists outbound mail history with retry status.
  • APScheduler logger prints next_run + last_run per job.

Recommended Prometheus exporters: postgres_exporter, node_exporter, and a thin /healthz endpoint on the FastAPI side (returns DB ping + scheduler status). Not yet shipped — placeholder for future ops work.


9. Development Roadmap

See README.DEV.md "Out of scope" sections for the live backlog. Big-ticket items currently parked:

  • WebAuthn / FIDO2 second factor
  • Per-framework URS breakdown (URS_CIS / URS_ISO27001 / URS_NIS2)
  • SCIM v2 endpoint for IdP-driven provisioning
  • endoflife.date integration for EOL/EOS package detection
  • Real-time KEV push from Wazuh (currently poll-based)
  • Two-way Nessus false-positive sync
  • Concentration penalty on URS (≥ 3 high-impact failures → +10)
  • Settings-UI toggle for sla_breach_enabled (currently DB-only)