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,22 +1,59 @@
import os
from dotenv import load_dotenv
from pydantic_settings import BaseSettings, SettingsConfigDict
load_dotenv()
TENANT_ID = os.getenv("TENANT_ID")
CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
MONGO_URI = os.getenv("MONGO_URI")
DB_NAME = "micro_soc"
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=[".env", "../.env"],
env_file_encoding="utf-8",
extra="ignore",
)
# Optional periodic fetch settings
ENABLE_PERIODIC_FETCH = os.getenv("ENABLE_PERIODIC_FETCH", "false").lower() == "true"
FETCH_INTERVAL_MINUTES = int(os.getenv("FETCH_INTERVAL_MINUTES", "60"))
# Microsoft Graph / App credentials
TENANT_ID: str = ""
CLIENT_ID: str = ""
CLIENT_SECRET: str = ""
# Auth (OIDC/Bearer) settings
AUTH_ENABLED = os.getenv("AUTH_ENABLED", "false").lower() == "true"
AUTH_TENANT_ID = os.getenv("AUTH_TENANT_ID") or TENANT_ID or ""
AUTH_CLIENT_ID = os.getenv("AUTH_CLIENT_ID") or CLIENT_ID or ""
AUTH_SCOPE = os.getenv("AUTH_SCOPE", "")
AUTH_ALLOWED_ROLES = set([r.strip() for r in os.getenv("AUTH_ALLOWED_ROLES", "").split(",") if r.strip()])
AUTH_ALLOWED_GROUPS = set([g.strip() for g in os.getenv("AUTH_ALLOWED_GROUPS", "").split(",") if g.strip()])
# MongoDB
MONGO_URI: str = ""
DB_NAME: str = "micro_soc"
# Periodic fetch
ENABLE_PERIODIC_FETCH: bool = False
FETCH_INTERVAL_MINUTES: int = 60
# Auth (OIDC/Bearer) settings
AUTH_ENABLED: bool = False
AUTH_TENANT_ID: str = ""
AUTH_CLIENT_ID: str = ""
AUTH_SCOPE: str = ""
AUTH_ALLOWED_ROLES: str = ""
AUTH_ALLOWED_GROUPS: str = ""
# Data retention (0 = disabled)
RETENTION_DAYS: int = 0
# CORS
CORS_ORIGINS: str = "*"
_settings = Settings()
# Backward-compatible module-level exports
TENANT_ID = _settings.TENANT_ID
CLIENT_ID = _settings.CLIENT_ID
CLIENT_SECRET = _settings.CLIENT_SECRET
MONGO_URI = _settings.MONGO_URI
DB_NAME = _settings.DB_NAME
ENABLE_PERIODIC_FETCH = _settings.ENABLE_PERIODIC_FETCH
FETCH_INTERVAL_MINUTES = _settings.FETCH_INTERVAL_MINUTES
AUTH_ENABLED = _settings.AUTH_ENABLED
AUTH_TENANT_ID = _settings.AUTH_TENANT_ID or _settings.TENANT_ID or ""
AUTH_CLIENT_ID = _settings.AUTH_CLIENT_ID or _settings.CLIENT_ID or ""
AUTH_SCOPE = _settings.AUTH_SCOPE
AUTH_ALLOWED_ROLES = {r.strip() for r in _settings.AUTH_ALLOWED_ROLES.split(",") if r.strip()}
AUTH_ALLOWED_GROUPS = {g.strip() for g in _settings.AUTH_ALLOWED_GROUPS.split(",") if g.strip()}
RETENTION_DAYS = _settings.RETENTION_DAYS
CORS_ORIGINS = [o.strip() for o in _settings.CORS_ORIGINS.split(",") if o.strip()]