fix(api): restore Alertmanager project context
This commit is contained in:
@@ -120,6 +120,26 @@ from src.workers import close_signal_worker, init_signal_worker
|
||||
setup_logging()
|
||||
logger = get_logger("awoooi.api")
|
||||
|
||||
ALERTMANAGER_WEBHOOK_PATH = "/api/v1/webhooks/alertmanager"
|
||||
ALERTMANAGER_DEFAULT_PROJECT_ID = "awoooi"
|
||||
|
||||
|
||||
def _resolve_request_project_context(request: Request) -> tuple[str | None, str]:
|
||||
"""Resolve tenant context for RLS while keeping non-webhook routes fail-closed."""
|
||||
for candidate in (
|
||||
request.headers.get("X-Project-ID"),
|
||||
request.headers.get("X-Tenant-ID"),
|
||||
request.query_params.get("project_id"),
|
||||
):
|
||||
project_id = candidate.strip() if candidate else None
|
||||
if project_id:
|
||||
return project_id, "request.header_or_query"
|
||||
|
||||
if request.url.path == ALERTMANAGER_WEBHOOK_PATH:
|
||||
return ALERTMANAGER_DEFAULT_PROJECT_ID, "request.alertmanager.default_project"
|
||||
|
||||
return None, "request.project_id.missing"
|
||||
|
||||
# =============================================================================
|
||||
# Sentry SDK Initialization (Error Tracking - 補強 SignOz)
|
||||
# Self-Hosted @ 192.168.0.110
|
||||
@@ -905,15 +925,7 @@ async def request_logging_middleware(request: Request, call_next):
|
||||
from src.core.context import clear_project_context, get_current_project_context, set_project_context
|
||||
|
||||
request_id = request.headers.get("X-Request-ID") or str(uuid4())
|
||||
project_id = (
|
||||
request.headers.get("X-Project-ID")
|
||||
or request.headers.get("X-Tenant-ID")
|
||||
or request.query_params.get("project_id")
|
||||
)
|
||||
project_id = project_id.strip() if project_id else None
|
||||
source = "request.project_id.missing"
|
||||
if project_id:
|
||||
source = "request.header_or_query"
|
||||
project_id, source = _resolve_request_project_context(request)
|
||||
|
||||
context_tokens = set_project_context(
|
||||
project_id=project_id,
|
||||
|
||||
55
apps/api/tests/test_alertmanager_project_context.py
Normal file
55
apps/api/tests/test_alertmanager_project_context.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from starlette.requests import Request
|
||||
|
||||
from src.main import _resolve_request_project_context
|
||||
|
||||
|
||||
def _request(
|
||||
path: str,
|
||||
*,
|
||||
query_string: bytes = b"",
|
||||
headers: list[tuple[bytes, bytes]] | None = None,
|
||||
) -> Request:
|
||||
return Request(
|
||||
{
|
||||
"type": "http",
|
||||
"method": "POST",
|
||||
"path": path,
|
||||
"scheme": "http",
|
||||
"server": ("testserver", 80),
|
||||
"client": ("127.0.0.1", 50000),
|
||||
"query_string": query_string,
|
||||
"headers": headers or [],
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_alertmanager_webhook_without_header_uses_awoooi_project_context():
|
||||
project_id, source = _resolve_request_project_context(
|
||||
_request("/api/v1/webhooks/alertmanager")
|
||||
)
|
||||
|
||||
assert project_id == "awoooi"
|
||||
assert source == "request.alertmanager.default_project"
|
||||
|
||||
|
||||
def test_alertmanager_webhook_keeps_explicit_project_context_priority():
|
||||
project_id, source = _resolve_request_project_context(
|
||||
_request(
|
||||
"/api/v1/webhooks/alertmanager",
|
||||
headers=[(b"x-project-id", b"tenant-a")],
|
||||
)
|
||||
)
|
||||
|
||||
assert project_id == "tenant-a"
|
||||
assert source == "request.header_or_query"
|
||||
|
||||
|
||||
def test_non_alertmanager_route_without_header_still_fails_closed():
|
||||
project_id, source = _resolve_request_project_context(
|
||||
_request("/api/v1/security/db-context-guard")
|
||||
)
|
||||
|
||||
assert project_id is None
|
||||
assert source == "request.project_id.missing"
|
||||
Reference in New Issue
Block a user