gendesign/backend/tests/ops
bot-backend de940c7534
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
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
feat(ops): off-box копия рантайм-конфига — зашифрованной, иначе никак
Четвёртый пункт приёмки #2203. В дампах есть колонки под pgp_sym_encrypt, ключ
к ним лежит на самой машине и никуда не уезжает: потеря машины означает «дампы
есть, расшифровать нечем». Ради этой связки шифрование в базе и заводилось.

КУДА И ПОЧЕМУ ИМЕННО ТУДА. В тот же S3, отдельным префиксом env/, и только
зашифрованным. Разобранные варианты:

  - рядом с дампами открытым — нельзя: ключ рядом с шифротекстом обнуляет
    шифрование, одна утечка доступа к бакету отдаёт и то и другое;
  - на соседний хост по SSH — потребовало бы завести доверие между машинами,
    которого нет (проверено: Permission denied (publickey)), то есть РАСШИРИТЬ
    периметр ровно тогда, когда #3075 его сужает;
  - отдельный бакет с отдельными ключами — правильнее всего, но требует новых
    учётных данных.

Выбран единственный исполнимый без расширения доступа: шифротекст в S3,
парольная фраза — вне S3.

FAIL-CLOSED. Без фразы скрипт не выгружает файл открытым, а падает с явным
сообщением и алертом. Молчаливая выгрузка ключа в бакет с дампами хуже
отсутствия копии: создаёт ложное чувство защищённости.

Фраза уходит через дескриптор, а не аргументом — иначе видна в ps любому
пользователю машины. После шифрования файл проверяется обратной расшифровкой:
без этого можно годами возить нечитаемый мусор и узнать в тот момент, когда он
понадобился.

Прогон на хосте 27.08 (подставной исходник, боевой не трогался):
  без фразы → код 1, файлов создано 0
  с фразой  → «Зашифровано и проверено расшифровкой», 110 байт
  своей фразой читается, чужой — нет

ОДИН ШАГ ЗА ВЛАДЕЛЬЦЕМ, и он неустраним: фраза обязана жить там, где переживёт
смерть машины, иначе копия бесполезна — расшифровать будет нечем. Сгенерировать
её здесь и оставить на хосте нельзя по построению. Инструкция — в шапке скрипта.

Пять тестов сторожат ровно те свойства, ради которых всё сделано.
Прогон: 85 ops-тестов зелёные, ruff чист.

Refs #2203
2026-08-27 16:32:27 +03:00
..
__init__.py fix(ci): прод-деплои в одну группу concurrency — прун одного убивал pull другого (#2950) (#2952) 2026-08-20 07:47:48 +00:00
test_3xxx_alertmanager_inode.py fix(ops/metrics): правки конфига Alertmanager молча не доезжали до контейнера 2026-08-27 15:10:23 +03:00
test_2203_backup_trailer_grep_dashdash.py fix(ops): проверка трейлера дампа падала на grep — ведущие -- принимались за опции (#2203) 2026-08-20 23:38:45 +03:00
test_2203_env_offbox.py feat(ops): off-box копия рантайм-конфига — зашифрованной, иначе никак 2026-08-27 16:32:27 +03:00
test_2203_notify_topic.py fix(tests): ruff E741 — однобуквенное имя переменной в разборе скрипта 2026-08-27 13:16:26 +03:00
test_2950_deploy_concurrency_group.py chore(format): нормализация под ruff 0.15.20 — 161 файл, только формат (#2864) (#3022) 2026-08-21 12:01:52 +00:00
test_3029_deploy_drift.py feat(ops): сторож расхождения «прод ↔ main» — молчаливый недоехавший деплой становится видимым (#3029) 2026-08-27 12:35:43 +03:00
test_3059_alert_retry.py fix(ops): алерт не теряется от одного сетевого отказа (#3059) 2026-08-26 10:02:46 +03:00
test_3078_alert_ack.py fix(tests): убрать директивы noqa на неактивное правило 2026-08-27 14:32:34 +03:00
test_3078_alert_topic.py feat(observability): алерты адресуются в топик форумной группы (#3078) 2026-08-26 14:10:56 +03:00
test_3078_exporter_profiles.py fix(observability): агент не падает из-за переменной чужой роли (#3078) 2026-08-26 12:45:31 +03:00
test_3078_metrics_role_discovery.py fix(observability): привилегированную роль спрашиваем у контейнера, а не угадываем (#3078) 2026-08-26 12:08:37 +03:00
test_3078_oncall_route.py feat(observability): кнопка «Принял в работу» под клиентским инцидентом (#3078) 2026-08-27 13:56:00 +03:00
test_3114_log_credential_scrub.py fix(observability): пароли не уезжают в Loki — скруббер учётных данных (#3114) 2026-08-26 15:50:57 +03:00
test_3114_pg_exporter_version.py fix(ops/metrics): postgres-exporter печатал пароль БД в лог при каждой ошибке 2026-08-27 15:55:24 +03:00