feat(admin): Audit-Logging schreibender Admin-Aktionen — Plan-Schritt 5
- app/audit.py: eigener Logger "va.audit" (eigener stdout-Handler -> Journal/Log-Tab). log_admin_action() protokolliert Aktion + Auslöser (SSO-Name oder admin-key). - Verdrahtet in: config_set/config_reset (PUT/DELETE /admin/config), llm_backend_switch (+ _rejected), gateway_restart. - Tests: caplog prüft Audit-Zeilen für config_set und abgelehnten Backend-Switch. - Doku §7.5: Audit-Format im Log-Tab. Schließt den Plan (Admin-gesteuerte LLM-/Gateway-Verwaltung, Schritte 1–5) ab. 167 grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b2576fd465
commit
33d7189418
4 changed files with 119 additions and 7 deletions
44
tests/test_audit.py
Normal file
44
tests/test_audit.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"""Tests für das Audit-Logging der Admin-Aktionen."""
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.main import app
|
||||
from app.config import settings
|
||||
from app.runtime_config import invalidate_cache
|
||||
|
||||
client = TestClient(app)
|
||||
ADMIN = "test-admin-key"
|
||||
ADM_HDR = {"X-Admin-Key": ADMIN}
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _setup(monkeypatch):
|
||||
monkeypatch.setattr(settings, "admin_api_key", ADMIN)
|
||||
monkeypatch.setattr(settings, "auth_enabled", False)
|
||||
invalidate_cache()
|
||||
yield
|
||||
invalidate_cache()
|
||||
|
||||
|
||||
def test_config_set_is_audited(caplog):
|
||||
with caplog.at_level(logging.INFO, logger="va.audit"):
|
||||
r = client.put("/api/admin/config/local_llm_top_p",
|
||||
json={"value": "0.7"}, headers=ADM_HDR)
|
||||
assert r.status_code == 200
|
||||
line = "\n".join(caplog.messages)
|
||||
assert "action=config_set" in line
|
||||
assert "local_llm_top_p" in line
|
||||
assert "user=admin-key" in line
|
||||
# aufräumen
|
||||
client.delete("/api/admin/config/local_llm_top_p", headers=ADM_HDR)
|
||||
|
||||
|
||||
def test_backend_switch_rejection_is_audited(caplog):
|
||||
with caplog.at_level(logging.INFO, logger="va.audit"):
|
||||
r = client.post("/api/admin/llm/backend",
|
||||
json={"backend": "boese"}, headers=ADM_HDR)
|
||||
assert r.status_code == 422
|
||||
assert "action=llm_backend_switch_rejected" in "\n".join(caplog.messages)
|
||||
Loading…
Add table
Add a link
Reference in a new issue