umbau 1.0
This commit is contained in:
63
app/recordings/recorder.py.bak_1788208152
Normal file
63
app/recordings/recorder.py.bak_1788208152
Normal file
@ -0,0 +1,63 @@
|
||||
"""
|
||||
Session-Aufzeichnung mit Hash-Verkettung (siehe Konzept 6.5).
|
||||
|
||||
Jede Session schreibt eine eigene JSONL-Datei unter settings.recordings_dir.
|
||||
Jede Zeile verkettet sich mit der vorherigen (gleiches Prinzip wie das
|
||||
Audit-Log, app/security/audit.py), damit nachtraegliche Manipulation der
|
||||
Aufzeichnung erkennbar ist.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from app.config import settings
|
||||
|
||||
GENESIS_HASH = "0" * 64
|
||||
|
||||
|
||||
class SessionRecorder:
|
||||
def __init__(self, session_id: int) -> None:
|
||||
self.session_id = session_id
|
||||
self.path = settings.recordings_dir / f"session_{session_id}.jsonl"
|
||||
self._prev_hash = GENESIS_HASH
|
||||
self._start_ts = time.time()
|
||||
self._fh = open(self.path, "a", encoding="utf-8")
|
||||
try:
|
||||
self.path.chmod(0o600)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def record(self, direction: str, data: str) -> None:
|
||||
"""direction: 'input' (Tastatureingabe) oder 'output' (Terminal-/RDP-Ausgabe)."""
|
||||
offset = round(time.time() - self._start_ts, 4)
|
||||
entry = {"t": offset, "dir": direction, "data": data}
|
||||
entry_json = json.dumps(entry, ensure_ascii=False, sort_keys=True)
|
||||
entry_hash = hashlib.sha256((self._prev_hash + "|" + entry_json).encode()).hexdigest()
|
||||
line = json.dumps({"entry": entry, "prev_hash": self._prev_hash, "hash": entry_hash})
|
||||
self._fh.write(line + "\n")
|
||||
self._fh.flush()
|
||||
self._prev_hash = entry_hash
|
||||
|
||||
def close(self) -> None:
|
||||
if not self._fh.closed:
|
||||
self._fh.close()
|
||||
|
||||
|
||||
def verify_recording(path: Path) -> bool:
|
||||
prev_hash = GENESIS_HASH
|
||||
with open(path, encoding="utf-8") as fh:
|
||||
for line in fh:
|
||||
if not line.strip():
|
||||
continue
|
||||
row = json.loads(line)
|
||||
if row["prev_hash"] != prev_hash:
|
||||
return False
|
||||
entry_json = json.dumps(row["entry"], ensure_ascii=False, sort_keys=True)
|
||||
expected = hashlib.sha256((prev_hash + "|" + entry_json).encode()).hexdigest()
|
||||
if expected != row["hash"]:
|
||||
return False
|
||||
prev_hash = row["hash"]
|
||||
return True
|
||||
Reference in New Issue
Block a user