feat: implement Phase 1 hardening

- Verify JWT signatures via JWKS in auth.py
- Fix broken frontend auth button references
- Add Pydantic Settings for env validation (RETENTION_DAYS, CORS_ORIGINS)
- Create MongoDB indexes + TTL on startup
- Add /health endpoint and CORS middleware
- Escape regex input in event queries
- Fix dedupe() return calculation in maintenance.py
- Replace basic logging with structured structlog JSON logs
- Update README and add ROADMAP.md
This commit is contained in:
2026-04-14 11:48:29 +02:00
parent f9f1399f57
commit 4f6e16d64d
12 changed files with 392 additions and 46 deletions

View File

@@ -1,3 +1,4 @@
import re
from fastapi import APIRouter, HTTPException, Depends
from database import events_collection
from auth import require_auth
@@ -22,20 +23,21 @@ def list_events(
if service:
filters.append({"service": service})
if actor:
actor_safe = re.escape(actor)
filters.append(
{
"$or": [
{"actor_display": {"$regex": actor, "$options": "i"}},
{"actor_upn": {"$regex": actor, "$options": "i"}},
{"actor.user.userPrincipalName": {"$regex": actor, "$options": "i"}},
{"actor_display": {"$regex": actor_safe, "$options": "i"}},
{"actor_upn": {"$regex": actor_safe, "$options": "i"}},
{"actor.user.userPrincipalName": {"$regex": actor_safe, "$options": "i"}},
{"actor.user.id": actor},
]
}
)
if operation:
filters.append({"operation": {"$regex": operation, "$options": "i"}})
filters.append({"operation": {"$regex": re.escape(operation), "$options": "i"}})
if result:
filters.append({"result": {"$regex": result, "$options": "i"}})
filters.append({"result": {"$regex": re.escape(result), "$options": "i"}})
if start or end:
time_filter = {}
if start:
@@ -44,14 +46,15 @@ def list_events(
time_filter["$lte"] = end
filters.append({"timestamp": time_filter})
if search:
search_safe = re.escape(search)
filters.append(
{
"$or": [
{"raw_text": {"$regex": search, "$options": "i"}},
{"display_summary": {"$regex": search, "$options": "i"}},
{"actor_display": {"$regex": search, "$options": "i"}},
{"target_displays": {"$elemMatch": {"$regex": search, "$options": "i"}}},
{"operation": {"$regex": search, "$options": "i"}},
{"raw_text": {"$regex": search_safe, "$options": "i"}},
{"display_summary": {"$regex": search_safe, "$options": "i"}},
{"actor_display": {"$regex": search_safe, "$options": "i"}},
{"target_displays": {"$elemMatch": {"$regex": search_safe, "$options": "i"}}},
{"operation": {"$regex": search_safe, "$options": "i"}},
]
}
)