OPEN BETA
OPEN BETA

Technische Architektur

Ein tiefer Einblick in den YADS Stack — von der Datenbank bis zum Scanner-Modul.

Stack Übersicht

YADS ist eine vollständig containerisierte Plattform, die auf bewährten Open-Source-Komponenten aufbaut. Kein proprietäres Middleware-Labyrinth — jede Schicht ist austauschbar und direkt überprüfbar.

Browser / API-Clients

Nginx Reverse Proxy

not included

TLS-Terminierung, Rate Limiting, Security-Header

empfohlen · separates Repository
Application Layer

FastAPI Core API

REST-Endpunkte + Jinja2 Server-Side Rendering

yads-api · Port 8000
Messaging & Task Execution

RabbitMQ Broker

Task-Queue für Celery-Jobs (AMQP)

BROKER_URL

Celery Worker

Parallele Scan-Ausführung aller 88+ Module

yads-worker

Valkey / Redis

Result Backend + Echtzeit Log-Streaming

REDIS_URL
Scheduler

Python Scheduler Loop

60s-Takt, dispatcht fällige Scans, bereinigt hängende Jobs

scheduler.py · kein celery beat
Persistence

PostgreSQL 15

Relationale Daten + JSONB für flexible Scan-Ergebnisse

yads-db · Port 5432

Volume Mounts

Persistente Konfiguration, Zertifikate, Upload-Artefakte

docker volumes

Kernkomponenten im Detail

Jeder Dienst hat eine klar definierte Verantwortlichkeit. Hot-Reload über Volume-Mounts ermöglicht schnelle Entwicklungszyklen ohne Docker-Rebuild.

FastAPI Core API

Das Herzstück von YADS. Steuert alle UI-Anfragen (Server-Side Rendering mit Jinja2-Templates), REST-Endpunkte für externe Clients sowie die Scan-Orchestrierung. Enthält ~50 Router-Dateien für saubere Trennung nach Domäne.

FastAPI Jinja2 SQLModel Pydantic v2 Python 3.12
🔄

Celery Worker

Führt alle Scanner-Module asynchron aus. Jeder Scan-Task erhält ein definiertes Timeout (3600s hard, 3480s soft). Prefetch ist bewusst auf 1 gesetzt, um Worker-Stau bei langen Scans zu vermeiden. Kein celery beat — periodische Tasks laufen direkt im Scheduler-Loop.

Celery 5 RabbitMQ (AMQP) Valkey Result Backend
🗄️

PostgreSQL 15 + JSONB

Relationale Kerndaten (Targets, Tenants, User, Findings) mit JSONB-Feldern für Scanner-Rohdaten. Verschlüsselte Felder via EncryptedString TypeDecorator. Migrationen laufen beim Container-Start über ein dediziertes Migrationsskript — kein Alembic.

PostgreSQL 15 JSONB EncryptedString AES-256
📡

RabbitMQ Task Broker

Übernimmt die zuverlässige Task-Auslieferung an Celery-Worker. Wird über BROKER_URL konfiguriert. Separate Queue pro Priorität ermöglicht Priorisierung kritischer Sofort-Scans gegenüber geplanten Bulk-Jobs.

RabbitMQ AMQP
🔴

Valkey / Redis

Doppelte Funktion: Celery Result Backend für Task-Status-Tracking und Echtzeit-Log-Streaming an die UI über Server-Sent Events (SSE). Valkey ist ein BSD-3-lizenzierter Redis-Fork und ersetzt seit YADS 2.0 das frühere Redis 7 (SSPL).

Valkey 8 SSE Streaming Pub/Sub
🛡️

Nginx Reverse Proxy

BSI TR-02102-2 konforme TLS-Konfiguration (TLS 1.2/1.3). Rate Limiting (10 req/s, Burst 20), SNI-Enforcement, WAF-lite gegen Bad Bots und bekannte Injection-Muster. Läuft als unprivilegierter nginx-User.

Nginx Alpine TLS 1.2/1.3 BSI TR-02102-2 HSTS

Scan Pipeline

Von der Ziel-Erfassung bis zum Security Finding — der komplette Weg eines Scans durch das System.

1

Ziel registrieren

Ein Target (Domain, IP, CIDR) wird in der Datenbank angelegt und einem Tenant zugeordnet. Scan-Typ und Intervall werden konfiguriert.

2

Scheduler dispatcht

Der Scheduler-Loop (60s Takt) prüft fällige Targets und sendet Celery-Tasks an den RabbitMQ-Broker. Hängende Scans werden alle 5 Minuten automatisch zurückgesetzt.

3

Celery Worker übernimmt

Ein Worker zieht den Task aus der Queue. Die Modul-Registry lädt alle für den Scan-Typ registrierten Module. Parallele Ausführung per asyncio innerhalb des Workers.

4

Scanner-Module laufen

