Перейти к содержанию

Обновления

Обновление на 0.33

Текущая опубликованная версия — 0.33 у всех компонентов: backend, worker, frontend, сканер инфраструктурного кода и DomainScope. Версии при этом независимые, и совпадение номеров — не правило: полный набор образов есть не для каждой версии.

0.33 — крупный релиз: плагинная платформа доведена до состояния, в котором она несёт интеграции целиком, а ядро от них разгружено. Ниже — только то, что требует действий при обновлении. Что появилось нового — в разделе Что нового в 0.33.

⚠️ Миграций много, и две из них долгие

С 0.31 до 0.33 накопилось 69 миграций схемы. Таблицу находок целиком ни одна не переписывает, но на инсталляции с накопленным объёмом две стоят внимания:

  • 00141 создаёт три сводных представления сразу с наполнением — это три полных прохода по таблице находок;
  • 00159 строит GIN-индекс по номерам CVE в неблокирующем режиме (CONCURRENTLY). На очень большой таблице он может не уложиться в бюджет ожидания общей блокировки миграций и помешать старту остальных реплик.

Что сделать заранее:

  1. поднять MIGRATION_LOCK_WAIT_SECONDS (по умолчанию 180 секунд) — либо построить этот индекс руками в тихие часы до обновления;
  2. обновлять сначала backend, потом воркеры: воркеры ждут ту же блокировку и на долгой миграции уходят в цикл перезапусков;
  3. проверять применение по схеме, а не по статусу выката:

    kubectl -n hub exec deploy/hub-backend -- \
      psql "$DATABASE_URL" -c \
      "SELECT version_id, is_applied, tstamp FROM goose_db_version ORDER BY version_id DESC LIMIT 5;"
    

Резервная копия базы перед обновлением обязательна: обратных миграций нет.

⚠️ Каналы Mattermost и MAX вынесены из ядра в плагины

Встроенного пути доставки для этих двух каналов больше нет: панели в настройках проекта исчезли, очереди mattermost_notifications и maxru_notifications удалены. Доставку ведут плагины mattermost-notifier и maxru-notifier.

Порядок обновления обязателен именно такой: обновиться → установить плагин → перенести настройки. Перенос требует установленного плагина-получателя, поэтому заранее, на 0.32, его выполнить нечем.

  1. Обновите компоненты до 0.33.
  2. Установите плагин канала (mattermost-notifier, maxru-notifier) — пошагово это описано в Официальных плагинах. Оба — нативные (Tier 2), поэтому источнику каталога нужно разрешение на исполнение нативных плагинов.
  3. Для Mattermost заполните в конфигурации установки плагина поле «Адрес сервера Mattermost» (mattermost_base_url). Без него установка и настройка проходят, а доставка отклоняется: Mattermost размещают у себя, адрес заранее неизвестен и в подписанном описании плагина его нет — именно это поле и разрешает исходящее соединение к вашему серверу.
  4. Перенесите настройки проектов админским запросом. Интерфейса у переноса нет:

    # dry-run (по умолчанию): показывает, что будет сделано, ничего не меняя
    curl -X POST -H "Authorization: Bearer $TOKEN" \
      "https://hub.example.com/api/v1/admin/maintenance/channel-config-backfill?channel=mattermost"
    
    # перенос; в ответе — сколько перенесено, сколько пропущено
    curl -X POST -H "Authorization: Bearer $TOKEN" \
      "https://hub.example.com/api/v1/admin/maintenance/channel-config-backfill?channel=mattermost&mode=final"
    

    Параметр channel — mattermost либо maxru. Проекты, у которых конфиг плагина уже есть, не трогаются и считаются отдельно.

Между «посмотреть» и «перенести» есть окно

В этом окне правки, сделанные старым путём (PUT /projects/:id), потеряются. Поэтому режим по умолчанию — dry-run, а момент переноса выбирает оператор. До переноса уведомления по этим каналам не отправляются: прежние настройки никуда не делись, но читает их только перенос.

Данные в базе сохранены: колонки projects.mattermost_config, projects.maxru_config и projects.mattermost_bot_config остаются на месте и будут удалены отдельным релизом — после того, как у вас была версия, на которой перенос возможен. Обновление настройки не теряет.

Настройка «Mattermost через бота» удалена без переноса: доставки по этому пути не существовало — форма сохранялась, уведомления не приходили.

⚠️ Удалённые переменные окружения

Переменная Что с ней
MATTERMOST_NOTIFICATION_WORKERS Удалена — очереди, которой она управляла, больше нет
MAXRU_NOTIFICATION_WORKERS Удалена — то же
TELEGRAM_NOTIFICATION_WORKERS Не читается — Telegram доставляет плагин, своей очереди у канала нет
MATTERMOST_ALLOW_LOCAL_DIAL Не читается никем; Hub при старте сообщает, что переменные подсистемы больше ничем не управляют

Оставленные в конфигурации значения не читаются и не мешают старту.

⚠️ Образ frontend работает от непривилегированного пользователя

Образ dexionius/sshub-frontend:0.33 запускается под uid/gid 101 и пишет pid-файл в /tmp. Чарт из этой поставки задаёт то же самое (frontend.frontend.podSecurityContext), поэтому обновление по чарту действий не требует. Проверьте окружение, если вы переопределяли securityContext (например, runAsUser: 0 из-за прежнего поведения образа) или монтировали тома с расчётом на root.

⚠️ Официальный каталог плагинов подключается сам

При обновлении заводится источник каталога hub-official — регистрировать его руками больше не нужно. Инсталляции, зарегистрировавшие тот же каталог раньше, дубля не получают; удалённая запись при следующем обновлении не возвращается.

Разрешение на нативные плагины при этом не выдаётся — это решение оператора. На свежей инсталляции каталог виден, а нативные плагины (в том числе все шесть каналов уведомлений) не ставятся, пока источнику не разрешено исполнение вне песочницы WASM. Провайдерам задач разрешение не нужно: им нативный режим запрещён, и они всегда исполняются в песочнице. Отказ не молчаливый: в каталоге такие записи помечены, а карточка объясняет причину и куда нажать.

Что нового в 0.33 — Hub

Плагинная платформа

  • Tier 2 — нативные плагины в изолированном процессе (gRPC), в дополнение к WASM; публикация нативных плагинов в общий каталог.
  • Каналы уведомлений как плагины: Telegram, Slack, Microsoft Teams, Mattermost, MAX, электронная почта. Диспетчер рассылает событие любому канальному плагину, а не захардкоженному списку — см. Уведомления.
  • История версий в каталоге, установка конкретной версии и явный откат; установка из файла и отзыв подписи по digest'у.
  • Обогащение находок данными БДУ ФСТЭК по номеру CVE; источник инвентаря FleetDM (хосты и уязвимости периодическим опросом); кэш данных о CVE на стороне Hub — плагин спрашивает, что уже известно, и не резолвит это заново.

Учёт задач

  • Провайдеры задач как плагины: Jira, GitHub Issues, Trello. Курируемый список целей заведения, привязка существующей задачи, опрос статусов, авто-закрытие, групповое заведение и бэкфилл истории, попроектная конфигурация — см. Учёт задач.

Находки

  • Свод инвентарных находок по пакету, хосту и CVE с drill-down и массовыми действиями по строке свода.
  • Ручное объединение находок и его отмена; ручные теги с аудитом; правила автоподавления; автоматическая связь находок по значению секрета; ручной ввод находки без SARIF — см. Жизненный цикл находки.

Доступ и наблюдаемость

  • BOOTSTRAP_ADMIN_EMAILS — первый администратор без временного отключения SSO; интерфейс управления ролями с матрицей прав; работа по ключу сервисного аккаунта (чтение и изменение находок, дашборд, нарушения SLA).
  • Метрики Prometheus на отдельном порту у всех трёх долгоживущих процессов и трейсинг OpenTelemetry — см. Эксплуатация.

Интерфейс и API

  • sshub — консольный клиент: находки, дашборд, отчёты, инвентарь, SLA, задачи, админка, гейт для CI — см. Консольный клиент.
  • Портируемая спека OpenAPI 3 и генерация клиентов.
  • Уведомление о вышедшем релизе, выключенное по умолчанию.

Что нового в 0.33 — DomainScope

  • Suspended-домены: запрет по специфичности и зонд возврата — зонд отчитывается в начале цикла и не ждёт перечисления поддоменов.
  • Цели nuclei и ZAP проверяются скоупом Hub, а не только владением адресом: прежде сканировалось и то, что из скоупа уже убрали.
  • Зоны перечисляются по расписанию, а не все на каждом цикле.

Из 0.32, если вы обновляетесь с 0.31: цели портскана берутся из текущего резолва активных доменов, а не из истории резолвов; обогащение из Metabase убрано в пользу плагина Hub metabase-cmdb.

Полный список изменений, включая замеренные улучшения производительности, — в CHANGELOG.md поставки.

Формат версий

Hub использует единую схему для всех компонентов:

X.Y.BUILD+COMMIT

Пример: 0.9.20260602093200+a1b2c3d

Часть Что
X.Y Major.Minor — общий для всех компонентов
BUILD UTC timestamp YYYYMMDDHHMMSS (когда собрали)
COMMIT Короткий git-hash (для аудита со стороны поставщика)

DomainScope версионируется независимо.

Где смотреть текущую версию

# UI Hub — footer показывает версии frontend + backend; warning при рассинхроне X.Y

# Backend HTTP
curl https://hub.example.com/version
curl https://hub.example.com/api/v1/version

Ответ /version:

{
  "component": "backend",
  "version": "0.9.20260602093200+a1b2c3d",
  "commit": "a1b2c3d",
  "built_at": "2026-05-24T00:00:00Z"
}

Поле component — имя компонента (backend, worker, …), built_at — ISO-таймстамп сборки.

Выбор версии

Образы публикуются с явными тегами вида X.Y, а также с тегом latest. Указывайте явный тег и в docker-compose.yml, и в значениях чарта. Причины две:

  • latest не позволяет понять, что именно развёрнуто, и не даёт откатиться на предыдущее состояние;
  • в Kubernetes под с latest не перечитает образ без явного перезапуска и политики imagePullPolicy: Always — легко получить смесь версий между репликами.

Проверьте, что тег есть у всех компонентов

Теги публикуются независимо, и не для каждой версии существует полный набор образов. Прежде чем менять версию, убедитесь, что нужный тег доступен для всех компонентов, которые вы разворачиваете: backend, worker, frontend, сканер конфигураций, DomainScope, образ песочницы.

Проверить перечень опубликованных тегов можно так:

for img in sshub-backend sshub-worker sshub-frontend \
           sshub-iac-scanner domain-scope sshub-sandbox-tools; do
  echo "== $img"
  curl -s "https://hub.docker.com/v2/repositories/dexionius/$img/tags?page_size=20" \
    | grep -o '"name":"[^"]*"'
done

Разворачивайте все компоненты одной версией. Интерфейс сравнивает свою версию X.Y с версией backend и показывает предупреждение при расхождении — это признак того, что обновились не все компоненты.

Перед обновлением — всегда

  1. Резервная копия базы — см. Эксплуатация.
  2. Проверить наличие тега у всех компонентов, как описано выше.
  3. Прочитать описание изменений к новой версии.
  4. Проверить переменные окружения — новая версия может требовать новых.
  5. Продумать откат: на какой тег возвращаться. Учтите, что миграции базы вперёд применяются автоматически, а обратно — нет.

Docker Compose

cd /opt/hub
docker compose pull
docker compose up -d

# Проверка
curl https://hub.example.com/version

Backend стартует, прокатывает миграции, потом обслуживает.

Kubernetes (Helm)

