# TI-Monitor

Telematikinfrastruktur-Ueberwachung fuer IKK Kliniken — KoCoBox MED+ und RISE Konnektoren, KoCoBox-Managementschnittstelle (Karten, Terminals, Zertifikate, System) **und** ORGA Kartenterminals (6141 online / Neo).

Echtzeit-Monitoring der gesamten TI-Infrastruktur eines Standorts: Konnektor-Erreichbarkeit, gSMC-K-Zertifikate, alle gesteckten Karten (eGK/HBA/SMC-B/SMC-KT) mit Ablaufdatum und PIN-Status, Terminal-Status, Online-PIN-Freischaltung. Laeuft **lokal im Klinik-Netzwerk** — keine Cloud, keine externen Abhaengigkeiten, keine Daten verlassen das Haus. Admin-Passwoerter und SMC-B-PINs werden Fernet-verschluesselt mit maschinengebundenem Schluessel abgelegt.

## Architektur

```
┌─────────────────────────────────────────────────┐
│  TI-Monitor (localhost:8443)                     │
│                                                  │
│  main.py ─── FastAPI + uvicorn                   │
│  ├── Polling-Loop (async, 10-300s Intervall)     │
│  ├── httpx → profilbasierte Konnektor-Checks     │
│  ├── ssl/socket → Zertifikats-Analyse            │
│  ├── SSE → Browser Live-Updates                  │
│  └── JSON-Persistenz (config + history)          │
│                                                  │
│  static/index.html ─── Single-File Dashboard     │
│  static/produkt.html ── Produktseite             │
└──────────────┬──────────────────────────────────┘
               │ HTTPS :9443 / :8443 / :443
      ┌────────▼────────┐
      │ TI-Konnektor    │  (KoCoBox, RISE, TLS)
      │ Admin + SDS     │
      └─────────────────┘
```

**Single-File-Architektur:** Das komplette Projekt besteht aus `main.py` (Backend) und `static/index.html` (Frontend). Keine Datenbank, kein Build-Prozess, kein Docker.

## Features

| Feature | Beschreibung |
|---|---|
| Live-Dashboard | Status-LEDs je Geraet, Echtzeit via SSE |
| Polling-Loop | Konfigurierbares Intervall (10–300 Sekunden) |
| Herstellerprofile | KoCoBox MED+, RISE Konnektor, generischer TLS-Check |
| Netzwerksuche | Lokale CIDR-Suche nach KoCoBox, RISE, generischen TLS-Endpunkten und ORGA-Hinweisen |
| SSL-Zertifikats-Check | Ablaufdatum und Issuer automatisch auslesen |
| 30-Punkt Timeline | Visuelle Verfuegbarkeits-Historie je Geraet |
| Failure-Counter | Alert-Schwelle konfigurierbar (Standard: 3) |
| Browser-Notifications | Desktop-Benachrichtigung bei Ausfall |
| Beep-Alert | Akustischer Alarm bei Statuswechsel |
| CRUD Konnektoren + Terminals | Hinzufuegen, Bearbeiten, Loeschen, Aktivieren/Deaktivieren |
| ORGA-Status-Scrape | Produktversion, gSMC-KT ECC/RSA Ablauf, TLS-/VPN-/SICCT-Status, TSL-Liste |
| SMC-B-Karten-Status | ICCSN, PIN-Status (verified/transport/blocked), Slot, Channels |
| Online-PIN-Button | SMC-B mit Klick aus dem Dashboard entsperren |
| Auto-Reactivate (optional) | SMC-B nach Stromausfall automatisch entsperren — max. 1×/Tag |
| KoCoBox Managementschnittstelle | Login als `koco-root`, **alle 5 Dienste** auslesen: Kartendienst (alle Karten mit ICCSN/Slot/Ablauf), Kartenterminaldienst, Zertifikatsdienst, Systeminformations-, Protokollierungsdienst |
| Klinik-weite Ablauf-Warnung | Banner zeigt Anzahl Karten <30/<90 Tage Restlaufzeit ueber alle KoCoBoxen |
| Karten-Detailansicht | Tabelle aller eGK/HBA/SMC-B/SMC-KT mit Filter und Sortierung nach Ablauf |
| Terminal-Auto-Befuellung | Aus der KoCoBox erkannte Kartenterminals lassen sich per Klick als Monitor-Terminal anlegen |
| Verschluesselte Secrets | KoCoBox-Passwort + ORGA-Admin-Passwort + SMC-B-PIN per Fernet (PBKDF2-SHA256, 100k Iterationen) |
| Port-Fallback | 8443 belegt → automatisch 8444 |