88+ Module führen spezialisierte Checks durch: DNS-Aufklärung, TLS-Analyse, Web-Scan, Port-Scan, Kryptografie-Bewertung, Threat-Intel-Lookup, Cloud-Storage-Prüfung u.v.m. API-Keys werden tenant-spezifisch oder über globale Env-Vars aufgelöst.

5

Ergebnisse & Deduplizierung

Scan-Ergebnisse werden als ScanResult-Objekte mit SHA256-Hash gespeichert. Nur wenn sich der Hash gegenüber dem Vorscan ändert, wird ein ChangeEvent erzeugt — kein Rauschen durch unveränderte Ergebnisse.

6

Security Findings

Neue Schwachstellen erhalten eine sequenzielle YF-ID (YF-000001 bis YF-999999). Status-Lifecycle: open → acknowledged → fixed / false_positive. Auto-Close wenn ein Finding im nächsten Scan nicht mehr auftaucht. Auto-Reopen wenn es wieder erscheint.

7

SLA-Tracking & Benachrichtigung

Pro Finding wird eine SLA-Frist berechnet (BSI-Defaults: Critical 7d, High 30d, Medium 90d, Low 180d), die pro Tenant konfigurierbar ist. Überfällige Findings erscheinen prominent im Dashboard.


Kernmodell Daten

Die wichtigsten Entitäten und ihre Beziehungen im YADS Datenbankschema.

Entität Zweck Wichtige Felder
Tenant Mandant / Organisation name, license_key, sla_critical, sla_high
Target Zu scannende Domäne oder IP hostname, scan_status, last_scanned_at, scan_interval
ScanResult Rohdaten eines Modul-Runs module, data (JSONB), scanned_at, sha256_hash
SecurityFinding Persistente Schwachstelle yf_id, severity, status, evidence_data (JSONB), sla_due
ChangeEvent Änderungsprotokoll target_id, module, detected_at, diff_summary
TenantApiKey Tenant-spezifische API-Keys für Scanner key_name, encrypted_value, tenant_id
User Plattform-Benutzer email, tenant_id, role, mfa_secret

Multi-Tenant Architektur

YADS trennt Daten strikt nach Mandanten. Alle Datenbankabfragen werden automatisch auf tenant_id gefiltert — kein Cross-Tenant-Datenleak durch Fehler in der Geschäftslogik möglich.

Datenisolation Jede Query filtert auf tenant_id
API-Keys pro Tenant Shodan, VirusTotal etc. tenant-spezifisch konfigurierbar
SLA pro Tenant Individuelle Fristen für Critical/High/Medium/Low
Platform Admin Sieht alle Tenants, kann zwischen ihnen wechseln
Quota-Tracking Optionales Max-Targets-Limit pro Tenant, Live-Anzeige im Header

Modul System

Scanner-Module sind eigenständige Python-Klassen, die von BaseScannerModule erben. Neue Module können ohne Änderungen am Core hinzugefügt werden — reine Plug-in-Architektur.

🔌

BaseScannerModule

Abstrakte Basisklasse für alle Scanner. Definiert run_scan(target, db, tenant_id) und api_key_specs. Module registrieren sich automatisch in der REGISTRY beim Import.

yads/core/base.py
🗝️

ApiKeySpec System

Module deklarieren ihre API-Key-Anforderungen via ApiKeySpec. Die UI rendert automatisch Eingabefelder in den Tenant-Einstellungen. Keys werden tenant-spezifisch oder über globale Env-Vars aufgelöst.

TenantApiKey Tabelle EncryptedString Env-Fallback
📦

Add-on System

Erweiterte Module werden als Add-ons separat installiert (yads-addons/). Installation über die Admin-UI, Signaturprüfung per ZIP-Validation.

ZIP-Upload Signaturprüfung
Modulkategorie Beispiele Verfügbarkeit
DNS & Subdomain Subdomain-Enumeration, DNSSEC, SPF/DMARC/DKIM Core
Web & TLS HTTP-Header-Analyse, TLS-Konfiguration, Zertifikat-Monitoring Core
Kryptografie & PQC Cipher-Suite-Analyse, PQC-Readiness, CBOM-Generierung Core
Threat Intelligence VirusTotal, Shodan, Censys, Blacklist-Checks Core
OSINT & Recon WHOIS, ASN-Lookup, Screenshot, Visual OSINT Core
Compliance & Supply Chain JavaScript Supply Chain, Cookie Consent, Third Party Risk Add-on
Cloud & Infrastructure Cloud Storage Deep Scan, Kubernetes Exposure, CI/CD Exposure Add-on
Brand & Mobile Brand Monitor, Mobile App Monitor, Exposed Admin Panel Add-on

Design Entscheidungen

Bewusste Architekturentscheidungen, die YADS von typischen SaaS-Plattformen unterscheiden.

Warum

