Перенесены секреты из .env в SM
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
REDACTED = "[REDACTED]"
|
||||
_SENSITIVE_KEY = re.compile(
|
||||
r"(authorization|cookie|password|passwd|secret|token|api[_-]?key|"
|
||||
r"database[_-]?url|redis[_-]?url|dsn|callback[_-]?url)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
_URI_USERINFO = re.compile(r"(?P<scheme>[a-z][a-z0-9+.-]*://)[^/@\s]+@", re.IGNORECASE)
|
||||
_QUERY_SECRET = re.compile(
|
||||
r"(?P<prefix>[?&](?:token|access_token|api_key|key|secret|password)=)[^&#\s]+",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
_AUTH_VALUE = re.compile(r"\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]+", re.IGNORECASE)
|
||||
|
||||
|
||||
def sanitize_text(value: str) -> str:
|
||||
value = _URI_USERINFO.sub(r"\g<scheme>[REDACTED]@", value)
|
||||
value = _QUERY_SECRET.sub(r"\g<prefix>[REDACTED]", value)
|
||||
return _AUTH_VALUE.sub(r"\1 [REDACTED]", value)
|
||||
|
||||
|
||||
def sanitize_value(value: Any) -> Any:
|
||||
if isinstance(value, str):
|
||||
return sanitize_text(value)
|
||||
if isinstance(value, Mapping):
|
||||
return {
|
||||
str(key): REDACTED if _SENSITIVE_KEY.search(str(key)) else sanitize_value(item)
|
||||
for key, item in value.items()
|
||||
}
|
||||
if isinstance(value, list):
|
||||
return [sanitize_value(item) for item in value]
|
||||
if isinstance(value, tuple):
|
||||
return tuple(sanitize_value(item) for item in value)
|
||||
return value
|
||||
|
||||
|
||||
def redact_event(
|
||||
_logger: Any,
|
||||
_method_name: str,
|
||||
event_dict: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
return sanitize_value(event_dict)
|
||||
@@ -22,6 +22,7 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
|
||||
from app.db import Database, SmsTemplate
|
||||
from app.domain import DomainError
|
||||
from app.logging_security import redact_event
|
||||
from app.metrics import CALLBACK_LAG, CALLBACK_TOTAL
|
||||
from app.schemas import CallbackItem, ErrorEnvelope, MessageResponse, SendRequest, SendResponse
|
||||
from app.service import (
|
||||
@@ -42,6 +43,7 @@ def configure_logging(level: str) -> None:
|
||||
processors=[
|
||||
structlog.contextvars.merge_contextvars,
|
||||
add_trace_context,
|
||||
redact_event,
|
||||
structlog.processors.TimeStamper(fmt="iso", utc=True, key="timestamp"),
|
||||
structlog.stdlib.add_log_level,
|
||||
structlog.processors.JSONRenderer(),
|
||||
@@ -147,7 +149,11 @@ async def http_error(request: Request, exc: StarletteHTTPException) -> JSONRespo
|
||||
|
||||
@app.exception_handler(Exception)
|
||||
async def unhandled_error(request: Request, exc: Exception) -> JSONResponse:
|
||||
log.exception("request.failed", error_code="internal_error")
|
||||
log.error(
|
||||
"request.failed",
|
||||
error_code="internal_error",
|
||||
error_type=type(exc).__name__,
|
||||
)
|
||||
return error_response(request, "internal_error", "Internal server error", 500)
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from prometheus_client import start_http_server
|
||||
from sqlalchemy import and_, func, or_, select, update
|
||||
|
||||
from app.db import Database, SendStatus, SmsOutboundMessage
|
||||
from app.logging_security import redact_event
|
||||
from app.metrics import (
|
||||
JOURNAL_ROWS,
|
||||
PENDING_AGE,
|
||||
@@ -37,6 +38,7 @@ def configure_logging(level: str) -> None:
|
||||
processors=[
|
||||
structlog.contextvars.merge_contextvars,
|
||||
add_trace_context,
|
||||
redact_event,
|
||||
structlog.processors.TimeStamper(fmt="iso", utc=True, key="timestamp"),
|
||||
structlog.stdlib.add_log_level,
|
||||
structlog.processors.JSONRenderer(),
|
||||
@@ -217,9 +219,12 @@ async def worker_loop(stop: asyncio.Event) -> None:
|
||||
await save_result(db, message.id, result, message.attempt_count)
|
||||
except TimeoutError:
|
||||
continue
|
||||
except Exception:
|
||||
except Exception as exc:
|
||||
SETTINGS_VALID.set(0)
|
||||
log.exception("worker.iteration_failed")
|
||||
log.error(
|
||||
"worker.iteration_failed",
|
||||
error_type=type(exc).__name__,
|
||||
)
|
||||
try:
|
||||
await asyncio.wait_for(stop.wait(), timeout=5)
|
||||
except TimeoutError:
|
||||
|
||||
Reference in New Issue
Block a user