## Voraussetzungen

- Windows 10/11 oder Windows Server 2016+
- Python 3.10+
- Netzwerkzugriff auf den Konnektor
  - KoCoBox MED+: Port 9443
  - RISE Konnektor: Management-Port 8443, Dienstverzeichnis auf 443/80
- Freier Port 8443 (Fallback 8444)
- Fuer den lokalen Health-Check kein Internet erforderlich; Lizenz- und Updatepruefung verwenden c3po42.de
- Kein Admin-Recht fuer den Betrieb noetig

## Installation

### Einzeiler (empfohlen)

```powershell
irm https://downloads.c3po42.de/ti-monitor/install.ps1 | iex
```

Installiert nach `C:\TI-Monitor`, richtet Python-Abhaengigkeiten ein und startet das Dashboard.

### Manuell

```bash
# Abhaengigkeiten installieren
pip install -r requirements.txt

# Starten
python main.py
```

Der Browser oeffnet automatisch `http://localhost:8443`.

## Dateien

```
C:\TI-Monitor\
├── main.py              # FastAPI Backend (komplettes Backend in einer Datei)
├── requirements.txt     # Python-Abhaengigkeiten (fastapi, uvicorn, httpx)
├── config.json          # Konnektoren + Einstellungen (wird automatisch erstellt)
├── history.json         # Check-Historie (wird automatisch erstellt)
├── CLAUDE.md            # Claude Code Kontext
├── README.md            # Diese Datei
├── BENUTZERHANDBUCH.md  # Anleitung fuer Endbenutzer
└── static/
    ├── index.html       # Single-File Dashboard (HTML + CSS + JS)
    └── produkt.html     # Produktseite
```

## Konfiguration

Die Konfiguration wird in `config.json` gespeichert (automatisch erstellt beim ersten Konnektor):

```json
{
  "konnektoren": [
    {
      "id": "a1b2c3d4",
      "name": "KoCoBox Haupthaus",
      "ip": "192.168.1.100",
      "standort": "IKK Haupthaus",
      "profile": "kocobox",
      "port": 9443,
      "enabled": true,
      "koco_username": "koco-root",
      "koco_password_enc": "gAAAAAB...",
      "scrape_kartendienst": true
    }
  ],
  "terminals": [
    {
      "id": "f5e6d7c8",
      "name": "ikt-smcb-2",
      "ip": "10.120.33.12",
      "standort": "Anmeldung Raum 2",
      "port": 443,
      "hersteller": "ORGA",
      "enabled": true,
      "smcb_slot": 1,
      "auto_reactivate_smcb": false,
      "admin_password_enc": "gAAAAAB...",
      "smcb_pin_enc": "gAAAAAB..."
    }
  ],
  "settings": {
    "poll_interval_seconds": 30,
    "alert_after_failures": 3
  }
}
```

**Verschluesselung:** `admin_password_enc` und `smcb_pin_enc` sind Fernet-Tokens. Der Schluessel wird aus Hostname + Benutzername + einem zufaelligen Salt unter `%LOCALAPPDATA%\TI-Monitor\.key` abgeleitet (PBKDF2-SHA256, 100 000 Iterationen). Eine kopierte `config.json` ist auf einem anderen Rechner nutzlos.

## API-Endpunkte

