fix(tradein/auth): агрегированный отказ пишется на ERROR — иначе канала нет (#2715)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m8s
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m8s
Бэкенд поднят с LoggingIntegration(level=INFO, event_level=ERROR) (app/main.py): событием GlitchTip запись становится ровно с ERROR, а WARNING остаётся строкой в docker-логе, которая умирает с ротацией и редеплоем — то есть ровно тем следом, на бесполезность которого жалуется пункт 1 issue. Прецедент цены известен (#2674): монитор писал WARNING про протухшие куки, событий было ноль. Спама не будет: запись не чаще раза в окно (1с), все группируются в один issue. Получателей у проекта по-прежнему нет (#2673) — событие будет видно в интерфейсе и никому не уйдёт; это сказано в docstring, а не подразумевается. Уровень закреплён тестом: понижение до WARNING выключило бы канал молча. Refs #2715
This commit is contained in:
parent
1610c01c6d
commit
8958a657cb
2 changed files with 16 additions and 4 deletions
|
|
@ -219,10 +219,18 @@ def _saturated_429(ip: str) -> HTTPException:
|
|||
дублируется. Первый отказ отчитывается сразу, а не в конце окна: одиночная
|
||||
аномалия обязана быть видна, даже если продолжения не будет.
|
||||
|
||||
Уровень ERROR, а не WARNING, — не косметика: бэкенд поднят с
|
||||
`LoggingIntegration(level=INFO, event_level=ERROR)` (app/main.py), то есть
|
||||
ровно с ERROR запись становится событием GlitchTip, а WARNING остаётся
|
||||
строкой в docker-логе, которая умирает с ротацией и редеплоем. Цена
|
||||
прецедента известна (#2674): монитор писал WARNING про протухшие куки — и
|
||||
событий было ноль. Спама не будет: запись не чаще раза в окно, и все они
|
||||
группируются в один issue (шаблон сообщения один).
|
||||
|
||||
Чего это НЕ делает: у GlitchTip-проекта нет ни правил, ни получателей
|
||||
(#2673), так что уведомление никому не уйдёт — след появляется в аудите и
|
||||
в логе, а не в чьём-то телефоне. Проверить доставку поведенчески сейчас
|
||||
нельзя, и утверждать её здесь было бы враньём.
|
||||
(#2673), так что уведомление никому не уйдёт — событие будет видно в
|
||||
интерфейсе, но не в чьём-то телефоне. Проверить доставку поведенчески
|
||||
сейчас не на чем, и утверждать её здесь было бы враньём.
|
||||
|
||||
`username=""` — не заглушка: имя не пишем ПОТОМУ, что отказ случился до
|
||||
того, как мы на него посмотрели. Записывай мы присланное, атакующий
|
||||
|
|
@ -237,7 +245,7 @@ def _saturated_429(ip: str) -> HTTPException:
|
|||
if now - _saturation_reported_at >= _SATURATION_REPORT_WINDOW_S:
|
||||
rejected, _saturation_rejected = _saturation_rejected, 0
|
||||
_saturation_reported_at = now
|
||||
logger.warning(
|
||||
logger.error(
|
||||
"login rejected: password verify saturated — %d отказов с прошлой записи "
|
||||
"(не чаще раза в %.0fс), последний ip=%s",
|
||||
rejected,
|
||||
|
|
|
|||
|
|
@ -1057,6 +1057,10 @@ def test_saturation_is_reported_once_per_window_and_lands_in_audit(
|
|||
|
||||
lines = [r for r in caplog.records if "saturated" in r.getMessage()]
|
||||
assert len(lines) == 1, f"20 отказов дали {len(lines)} строк в логе — агрегации нет"
|
||||
# ERROR, а не WARNING: бэкенд поднят с LoggingIntegration(event_level=ERROR)
|
||||
# (app/main.py), и только с ERROR запись становится событием GlitchTip.
|
||||
# Понижение уровня выключило бы канал молча — прецедент #2674.
|
||||
assert lines[0].levelno == logging.ERROR
|
||||
|
||||
saturated = [e for e in events if e["event_type"] == "login_verify_saturated"]
|
||||
assert len(saturated) == 1, saturated
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue