Проверка целостности

Контроль Docker-образов, идентификация версий, защита конфигурации, верификация
ООО «Рапид.Исследовательские системы»
Версия: 1.1.2
Дата: март 2026

1. Назначение

Документ описывает механизмы контроля целостности программных компонентов и конфигурационных файлов платформы Rapeed BI на всех этапах: сборка, доставка, развёртывание, эксплуатация.

Основным инструментом автоматизированной проверки целостности Docker-образов является скрипт verify_digests.py, входящий в состав дистрибутива. Скрипт запрашивает SHA-256 digest каждого образа напрямую у реестра через Docker Registry API v2 и сравнивает с эталонными значениями из файла checksums.lock.

2. Объекты контроля целостности

ОбъектМеханизм контроляАлгоритм
Docker-образы компонентовverify_digests.py + checksums.lockSHA-256 (Docker-Content-Digest)
Конфигурационные файлыШифрование SOPS/AGEX25519 + ChaCha20-Poly1305
Дистрибутив (архивы образов)Image digest при загрузкеSHA-256

3. Контроль целостности Docker-образов

Каждый Docker-образ в реестре имеет неизменяемый идентификатор (digest). Digest вычисляется реестром как SHA-256 от манифеста образа. Любое изменение содержимого образа приводит к изменению digest.

3.1. Алгоритм получения digest

Скрипт verify_digests.py получает digest напрямую из реестра через Docker Registry API v2, не требуя скачивания образа:

# HTTP-запрос к реестру: GET https://<registry>/v2/<repository>/manifests/<tag> Accept: application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json # Реестр возвращает в заголовке ответа: Docker-Content-Digest: sha256:a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
Используется заголовок Docker-Content-Digest, возвращаемый реестром — это авторитетное значение, совпадающее с digest, по которому Docker выполняет docker pull image@sha256:.... Digest не вычисляется локально, а запрашивается у источника.

3.2. Реестр образов

ПараметрЗначение
Адрес реестра<адрес-реестра>
ПротоколHTTPS
АутентификацияBasic Auth (переменные REGISTRY_USER / REGISTRY_PASS или ~/.docker/config.json)
APIDocker Registry HTTP API v2
Неизменяемость digestГарантируется Docker Content Trust

3.3. Перечень контролируемых образов

ОбразНазначение
registry.rapeed.ai/rapeed-frontendВеб-интерфейс
registry.rapeed.ai/rapeed-services-widgetsREST API
registry.rapeed.ai/rapeed-services-idsАналитическое ядро
registry.rapeed.ai/rapeed-services-import-cppИмпорт данных
registry.rapeed.ai/rapeed-microservices-pivot-msСводные таблицы
registry.rapeed.ai/rapeed-microservices-ui-settings-msНастройки интерфейса
registry.rapeed.ai/rapeed-uploadЗагрузка файлов
registry.rapeed.ai/auth-proxyWebSocket-аутентификация
registry.rapeed.ai/rapeed-keycloakУправление идентификацией
registry.rapeed.ai/rapeed-grafanaМониторинг
registry.rapeed.ai/rapeed-composevectorСбор логов контейнеров

Помимо образов из приватного реестра, контролируются также сторонние образы, объявленные в docker-compose.yml: nginx, postgres, grafana/tempo, victoriametrics/*, ghcr.io/google/cadvisor, cr.yandex/mirror/rabbitmq.

3.4. Эталонный файл checksums.lock

Файл checksums.lock содержит зафиксированные digest всех образов, объявленных в docker-compose.yml. Генерируется при подготовке релиза и поставляется вместе с дистрибутивом.

# checksums.lock — сгенерирован verify_digests.py # НЕ редактируйте вручную. Обновить: python verify_digests.py --update meta: generated_at: "2026-03-24T10:00:00Z" generated_by: "verify_digests.py" compose_files: - "customers/rapeed/docker-compose.yml" images: "index.docker.io/library/nginx:1.29.1": digest: "sha256:b46f5cb5..." updated_at: "2026-03-24T10:00:01Z" "registry.rapeed.ai/rapeed-frontend:1.1.2": digest: "sha256:e9a2c3d4..." updated_at: "2026-03-24T10:00:02Z" "registry.rapeed.ai/rapeed-composevector:latest": digest: "sha256:aaaabbbb..." warning: "non-deterministic tag — digest may change without compose file update" updated_at: "2026-03-24T10:00:03Z"
Образы с тегами latest и development помечаются предупреждением (WARN): digest записывается в lock-файл для информации, но при проверке (--check) не сравнивается, так как тег не является детерминированным.

4. Защита конфигурации

Конфигурационные файлы, содержащие секреты, защищены шифрованием:

ПараметрЗначение
ИнструментMozilla SOPS
Бэкенд шифрованияAGE
Алгоритм обмена ключамиX25519
Алгоритм шифрования данныхChaCha20-Poly1305
Зашифрованный файл.env.enc
Ключ расшифровкиSOPS_AGE_KEY

4.1. Принцип работы

  1. В дистрибутиве поставляется только зашифрованный файл .env.enc
  2. Ключ расшифровки SOPS_AGE_KEY передаётся отдельно от дистрибутива
  3. При запуске скрипт установки расшифровывает конфигурацию в память
  4. Любое изменение зашифрованного файла без ключа приводит к ошибке расшифровки, подмена обнаруживается автоматически

4.2. Верификация

sops --decrypt .env.enc > /dev/null 2>&1 && echo "OK" || echo "INTEGRITY ERROR"

5. Контроль целостности при доставке

Дистрибутив содержит Docker-образы в виде архивов .tgz. Целостность контролируется на каждом этапе:

ЭтапМеханизмОписание
Сборка (CI/CD)Docker digestОбраз получает неизменяемый SHA-256 digest при публикации в реестр
Фиксация эталонаverify_digests.py --updateDigest всех образов из docker-compose.yml запрашивается у реестра и записывается в checksums.lock
Упаковкаcrane pull + saveОбраз выгружается из реестра с проверкой digest
ДоставкаЗашифрованный архивДистрибутив передаётся как единый пакет, включая checksums.lock
Установкаdocker loadПри загрузке образа Docker проверяет целостность слоёв
Верификация у заказчикаverify_digests.py --localDigest локально загруженных образов сравниваются с checksums.lock через docker inspect; доступ к реестру не требуется

6. Процедура верификации

6.1. Проверка digest образов у заказчика (основная процедура)

Скрипт verify_digests.py и файл checksums.lock входят в состав дистрибутива. Требования: Python 3.8+, библиотека pyyaml, Docker CLI. Доступ к реестру не требуется.

Шаг 1. Загрузите образы из архивов дистрибутива:

# Загрузить все образы из архивов .tgz: bash load_all_images.sh

Шаг 2. Запустите проверку целостности:

python verify_digests.py --local --file docker-compose.yml

Скрипт сравнивает digest каждого загруженного образа (через docker inspect) с эталонными значениями из checksums.lock. Сетевые подключения не выполняются.

Ожидаемый результат при успешной проверке:

Проверка локальных образов (19 образов)... [PASS] index.docker.io/library/nginx:1.29.1 [PASS] index.docker.io/library/postgres:16.9 [PASS] registry.rapeed.ai/rapeed-frontend:1.1.2 [PASS] registry.rapeed.ai/rapeed-services-ids:release-1-1-2-clang1 ... [WARN] registry.rapeed.ai/rapeed-composevector:latest (non-deterministic tag, skipped) ------------------------------------------------------- ИТОГ: 19 образов проверено PASS : 17 WARN : 2 Результат: OK

При обнаружении расхождения:

[FAIL] registry.rapeed.ai/rapeed-frontend:1.1.2 locked: sha256:e9a2c3d4... current: sha256:deadbeef... Результат: FAILED ← exit code 1
Статус FAIL означает, что загруженный образ не соответствует эталону из checksums.lock. Необходимо повторно получить дистрибутив у поставщика и убедиться в его целостности.
Статус ERROR / «Образ не найден локально» означает, что образ ещё не загружен. Проверьте, что выполнен docker load для всех архивов дистрибутива.

6.2. Обновление эталонного файла (выполняется вендором)

Процедура выполняется поставщиком при подготовке нового релиза — после публикации образов в реестр. Заказчику не требуется.

# Сгенерировать новый checksums.lock из docker-compose.yml: python verify_digests.py --update --file customers/rapeed/docker-compose.yml # Для нескольких compose-файлов в общий lock: python verify_digests.py --update \ --file customers/rapeed/docker-compose.yml \ --file demo/docker-deploy/docker-compose.yml \ --lockfile checksums.lock
Файл checksums.lock включается в дистрибутив вместе с docker-compose.yml и архивами образов.

6.3. Проверка целостности конфигурации

sops --decrypt .env.enc > /dev/null 2>&1 && echo "Configuration OK" || echo "Configuration CORRUPTED"

6.4. Справочник кодов статуса verify_digests.py

СтатусОписаниеДействие
PASSDigest совпадает с эталоном
FAILDigest изменился — образ подменён или обновлёнВыяснить причину, обновить lock или остановить деплой
WARNТег недетерминирован (latest, development)Рекомендуется перейти на версионные теги
MISSINGОбраз есть в compose, но отсутствует в checksums.lockОбратиться к поставщику — возможно, устаревший lock-файл
ERRORОбраз не найден локально или ошибка docker inspectУбедиться, что docker load выполнен для всех архивов

6.5. Коды завершения и автоматизация

Скрипт возвращает код выхода 0 при успехе и 1 при наличии статусов FAIL или ERROR.

# Верификация у заказчика (после docker load, без доступа к реестру): python verify_digests.py --local --file docker-compose.yml --quiet \ || { echo "Integrity check FAILED — обратитесь к поставщику"; exit 1; }