Update audit logging and dashboard

This commit is contained in:
2025-05-13 21:54:40 +02:00
parent 60026a485d
commit 3055f5277b
20 changed files with 788 additions and 285 deletions

View File

@ -1,5 +1,6 @@
"""Tests of the backend api using pytest."""
import uuid
import logging
from pathlib import Path
from httpx import Response
@ -210,58 +211,17 @@ def test_audit_logging(test_client: TestClient) -> None:
audit_log_resp = test_client.get("/api/v1/audit/")
assert audit_log_resp.status_code == 200
audit_logs = audit_log_resp.json()
assert len(audit_logs) > 0
for entry in audit_logs:
assert isinstance(audit_logs, dict)
audit_count = audit_logs.get("total")
assert audit_count is not None
assert audit_count > 0
assert "results" in audit_logs
for entry in audit_logs["results"]:
# Let's try to reassemble the objects
audit_log = AuditView.model_validate(entry)
assert audit_log is not None
# def test_audit_log_filtering(
# session: Session, test_client: TestClient
# ) -> None:
# """Test audit log filtering."""
# # Create a lot of test data, but just manually.
# audit_log_amount = 150
# entries: list[AuditLog] = []
# for i in range(audit_log_amount):
# client_id = i % 5
# entries.append(
# AuditLog(
# operation="TEST",
# object_id=str(i),
# client_name=f"client-{client_id}",
# message="Test Message",
# )
# )
# session.add_all(entries)
# session.commit()
# # This should have generated a lot of audit messages
# audit_path = "/api/v1/audit/"
# audit_log_resp = test_client.get(audit_path)
# assert audit_log_resp.status_code == 200
# entries = audit_log_resp.json()
# assert len(entries) == 100 # We get 100 at a time
# audit_log_resp = test_client.get(
# audit_path, params={"offset": 100}
# )
# entries = audit_log_resp.json()
# assert len(entries) == 52 # There should be 50 + the two requests we made
# # Try to get a specific client
# # There should be 30 log entries for each client.
# audit_log_resp = test_client.get(
# audit_path, params={"filter_client": "client-1"}
# )
# entries = audit_log_resp.json()
# assert len(entries) == 30
def test_secret_invalidation(test_client: TestClient) -> None:
"""Test secret invalidation."""
initial_key = make_test_key()
@ -533,6 +493,69 @@ def test_write_audit_log(test_client: TestClient) -> None:
assert resp.status_code == 200
data = resp.json()
entry = data[0]
entry = data["results"][0]
for key, value in params.items():
assert entry[key] == value
def test_filter_audit_log(test_client: TestClient) -> None:
"""Test filtering of audit logs."""
# prepare some audit logs
messages = [
{
"subsystem": "backend",
"operation": "login",
"client_id": str(uuid.uuid4()),
"client_name": "foo",
"origin": "192.0.2.1",
"message": "message1",
},
{
"subsystem": "backend",
"operation": "create",
"client_id": str(uuid.uuid4()),
"client_name": "foo",
"origin": "192.0.2.1",
"secret_id": str(uuid.uuid4()),
"message": "message2",
},
{
"subsystem": "test",
"operation": "deny",
"client_id": str(uuid.uuid4()),
"client_name": "bar",
"origin": "192.0.2.2",
"message": "message3",
},
]
for message in messages:
test_client.post("/api/v1/audit", json=message)
# find all client_name=foo entries
resp = test_client.get("/api/v1/audit/", params={"client_name": "foo"})
assert resp.status_code == 200
data = resp.json()
assert data["total"] == 2
assert len(data["results"]) == 2
# Get the one message from 'bar'
resp = test_client.get("/api/v1/audit/", params={"client_name": "bar"})
assert resp.status_code == 200
data = resp.json()
assert data["total"] == 1
assert len(data["results"]) == 1
assert data["results"][0]["operation"] == "deny"
# test combining fields to get the login event
resp = test_client.get("/api/v1/audit/", params={"client_name": "foo", "operation": "login"})
data = resp.json()
assert data["total"] == 1
assert data["results"][0]["operation"] == "login"
assert data["results"][0]["message"] == "message1"