| Methode | Pfad | Beschreibung |
|---|---|---|
| `GET` | `/api/events` | SSE-Stream fuer Live-Updates |
| `GET` | `/api/konnektoren` | Liste aller Konnektoren mit Status |
| `GET` | `/api/profiles` | Verfuegbare Herstellerprofile |
| `GET` | `/api/discovery/defaults` | Lokale Netzvorschlaege fuer die Geraetesuche |
| `POST` | `/api/discovery/scan` | Privates IPv4-Netz scannen, z.B. `{"cidr": "192.168.1.0/24"}` |
| `POST` | `/api/konnektoren` | Konnektor hinzufuegen (Body kann `koco_password` + `scrape_kartendienst` enthalten) |
| `PUT` | `/api/konnektoren/{id}` | Konnektor bearbeiten (Passwort nur, wenn neu uebergeben) |
| `DELETE` | `/api/konnektoren/{id}` | Konnektor entfernen |
| `GET` | `/api/konnektoren/{id}/details` | Volle KoCoBox-Detaildaten (Karten, Terminals, Zertifikate, System, Protokoll) |
| `POST` | `/api/konnektoren/{id}/scrape` | Sofort-Scrape der Managementschnittstelle ausloesen |
| `GET` | `/api/terminals` | Liste aller Kartenterminals mit Status |
| `POST` | `/api/terminals` | Terminal hinzufuegen (Body: `name, ip, port, admin_password, smcb_pin?, smcb_slot?, auto_reactivate_smcb?`) |
| `PUT` | `/api/terminals/{id}` | Terminal bearbeiten (Passwort/PIN nur, wenn neu uebergeben) |
| `DELETE` | `/api/terminals/{id}` | Terminal entfernen |
| `POST` | `/api/terminals/{id}/pin` | SMC-B-PIN ans Terminal senden (optional `{"pin": "1234"}` im Body, sonst gespeicherte PIN) |
| `GET` | `/api/history/{id}` | Check-Historie eines Geraets (Konnektor oder Terminal) |
| `POST` | `/api/check/{id}` | Sofortigen Check ausloesen |
| `GET` | `/api/settings` | Einstellungen abrufen |
| `PUT` | `/api/settings` | Einstellungen aendern |

### Konnektor hinzufuegen (Beispiel)

```bash
curl -X POST http://localhost:8443/api/konnektoren \
  -H "Content-Type: application/json" \
  -d '{"name": "KoCoBox Haupthaus", "ip": "192.168.1.100", "standort": "Haupthaus", "profile": "kocobox", "port": 9443}'
```

### Polling-Intervall aendern

```bash
curl -X PUT http://localhost:8443/api/settings \
  -H "Content-Type: application/json" \
  -d '{"poll_interval_seconds": 60, "alert_after_failures": 5}'
```

## SSE-Events

Der `/api/events`-Endpunkt sendet folgende Event-Typen:

| Typ | Beschreibung |
|---|---|
| `init` | Initial-Status aller Konnektoren + Terminals beim Verbindungsaufbau |
| `check` | Ergebnis eines Geraete-Checks (mit `geraete_typ`, `geraete_id`, `alert`) |
| `added` | Neues Geraet hinzugefuegt (`geraete_typ` + `geraet`) |
| `updated` | Geraete-Daten geaendert |
| `deleted` | Geraet entfernt |
| `pin_result` | Ergebnis eines manuellen SMC-B-PIN-Versuchs |
| `auto_reactivate` | Ergebnis eines automatischen SMC-B-PIN-Versuchs |
| `scrape_done` | KoCoBox-Sofort-Scrape abgeschlossen, Zaehler + Alarme im Event |

## Tech-Stack