Задайте новый тег в значениях чарта и примените их:

helm upgrade hub ./charts/hub-platform -n hub -f values.yaml

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

Если вы всё же используете latest, смена тега не произойдёт сама: под не перечитает образ без imagePullPolicy: Always и явного перезапуска.

kubectl -n hub rollout restart deploy/hub-backend
kubectl -n hub rollout restart deploy/hub-worker
kubectl -n hub rollout restart deploy/hub-frontend

Миграции БД

Hub использует встроенную систему миграций — backend накатывает изменения схемы автоматически при старте.

Когда применяются

  • При старте backend
  • Применяется только то, чего нет в goose_db_version

Что важно знать

  • Прямые миграции — backend стартует, обновляет схему, потом начинает обслуживать
  • Обратной совместимости миграций нет — нельзя откатить схему на старую версию без рестора БД
  • Длительные миграции — release notes от поставщика отмечают ETA для тяжёлых миграций
  • Блокирующие — backend не отвечает на запросы пока миграция идёт

Если миграция упала

# Compose
docker compose logs backend | grep -i goose

# K8s
kubectl -n hub logs deploy/hub-backend | grep -i goose

# Состояние
docker compose exec postgres psql -U securityhub securityhub -c \
  "SELECT * FROM goose_db_version ORDER BY version_id DESC LIMIT 5;"

Если миграция упала — обычно goose откатывает транзакцию. Перезапустите backend. Если повторно падает — соберите логи и обратитесь к поставщику. Не правьте схему руками.

Rollback

Compose

# Остановить
docker compose down

# Восстановить БД из бэкапа (если миграции уже прокатились)
gunzip -c /backup/hub-pre-upgrade.sql.gz | docker compose exec -T postgres psql -U securityhub securityhub

# Откатиться на предыдущий образ (попросите у поставщика конкретный тэг)
# В .env: HUB_IMAGE_TAG=0.9.PREVIOUS
docker compose up -d

Kubernetes

# Helm revision history
helm history hub -n hub

# Откат на предыдущую ревизию
helm rollback hub <revision> -n hub

# Если БД продвинулась — restore + redeploy
kubectl -n hub scale deploy --all --replicas=0
# restore from PV snapshot / pgdump
helm rollback hub <revision> -n hub
kubectl -n hub scale deploy --all --replicas=2

DomainScope обновление

DomainScope обновляется независимо от Hub:

cd /opt/domainscope
docker compose pull
docker compose up -d

Совместимость API между Hub и DomainScope: оба сервиса используют публичные REST эндпоинты Hub (/api/v1/products/<id>/reports и /api/v1/projects/<id>/scope/proposals). При major-bump поставщик отмечает в release notes изменения контракта, если они есть.

Frontend и backend совместимость

Hub-frontend завязан на minor-версию backend. В footer UI отображается:

v0.9.20260602+a1b (frontend)  /  v0.9.20260601+x9y (backend)

При расхождении minor — warning в UI. При major — приложение может вести себя некорректно.

В compose/k8s они обновляются вместе (один тэг :latest).

Расписание обновлений

Окружение Частота
Staging / dev каждый минор
Pilot prod каждый минор +1 неделя после release
Production stable каждый второй минор, или security-only
Closed environments quarterly review + security patches

Hot-fix (security CVE) — катите ASAP в любом окружении.

Major-upgrade (X → X+1)

Major-upgrades содержат breaking changes. Перед накаткой:

  1. Прочитайте migration guide от поставщика
  2. Тестируйте на staging — полный цикл upload SARIF, Jira sync, notifications
  3. Запланируйте maintenance window (минимум 1 час)
  4. Подготовьте rollback-план (БД snapshot)
  5. Уведомите пользователей — за 24 часа

Major-upgrade обычно требует:

  • Обновить env vars (новые / переименованные)
  • Перенастроить интеграции (если поменялся формат конфига)
  • Сначала остановить worker, потом обновить backend, потом запустить worker

Связанные документы