102 lines
3.6 KiB
Python
102 lines
3.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Test-Skript fuer aza_audit_log.py"""
|
|
import os, sys, json
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from pathlib import Path
|
|
from aza_audit_log import (
|
|
log_event, export_audit_log, get_log_stats, _LOG_FILE,
|
|
)
|
|
|
|
if _LOG_FILE.exists():
|
|
_LOG_FILE.unlink()
|
|
|
|
passed = 0
|
|
failed = 0
|
|
|
|
def check(name, condition):
|
|
global passed, failed
|
|
if condition:
|
|
print(f" PASS: {name}")
|
|
passed += 1
|
|
else:
|
|
print(f" FAIL: {name}")
|
|
failed += 1
|
|
|
|
print("=== TEST 1: Events schreiben ===")
|
|
log_event("APP_START", "test_user", detail="test")
|
|
log_event("LOGIN_OK", "test_user")
|
|
log_event("LOGIN_FAIL", "test_user", success=False, detail="wrong password")
|
|
log_event("CONSENT_GRANT", "test_user")
|
|
log_event("AI_TRANSCRIBE", "test_user")
|
|
log_event("AI_CHAT", "test_user", detail="model=gpt-5.2")
|
|
log_event("AI_BLOCKED", "test_user", success=False, detail="kein Consent")
|
|
log_event("CONSENT_REVOKE", "test_user")
|
|
log_event("2FA_OK", "test_user")
|
|
log_event("2FA_FAIL", "test_user", success=False)
|
|
log_event("PASSWORD_CHANGE", "test_user")
|
|
log_event("APP_STOP", "test_user")
|
|
check("Logdatei existiert", _LOG_FILE.exists())
|
|
|
|
print("\n=== TEST 2: Log-Inhalt pruefen ===")
|
|
with open(_LOG_FILE, "r", encoding="utf-8") as f:
|
|
lines = [l.strip() for l in f if l.strip()]
|
|
check(f"12 Zeilen (gefunden: {len(lines)})", len(lines) == 12)
|
|
|
|
line1 = lines[0]
|
|
parts = [p.strip() for p in line1.split("|")]
|
|
check("6 Felder pro Zeile", len(parts) == 6)
|
|
check("Timestamp endet mit +00:00", "+00:00" in parts[0])
|
|
check("Event = APP_START", parts[1] == "APP_START")
|
|
check("User = test_user", parts[2] == "test_user")
|
|
check("Status = OK", parts[3] == "OK")
|
|
check("Source = desktop", parts[4] == "desktop")
|
|
|
|
line3 = lines[2]
|
|
parts3 = [p.strip() for p in line3.split("|")]
|
|
check("LOGIN_FAIL Status = FAIL", parts3[3] == "FAIL")
|
|
|
|
print("\n=== TEST 3: Statistiken ===")
|
|
stats = get_log_stats()
|
|
check("Datei existiert", stats["exists"])
|
|
check(f"12 Zeilen (stats: {stats['total_lines']})", stats["total_lines"] == 12)
|
|
check("APP_START in events", stats["events"].get("APP_START", 0) == 1)
|
|
check("LOGIN_FAIL in events", stats["events"].get("LOGIN_FAIL", 0) == 1)
|
|
check("AI_CHAT in events", stats["events"].get("AI_CHAT", 0) == 1)
|
|
|
|
print("\n=== TEST 4: Export ===")
|
|
path = export_audit_log()
|
|
check("Export-Datei existiert", os.path.exists(path))
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
check(f"12 Eintraege (export: {data['total_entries']})", data["total_entries"] == 12)
|
|
check("Erster Eintrag APP_START", data["entries"][0]["event"] == "APP_START")
|
|
check("Letzter Eintrag APP_STOP", data["entries"][-1]["event"] == "APP_STOP")
|
|
os.remove(path)
|
|
|
|
print("\n=== TEST 5: Data Minimization ===")
|
|
all_text = open(_LOG_FILE, "r", encoding="utf-8").read()
|
|
check("Kein Passwort im Log", "password" not in all_text.lower() or "wrong password" in all_text.lower())
|
|
check("Kein API-Key im Log", "sk-" not in all_text)
|
|
check("Kein Prompt im Log", "TRANSKRIPT:" not in all_text)
|
|
check("Detail < 200 Zeichen", all(len(p.strip()) < 200 for line in lines for p in [line.split("|")[-1]]))
|
|
|
|
print("\n=== TEST 6: Pipe-Sanitierung ===")
|
|
log_event("TEST", "user", detail="detail|mit|pipes")
|
|
with open(_LOG_FILE, "r", encoding="utf-8") as f:
|
|
last = [l.strip() for l in f if l.strip()][-1]
|
|
pipe_count = last.count("|")
|
|
check(f"Pipes ersetzt (nur 5 Trennzeichen, gefunden: {pipe_count})", pipe_count == 5)
|
|
|
|
# Cleanup
|
|
if _LOG_FILE.exists():
|
|
_LOG_FILE.unlink()
|
|
|
|
print(f"\n{'='*50}")
|
|
print(f"ERGEBNIS: {passed} PASS, {failed} FAIL")
|
|
if failed == 0:
|
|
print("ALLE TESTS BESTANDEN")
|
|
else:
|
|
sys.exit(1)
|