Server-Bibliothek
2026-07-23 548bab93e55f6e514557571d3c9da9b1c1d59c35
ARCHITEKTUR.md
@@ -146,45 +146,101 @@
## 6. "Rechner einrichten" – Verteilungs-Mechanismus
Route `/einrichten` (app.py) erzeugt bei Bedarf ein individuelles
Installations-Paket (ZIP mit `einrichten.ps1` + `Rechner-einrichten-starten.bat`),
Installations-Paket (ZIP mit `einrichten.ps1` + `Rechner-einrichten-starten.bat`
**+ den echten Installer-Dateien/ZIPs selbst** unter `tools/<id>.<endung>`),
statt vorab für jede Mitarbeiter/Tool-Kombination ein festes Skript zu pflegen.
**Wichtige Design-Entscheidung (Runde r16):** Die Installer-Dateien werden
bereits beim Erzeugen des Pakets (auf dem PC, der die Checkliste ausfüllt)
eingebettet, nicht erst beim Ausführen auf dem Zielrechner nachgeladen. Ein
früherer Ansatz lud die Dateien per `Invoke-WebRequest` zur Laufzeit vom
Server nach – das erforderte Netzwerkzugriff des Zielrechners auf den Server
in genau dem Moment der Einrichtung, was in der Praxis nicht immer gegeben
ist (z. B. Rechner noch nicht ans Firmennetz angebunden). Jetzt braucht der
Zielrechner für die eigentliche Installation **kein Netzwerk mehr** – nur die
abschließende, optionale Meldung ans zentrale Protokoll (`/zuweisungen/neu`)
versucht noch einen Netzwerkzugriff, scheitert dieser, bleibt trotzdem das
lokale Protokoll (`protokoll.log`) vollständig.
Ablauf beim Ausführen auf dem Zielrechner:
1. `.bat` kopiert sich selbst + das `.ps1` nach `C:\ClientBibliothek`
1. `.bat` kopiert den **kompletten entpackten Ordner** (inkl. `tools/`-
   Unterordner mit den echten Installer-Dateien) nach `C:\ClientBibliothek`
   (per `xcopy /E /I /Y`)
2. Self-Elevation (Admin-Rechte-Anfrage) über `Start-Process -Verb RunAs`
3. Automatische Windows-Defender-Ausnahme für `C:\ClientBibliothek`
   (`Add-MpPreference -ExclusionPath`) – ein einziger Pfad statt vieler
   Einzelausnahmen