- **Backend:** Python 3.10+, FastAPI, uvicorn
- **HTTP-Client:** httpx (async, SSL-tolerant)
- **SSL-Analyse:** Python `ssl` + `socket` Standardbibliothek
- **Frontend:** Vanilla HTML/CSS/JS, Single-File, Dark Theme (Cyan #06b6d4)
- **Fonts:** Fredoka + Space Mono (Google Fonts)
- **Persistenz:** JSON-Dateien (kein DB-Server noetig)
- **Echtzeit:** Server-Sent Events (SSE)

## Konnektor Health-Check

Der Monitor prueft jeden Konnektor gemaess Profil:

| Profil | Default-Port | Pruefung |
|---|---:|---|
| `kocobox` | 9443 | `https://{ip}:{port}/administration/start.htm` |
| `rise` | 8443 | `https://{ip}:{port}/` plus `https://{ip}/connector.sds`, Fallback `http://{ip}/connector.sds` |
| `generic_tls` | 443 | `https://{ip}:{port}/` plus TLS-Zertifikat |

KoCoBox und RISE werden nur dann als **Profil erkannt** markiert, wenn der jeweilige Profilcheck passt. Ein bloss erreichbarer HTTPS-Dienst reicht fuer RISE nicht mehr aus, um versehentlich KoCoBox-Kompatibilitaet vorzutaueschen.

## Netzwerksuche

Die Netzwerksuche laeuft vom TI-Monitor-Server aus und ist auf lokale/private IPv4-Netze begrenzt. Standardmaessig schlaegt der Monitor das lokale `/24`-Netz des Rechners vor und scannt maximal 512 Hosts.

Erkannt werden:
- KoCoBox MED+ ueber `https://{ip}:9443/administration/start.htm`
- RISE ueber `https://{ip}:8443/` und `connector.sds` auf 443/80
- ORGA-/Kartenterminal-Hinweise ueber die HTTPS-Startseite auf Port 443
- Generische TLS-Endpunkte als niedrige Konfidenz

Treffer koennen im Dashboard direkt in das passende Hinzufuegen-Modal uebernommen werden. Bereits erfasste IP/Profile werden als bekannt markiert.

### Optional: KoCoBox-Managementschnittstelle (Login)

Wenn im Konnektor-Eintrag ein KoCoBox-Passwort hinterlegt ist und der Schalter "Karten/Terminals/Zertifikate auslesen" aktiv ist, fuehrt jeder Polling-Zyklus zusaetzlich aus:

1. **Login** als `koco-root` per Form-Post (Pfad-Discovery: `/management/j_security_check`, `/management/login`, ...). Session-Cookie wird ~10 Min gehalten.
2. **Kartendienst:** Tabelle aller Karten mit `kartenterminal-i`, `kartenterminal-hostname`, `slot`, `typ`, `kartenbesitzer`, `iccsn`, `version`, `ablauf` — exakt die Felder aus der Web-UI. Daraus werden die Klinik-weiten Alarme berechnet (`<30 Tage`, `<90 Tage`).
3. **Kartenterminaldienst:** registrierte Terminals mit `ct-id`, `hostname`, `ip`, `status` — Basis fuer "Terminal uebernehmen".
4. **Zertifikatsdienst:** Konnektor-eigene Zertifikate (gSMC-K, NK-VPN, SIS) mit Ablaufdatum.
5. **Systeminformationsdienst:** Firmware-Version, Hardware, Kryptosystem (RSA/ECC), Uptime.
6. **Protokollierungsdienst:** zaehlt Fehler/Warnungen in der letzten Protokoll-Seite.

> KoCoBox stellt keine offiziell dokumentierte REST-API bereit. Login-, Listen- und Inhalts-Pfade werden aus einer Liste von Kandidaten probiert (`KOCO_*_PATHS` in `main.py`). Falls eine Firmware abweicht, einfach den richtigen Pfad ergaenzen.

## ORGA Kartenterminal Check

1. **HTTPS GET** an `https://{ip}/` — Erreichbarkeit + Response-Time
2. **SSL-Zertifikat** der Web-UI
3. Wenn ein Admin-Passwort hinterlegt ist:
   - **Login** per Form-Post (`remoteAdminPassword`), Session-Cookie wird ~10 Minuten gehalten
   - **Status-Scrape:** Produktversion, Serien-Nr., MAC, IP-Konnektor, TLS-Status, SICCT-Session, VPN-Status, Aktive TSL-Liste, gSMC-KT ECC + RSA Ablauf
   - **SMC-B Service-Tab:** ICCSN, PIN-Status (`verified | transport | blocked | missing`), Slot, Channels, Remote-PIN-Schalter
4. **Auto-Reactivate** (wenn pro Terminal aktiviert): bei PIN-Status `transport` oder `missing` wird die hinterlegte SMC-B-PIN einmal pro Tag automatisch gesendet — niemals bei `blocked`.

> ORGA stellt keine offiziell dokumentierte REST-API bereit. Login-, Status- und PIN-Pfade werden aus einer kandidatenweisen Liste probiert (`/login`, `/api/login`, `/auth/login` usw.). Falls eine Firmware abweicht, einfach den richtigen Pfad in `main.py` (Konstanten `ORGA_*_PATHS`) ergaenzen.

## Download

- Download-Seite: https://downloads.c3po42.de/ti-monitor/
- Deploy der Download-Seite: `python deploy_downloads.py`
