Files
ripe-cidr-collector/docs/plan-empty-backup-guard.md
T
ayurishchevandClaude Sonnet 5 ab89c87321 Do not trust empty backups when sources are configured
Restoring a backup with no data while sources are configured now sets the
db_recreated.json marker (503 until data is collected), and the backup job
skips copying an empty database in that state. Adds finding 11 to the review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 10:30:03 +03:00

5.2 KiB
Raw Blame History

План: защита от восстановления из пустой копии (находка 11)

Источник: трассировка _recover() по графу знаний и проверка запуском (см. docs/review-2026-09-21.md, находка 11).

Проблема

_recover ставит на место повреждённой базы самую свежую исправную копию, но не смотрит на её содержимое. Если копия пуста (ночное задание backup сработало до первого сбора или во время его сбоев), а источники в config.json настроены, то после порчи базы API отвечает 200 [] без метки: та же угроза, что в находке 1 (потребитель может принять пустой список за истину), только через восстановление. Подтверждено запуском: копия пустой базы -> порча -> /addresses даёт 200 [], метки нет.

Дизайн

  • Признак «пусто несмотря на источники»: db.empty_despite_sources(conn): в базе нет ни одного значения, а в config.json настроен хотя бы один ASN или FQDN. Сначала проверяется число значений (конфиг не читается, если данные есть); нечитаемый конфиг при пустой базе считается «пусто» (блокировка по умолчанию). Критерий намеренно общий, а не по типам: копия, где есть ASN, но нет адресов FQDN (например, все адреса отфильтрованы как неглобальные), не должна вечно держать выдачу в ожидании.
  • Восстановление: после успешного _restore_backup при empty_despite_sources пишется та же метка db_recreated.json (с полем reason). Дальше работает уже существующая защита: /addresses и /addresses/diff дают 503 с Retry-After, /health показывает degraded и db_recreated, сборщик снимает метку, когда данные собраны. Восстановление копии с данными метку не ставит.
  • Задание backup: пустую базу при настроенных источниках не копирует: backup_database возвращает None (не ошибка: статус задания остаётся успешным, в лог пишется сообщение), ротация не выполняется, существующие копии не затрагиваются. Так пустые копии не вытесняют хорошие за backup_keep дней и не появляются вовсе. Пустая база без источников копируется как раньше.

Изменения

  1. db.py: empty_despite_sources; recreated_pending использует общий разбор конфигурации; метка ставится в _recover (общая функция записи метки для обеих веток); backup_database возвращает None для пустой базы при источниках.
  2. collector_daemon.py: run_backup обрабатывает None (сообщение в лог).
  3. README.md: разделы о резервной копии и автовосстановлении.
  4. docs/review-2026-09-21.md: находка 11; итоги в docs/summary-empty-backup-guard.md.
  5. Тесты (1 новый, всего 28): пустая база при настроенных источниках копию не создаёт, копия с данными восстанавливается без метки, пустая копия (снятая, когда источников не было) при появлении источников даёт метку и 503-состояние.

Не входит

Тип-специфичное ожидание при восстановлении (см. выше); копии вне сервера; удаление уже существующих пустых копий (при необходимости - вручную из backups/).

Проверка

Тесты в контейнере; повтор запуска, воспроизводившего проблему: восстановление из пустой копии при настроенном источнике теперь даёт 503, метка есть, после появления данных выдача возобновляется; копия с данными - без метки.

Откат

Убрать проверку в _recover и backup_database (возврат к предыдущему коммиту); схема данных не затрагивается, метку можно удалить вручную.