4. Pro ausgewähltem Tool: entweder stille Installation (Download + Ausführung
   mit hinterlegtem Silent-Parameter, `.msi` läuft über `msiexec`) oder – bei
   Tools ohne einzelne Installer-Datei ("Ordner-Typ", z. B. portable
   Programme wie Blender) – Download als ZIP nach `C:\ClientBibliothek\pakete\`,
   **bewusst ohne automatisches Entpacken** (Entscheidung in Runde r14: der
   Zielort für portable Tools variiert, das soll eine Person bewusst
4. Pro ausgewähltem Tool: entweder stille Installation aus der **lokal
   mitgelieferten** Datei unter `tools/<id>.<endung>` (mit hinterlegtem
   Silent-Parameter, `.msi` läuft über `msiexec`) oder – bei Tools ohne
   einzelne Installer-Datei ("Ordner-Typ", z. B. portable Programme wie
   Blender) – die mitgelieferte ZIP-Datei wird nach `C:\ClientBibliothek\pakete\`
   kopiert, **bewusst ohne automatisches Entpacken** (Entscheidung in Runde
   r14: der Zielort für portable Tools variiert, das soll eine Person bewusst
   entscheiden)
5. Lokales Protokoll unter `C:\ClientBibliothek\protokoll.log`
6. Automatischer POST an `/zuweisungen/neu` auf dem Server, um das zentrale
6. Optionaler POST an `/zuweisungen/neu` auf dem Server, um das zentrale
   Protokoll zu befüllen (Rechnername wird dabei über `$env:COMPUTERNAME`
   automatisch erkannt)
   automatisch erkannt) – best effort, kein Abbruch bei Fehlschlag
Die Ordner-Struktur unter `C:\ClientBibliothek`:
- `\downloads` – transiente Installer-Dateien, werden nach Gebrauch gelöscht
- `\tools` – die mitgelieferten Installer-Dateien/ZIPs (Quelle für die
  Installation, kommen direkt aus dem heruntergeladenen Paket)
- `\pakete` – ZIPs von portablen Tools, bleiben bewusst liegen
- `\protokoll.log` – lokale Mitschrift
Serverseitig teilen sich `/einrichten` (POST) und `/software/<id>/download`
die Hilfsfunktion `_zippe_ordner_in_bytes()` für das ZIP-Packen eines
Ordners, um Code-Duplikation zu vermeiden.
**Der Client-Ordner-Pfad ist eine Konstante** (`CLIENT_ORDNER` in `app.py`,
aktuell `C:\ClientBibliothek`) – zentral anpassbar, falls die Infrastruktur
einen anderen Standardpfad vorgibt.
## 6a. Zugriffsbeschränkung: lokal (Server) vs. Netzwerk
Seit Runde r17 unterscheidet die Anwendung, ob eine Anfrage direkt vom Server
selbst kommt (z. B. per RDP-Sitzung, im Browser dort `localhost`/`127.0.0.1`
aufgerufen) oder über das Netzwerk von einem anderen Rechner.
- `ist_lokaler_zugriff()` prüft `request.remote_addr` gegen `127.0.0.1`/`::1`
- `@app.before_request`-Hook `_zugriff_beschraenken()` blockiert für
  Netzwerk-Zugriffe alle Routen außer denen in `OEFFENTLICHE_ENDPUNKTE`
  (aktuell nur `einrichten` und `static`) mit einer 403-Seite
- Die Seite `/einrichten` zeigt sich bei Netzwerkzugriff unter anderem Namen
  ("Software anfordern" statt "Rechner einrichten") und mit Hinweis auf die
  Protokollierung
- Jeder Aufruf/Download über `/einrichten` wird in der Tabelle `zugriffslog`
  festgehalten (Zeitpunkt, IP-Adresse, per Reverse-DNS ermittelter
  Rechnername falls auflösbar, selbst angegebener Name, Aktion) – einsehbar
  unter `/zugriffslog` (selbst wieder nur lokal erreichbar)
**Wichtige Einschränkung:** Ein echter Windows-Benutzername lässt sich über
reines HTTP **nicht** zuverlässig ermitteln – dafür wäre eine
NTLM/Kerberos-Integration nötig (z. B. über einen IIS-Reverse-Proxy vor
Flask, der die Windows-Anmeldung übernimmt und den Benutzernamen per Header
an die Flask-App durchreicht). Das ist in diesem Prototyp **nicht**
umgesetzt. Aktuell basiert die Identifizierung auf der IP-Adresse, einem per
Reverse-DNS aufgelösten Rechnernamen (funktioniert nur, wenn im
Firmennetzwerk DNS-Einträge für Client-Rechner existieren) und dem selbst im
Formular angegebenen Namen (nicht verifiziert). Für eine belastbarere
Identifizierung müsste diese IIS/NTLM-Integration nachgerüstet werden.
**Anpassung an andere Infrastruktur:** Sollte der Server z. B. hinter einem
Reverse-Proxy laufen, liefert `request.remote_addr` ggf. die Proxy-IP statt
der echten Client-IP – in dem Fall müssten `X-Forwarded-For`-Header
ausgewertet werden (aktuell nicht implementiert, da kein Proxy im Einsatz).
## 7. Bekannte Grenzen / nicht vollständig getestet
- **Keine Authentifizierung.** Es gibt kein Login-System. Jeder, der den
  Server im Netzwerk erreichen kann, kann Software verwalten, Installer
  herunterladen und Installations-Pakete erzeugen. Das war für den internen,
  vertrauenswürdigen Einsatz im Firmennetz eine bewusste Vereinfachung –
  **bei einer Anpassung an eine andere/größere Infrastruktur unbedingt
  prüfen, ob das so bleiben darf**, insbesondere wenn der Server auch von
  außerhalb des Firmennetzes erreichbar sein könnte.
- **Keine echte Authentifizierung, nur Herkunfts-Beschränkung.** Seit r17
  ist die Verwaltung (Katalog, Protokolle, Zugriffsprotokoll) nur noch vom
  Server selbst aus erreichbar (siehe Abschnitt 6a) – das ist aber eine
  Netzwerk-/IP-basierte Einschränkung, **kein Login mit Benutzername/Passwort**.
  Wer direkt am Server sitzt (oder sich als diesen ausgibt, z. B. über
  IP-Spoofing im selben Netzwerksegment), hat vollen Zugriff. Für ein
  belastbares Sicherheitskonzept mit echten Benutzerkonten wäre ein
  richtiges Login-System nötig.
- **Kein HTTPS/TLS.** Die Kommunikation läuft unverschlüsselt über HTTP. Für
  ein internes, abgeschottetes Netzwerk meist unkritisch, sollte aber vor
  einem größeren Rollout bewertet werden.