gendesign/backend/app/observability/sentry_scrub.py
lekss361 8a04af5da3 fix(backend): GlitchTip release fallback + apiKey scrub (#204 review fixes)
- release= now: GIT_SHA or SENTRY_RELEASE or "unknown" (covers existing
  deploy.yml which writes SENTRY_RELEASE=$IMAGE_TAG, not GIT_SHA)
- new module app/observability/sentry_scrub.py: before_send_transaction
  hook that redacts apiKey/token/access_token/secret query params from
  HttpxIntegration spans before they reach GlitchTip
- config.py: model_validator promotes legacy SENTRY_DSN -> glitchtip_dsn
  with DeprecationWarning for backward compat on existing VPS env
- .env.example: added deprecated SENTRY_DSN entry with comment
- tests: 8 new cases covering release fallback + scrub module (11 total)
2026-05-16 18:04:01 +03:00

49 lines
1.6 KiB
Python

"""Хук before_send_transaction для GlitchTip/Sentry SDK.
Redact-ит api keys / tokens из URL-spans перед отправкой — чтобы
секреты (apiKey=..., api_key=..., token=...) не утекали в GlitchTip
через HttpxIntegration performance-spans.
"""
from __future__ import annotations
import re
from typing import Any
from sentry_sdk.types import Event
_SENSITIVE_PARAM_RE = re.compile(
r"((?:api[_-]?[Kk]ey|token|access[_-]?token|secret)=)([^&\s]+)",
re.IGNORECASE,
)
def _redact(value: Any) -> Any:
"""Заменить значения чувствительных query-параметров на [REDACTED]."""
if isinstance(value, str):
return _SENSITIVE_PARAM_RE.sub(r"\1[REDACTED]", value)
return value
def scrub_sensitive_query(event: Event, _hint: dict[str, Any]) -> Event | None:
"""Redact api keys / tokens из URL spans перед отправкой в GlitchTip.
Обрабатывает:
- span.data["url"], span.data["http.url"], span.data["http.target"]
- span["description"]
- event["request"]["url"]
"""
for span in event.get("spans") or []:
data = span.get("data")
if isinstance(data, dict):
for key in ("url", "http.url", "http.target"):
if key in data:
data[key] = _redact(data[key])
if "description" in span:
span["description"] = _redact(span["description"])
request = event.get("request")
if isinstance(request, dict) and "url" in request:
request["url"] = _redact(request["url"])
return event