Kein SPA-Framework

Server-Side Rendering via Jinja2 statt React/Vue. Ergebnis: keine komplexe Frontend-Build-Pipeline, vollständige HTML-Antworten indexierbar, keine CORS-Probleme, extrem schnelles TTFB.

Warum

Kein celery beat

Statt eines separaten Scheduler-Prozesses läuft ein einfacher Python-Loop mit 60s-Takt direkt im API-Container. Weniger moving parts, einfacheres Deployment, keine Beat-Worker-Synchronisationsprobleme.

Warum

Kein Alembic

Manuelle SQL-Migrationen in einem einzigen Skript (migrate_db.py), das beim Container-Start automatisch läuft. Gibt vollständige Kontrolle über die Migrationreihenfolge und vermeidet automatische Schema-Destructionen.

Warum

RabbitMQ statt Redis als Broker

RabbitMQ bietet echte AMQP-Semantik mit zuverlässiger Nachrichtenauslieferung, Dead-Letter-Queues und Message-Durability. Redis-als-Broker hat keine Garantien bei Worker-Crash während der Task-Ausführung.

Warum

JSONB für Scanner-Daten

Scanner-Ergebnisse haben unterschiedliche Strukturen je nach Modul. JSONB erlaubt schemafreie Speicherung mit vollem Index-Support. Kernfelder (severity, status) bleiben als typed columns für performante Queries.

Warum

Valkey statt Redis 7

Redis 7.4+ steht unter der SSPL-Lizenz, die für Self-Hosted-Produkte problematisch sein kann. Valkey ist der offizielle BSD-3-Clause-Fork, vollständig kompatibel, aktiv entwickelt von der Linux Foundation.

Warum

SHA256-basierte Deduplizierung

Scan-Ergebnisse werden gehasht. Nur bei Hash-Änderung wird ein ChangeEvent erzeugt. Verhindert Alert-Fatigue durch wiederholte Benachrichtigungen für unveränderte Befunde — ein kritisches Feature für produktive SOC-Teams.

Warum

Self-Hosted First

Alle Scan-Daten bleiben in der eigenen Infrastruktur. Keine Cloud-Abhängigkeit für Kernfunktionen. YADS läuft vollständig offline — relevant für regulierte Branchen (KRITIS, DORA, NIS2).


Sicherheitsarchitektur

Sicherheit ist kein nachgelagtertes Feature, sondern von Anfang an Teil jeder Komponente.

🔐

Authentifizierung & MFA

Session-basiertes Login mit signiertem JWT-Cookie. MFA via TOTP für Administratorrollen verpflichtend. BSI-Passwortrichtlinie: min. 12 Zeichen, 3 von 4 Zeichenklassen.

TOTP MFA signed Cookies BSI-Passwortpolicy
🛡️

CSRF-Schutz

Double-Submit-Cookie Pattern: Der CSRF-Token wird als Cookie gesetzt und muss als X-CSRF-Token-Header bei jedem State-ändernden Request mitgesendet werden. Signierte Cookies verhindern Token-Fälschung.

Double-Submit Cookie X-CSRF-Token Header
🔑

Verschlüsselung at Rest

Sensitive Datenbankfelder (API-Keys, Secrets) werden transparent via EncryptedString TypeDecorator ver- und entschlüsselt. Der Encryption-Key wird über YADS_ENCRYPTION_KEY aus der Umgebung geladen.

AES-256 EncryptedString Env-Key
🧱

Input-Validierung

Pydantic v2-Schemas validieren alle API-Eingaben. ZIP-Upload-Validation für Add-on-Installation verhindert Path Traversal. Strikte Regex-Validierung von Python-Identifiern schützt vor Import-Injection.

Pydantic v2 ZIP-Validation Regex-Guards
📊

Rate Limiting

Nginx-Level Rate Limiting: 10 Requests/Sekunde pro IP, Burst 20. Login-Endpunkte zusätzlich mit strengerem Limit. SSRF-Schutz in Webhook-Endpunkten verhindert interne Netzwerkzugriffe.

Nginx Rate Limit Login Throttling SSRF-Schutz
⚛️

PQC-Readiness

YADS scannt aktiv auf Post-Quantum-Kryptografie-Readiness — über alle relevanten TLS-Ports hinweg (443, 8443, 993, 465, 587, 636). Eine vierstufige Probe-Hierarchie (Nmap → sslyze → openssl s_client → stdlib) erkennt Hybrid-KEX-Gruppen wie X25519MLKEM768 (NIST FIPS 203). Zertifikat-Signaturen werden auf ML-DSA (FIPS 204) und SLH-DSA (FIPS 205) geprüft. CBOM-Generierung (Cryptography Bill of Materials) im CycloneDX-Format für jeden Release-Zyklus.

PQC Scanner CBOM ML-KEM ML-DSA sslyze Multi-Port