Перейти к основному содержимому
Monolit

Monolit / Архив 1.3.1

Руководство администратора

Установка в Docker Compose и Kubernetes, пользователи, REST API, CI/CD, резервное копирование, мониторинг.

Это документация Monolit 1.3.1. Актуальная версия — 1.3.4.

Открыть актуальную

Введение

Monolit — программная платформа для организации процесса безопасной разработки на стороне заказчика. Она объединяет инструменты статического анализа безопасности исходного кода (SAST), анализа зависимостей (SCA) и проверки выполнения правил кодирования (Linters), предоставляет веб-интерфейс для управления результатами сканирования, приложениями и уязвимостями, а также помогает формализовать выполнение требований ГОСТ Р 56939-2024.

Инструкция по установке

Требования к системе​

Минимальные и рекомендуемые системные требования:

  • Операционная система: Linux (Ubuntu 24.04.1 LTS или выше)
  • Процессор: 4 ядра
  • Оперативная память: 8 GB RAM
  • Свободное место: 50 GB
  • Сетевое подключение: Требуется для установки и получения обновлений

Установка в Docker (Docker Compose)​

  • Установка Docker и Docker Compose

Для установки платформы необходимо запустить скрипт установки:

curl -fsSL -o install.sh https://sdlplatform.ru/sdlplatform/install.sh && sudo bash install.sh

Скрипт автоматически:

  1. Проверит наличие Docker и Docker Compose (предложит установить, если не найдены)
  2. Скачает необходимые файлы в директорию sdlplatform/
  3. Запросит параметры конфигурации:
  • Порт — на котором будет доступна платформа (по умолчанию 80)
  • Версия (TAG) — версия образов для установки
  • Registry — адрес Docker Registry (по умолчанию registry.sdlplatform.ru)
  • Параметры БД — имя пользователя и базы данных PostgreSQL
  • Email-уведомления — настройки SMTP (опционально)
  • Интеграции — AppScreener, PT AI (опционально)
  1. Автоматически сгенерирует секреты (SECRET_KEY, пароли БД и MinIO)
  2. Выполнит авторизацию в Docker Registry
  3. Запустит платформу

Платформа включает следующие сервисы:

  • postgres — база данных PostgreSQL

  • minio — S3-совместимое объектное хранилище (бакеты: PDF-отчёты, свидетельства и шаблоны документов соответствия compliance-evidence)

  • nats — брокер сообщений для асинхронной коммуникации

  • redis — кеш и хранилище временных данных

  • backend — FastAPI-приложение с REST API

  • frontend — веб-интерфейс

  • nginx — обратный прокси-сервер

  • ml_triage_producer, ml_triage_analyzer, ml_triage_writer, ml_triage_janitor — конвейер AI-триажа уязвимостей (постановка задач, вызов AI-сервиса, запись результата, обслуживание очереди)

  • worker_ml_extractor — извлечение фрагмента кода вокруг места срабатывания для передачи в AI-сервис

  • butler_service — сервис управления задачами сканирования

  • pdf_generation_outbox — обработка очереди заданий на формирование PDF-отчётов

  • pdf_generator — сервис генерации PDF-отчётов

  • worker_* — воркеры для различных сканеров (semgrep, bandit, gosec, codeql, trivy, и др.)

  • Обновление

Для обновления необходимо заменить переменную TAG в .env на новую версию ПО

Запустить скрипт обновления:

bash update.sh

Установка в Kubernetes​

Helm chart и образы размещены в Harbor registry.sdlplatform.ru.

Требования:

  • Kubernetes кластер
  • kubectl
  • Helm 3 с поддержкой OCI (Helm 3.8+)
  • Ingress controller: NGINX
  • Storage: используется default StorageClass кластера
  • Доступ к registry.sdlplatform.ru (учётные данные robot account с правами pull в project sdlplatform)

Подготовка доступа к registry

Для скачивания образов и chart используйте учётные данные robot account, которые вам предоставил поставщик:

  • <name> — имя robot account (часть после robot$sdlplatform+, например pull-client)
  • <ROBOT_PASSWORD> — токен robot account, выданный при создании учётной записи
  1. Выполните логин в registry (для Helm OCI):
helm registry login registry.sdlplatform.ru -u 'robot$sdlplatform+<name>' -p '<ROBOT_PASSWORD>'

Если токен содержит спецсимволы:

printf '%s' '<ROBOT_PASSWORD>' | helm registry login registry.sdlplatform.ru -u 'robot$sdlplatform+<name>' --password-stdin
  1. Создайте imagePullSecret (чтобы kubelet мог загружать образы):
kubectl create namespace sdlplatform || true

kubectl -n sdlplatform create secret docker-registry registry-secret \
--docker-server=registry.sdlplatform.ru \
--docker-username='robot$sdlplatform+<name>' \
--docker-password='<ROBOT_PASSWORD>'
  1. Если в кластере возникает ошибка 429 Too Many Requests из-за ограничений DockerHub, добавьте учётные данные DockerHub отдельным secret:
  • <DOCKERHUB_USER> — логин на hub.docker.com
  • <DOCKERHUB_TOKEN_OR_PASSWORD> — access token или пароль от Docker Hub
kubectl -n sdlplatform create secret docker-registry dockerhub-secret \
--docker-server=docker.io \
--docker-username='<DOCKERHUB_USER>' \
--docker-password='<DOCKERHUB_TOKEN_OR_PASSWORD>'

Установка релиза

Релизная версия соответствует git-тэгу, например 1.2.0. Установка и все последующие обновления выполняются через файл values-prod.yaml.

Подготовьте values-prod.yaml:

cat > values-prod.yaml <<'YAML'
global:
imageRegistry: registry.sdlplatform.ru/sdlplatform/
imageTag: "1.2.0"
imagePullSecrets:
- registry-secret
- dockerhub-secret

ingress:
host: sdlplatform.example.com

config:
data:
NOTIFICATIONS_ENABLED: "false"
SMTP_HOST: ""
SMTP_PORT: ""
SMTP_USER: ""
SMTP_CONNECTION_TYPE: ""
APPSCREENER_URL: ""
PTAI_URL: ""
PORT: "8000"

secrets:
stringData:
SMTP_PASSWORD: ""
APPSCREENER_TOKEN: ""
PTAI_TOKEN: ""
YAML

Запустите установку через helm:

helm upgrade --install sdlplatform oci://registry.sdlplatform.ru/sdlplatform/sdlplatform \
--version 1.2.0 \
--namespace sdlplatform \
--create-namespace \
-f values-prod.yaml

Во время установки/обновления backend автоматически применяет миграции БД (Alembic) через initContainer. Первый запуск может занять 1–2 минуты.

Переменные окружения

Backend получает переменные из ConfigMap sdlplatform-config и Secret sdlplatform-secrets.

В ConfigMap задайте:

  • NOTIFICATIONS_ENABLED (true/false)
  • SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_CONNECTION_TYPE (tls/ssl)
  • APPSCREENER_URL, PTAI_URL (опционально)
  • PORT (опционально, по умолчанию — 80)

В Secrets задайте:

  • SMTP_PASSWORD
  • APPSCREENER_TOKEN, PTAI_TOKEN (опционально)

ConfigMap и Secret создаются chart'ом. Для изменения настроек отредактируйте values-prod.yaml и выполните helm upgrade с этим файлом.

Обновление релиза

Укажите версию:

RELEASE_VERSION=1.3.1

sed -i -E 's/^( imageTag: ).*$/\1"'"$RELEASE_VERSION"'"/' values-prod.yaml

Выполните обновление:

helm upgrade --install sdlplatform oci://registry.sdlplatform.ru/sdlplatform/sdlplatform \
--version "$RELEASE_VERSION" \
--namespace sdlplatform \
-f values-prod.yaml

Удаление

helm uninstall sdlplatform -n sdlplatform

Управление пользователями

Учётные данные по умолчанию​

После первого запуска в базе данных создаётся тестовая учётная запись суперпользователя:

ПолеЗначение
Emaildemo@example.com
Парольdemo

Используйте эти данные для первоначального входа и проверки работоспособности платформы. После настройки окружения замените тестовую учётную запись на рабочую или создайте новых пользователей.

Управление через веб-интерфейс​

Рекомендуемый способ управления пользователями — раздел «Пользователи» в веб-интерфейсе платформы. Доступен Администратору и Суперадминистратору.

Позволяет:

  • создавать учётные записи и задавать тип (regular, admin, super_admin)
  • редактировать данные (имя, тип учётной записи)
  • блокировать и разблокировать пользователей
  • выполнять массовые операции (смена типа, блокировка группы)

Подробное описание операций — в Руководстве пользователя, раздел «Управление пользователями».

Управление через API​

Для автоматизации (скрипты onboarding, CI/CD) управление пользователями доступно через REST API. Требуется токен Суперадминистратора. Доступны операции: создание, редактирование, массовая блокировка, смена типа и сброс типа до regular.

Примеры запросов приведены в разделе «Пользователи» → REST API данного руководства.

Аварийные операции через БД​

Внимание. Операции через БД предназначены только для аварийных ситуаций: утери доступа суперадминистратора, недоступности бэкенда или миграции данных. В штатной работе используйте веб-интерфейс или API.

Создание пользователя​

Для добавления пользователя напрямую в базу данных PostgreSQL выполните следующие шаги:

  1. Сгенерируйте bcrypt-хеш пароля:
docker compose exec backend python -c "from passlib.context import CryptContext; pwd_context = CryptContext(schemes=['bcrypt'], deprecated='auto'); print(pwd_context.hash('ВАШ_ПАРОЛЬ'))"

Хеш должен быть длиной ~60 символов и начинаться с $2b$12$. Пример: $2b$12$yPhCZhH.wtAFPri2o2xJPOGulZ8U0WXPmKWzVWmebc1xzBbBE7RQm

  1. Добавьте пользователя в БД:
# Экранируйте символы $ в хеше: замените $ на \$
docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
INSERT INTO \"user\" (email, hashed_password, is_active, type, full_name)
VALUES ('user@example.com', '\$2b\$12\$ОСТАЛЬНАЯ_ЧАСТЬ_ХЕША', true, 'regular', 'Полное Имя');
"

⚠️ Важно:

  • Символы $ в хеше нужно экранировать обратными слешами: \$
  • Bcrypt-хеш $2b$12$abc... должен превратиться в \$2b\$12\$abc...
  • Без экранирования bash интерпретирует $ как переменные, и хеш будет неполным

Для создания суперадминистратора установите type в super_admin:

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
INSERT INTO \"user\" (email, hashed_password, is_active, type, full_name)
VALUES ('admin@example.com', '\$2b\$12\$ОСТАЛЬНАЯ_ЧАСТЬ_ХЕША', true, 'super_admin', 'Администратор');
"

Полный пример:

# 1. Генерируем хеш
docker compose exec backend python -c "from passlib.context import CryptContext; pwd_context = CryptContext(schemes=['bcrypt'], deprecated='auto'); print(pwd_context.hash('mypassword123'))"
# Получаем: $2b$12$sze/sfRE5RiG8KEFh42.QOwT8hgyipXVsBqt8qb3paWuDxwJpA4gu

# 2. Вставляем с экранированием $ → \$
docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
INSERT INTO \"user\" (email, hashed_password, is_active, type, full_name)
VALUES ('newuser@example.com', '\$2b\$12\$sze/sfRE5RiG8KEFh42.QOwT8hgyipXVsBqt8qb3paWuDxwJpA4gu', true, 'regular', 'New User');
"

Структура таблицы user:

  • id — автоинкрементный первичный ключ
  • email — уникальный email пользователя
  • hashed_password — bcrypt-хеш пароля
  • is_active — флаг активности (true/false)
  • type — тип пользователя: super_admin, admin, regular (по умолчанию regular)
  • full_name — полное имя пользователя (опционально)
  • created_at — дата и время создания

Просмотр пользователей​

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "SELECT id, email, is_active, type, full_name, created_at FROM \"user\";"

Удаление пользователя​

Перед удалением пользователя необходимо проверить, есть ли у него связанные данные (приложения, комментарии и т.д.).

Проверка связанных приложений:

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
SELECT id, name, owner_id FROM application WHERE owner_id = (SELECT id FROM \"user\" WHERE email='user@example.com');
"

Вариант 1: Удаление со всеми связанными данными

Удаляет пользователя вместе со всеми его приложениями и сканами (используйте с осторожностью!):

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
BEGIN;
-- Удаляем приложения пользователя (каскадно удалятся все связанные сканы)
DELETE FROM application WHERE owner_id = (SELECT id FROM \"user\" WHERE email='user@example.com');
-- Удаляем комментарии пользователя
DELETE FROM comments WHERE user_id = (SELECT id FROM \"user\" WHERE email='user@example.com');
-- Удаляем пользователя
DELETE FROM \"user\" WHERE email='user@example.com';
COMMIT;
"

Вариант 2: Переназначение приложений другому пользователю

Передаёт все приложения пользователя другому владельцу перед удалением:

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
BEGIN;
-- Переназначаем приложения на другого пользователя
UPDATE application
SET owner_id = (SELECT id FROM \"user\" WHERE email='new_owner@example.com')
WHERE owner_id = (SELECT id FROM \"user\" WHERE email='user@example.com');
-- Удаляем комментарии пользователя
DELETE FROM comments WHERE user_id = (SELECT id FROM \"user\" WHERE email='user@example.com');
-- Удаляем пользователя
DELETE FROM \"user\" WHERE email='user@example.com';
COMMIT;
"

Вариант 3: Деактивация пользователя (рекомендуется)

Вместо удаления можно деактивировать пользователя, сохранив историю:

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
UPDATE \"user\" SET is_active = false WHERE email='user@example.com';
"

Исправление пароля пользователя​

Если при входе возникает ошибка hash could not be identified, значит пароль был сохранён неправильно (не как bcrypt-хеш).

Исправление пароля:

# 1. Сгенерируйте новый хеш
docker compose exec backend python -c "from passlib.context import CryptContext; pwd_context = CryptContext(schemes=['bcrypt'], deprecated='auto'); print(pwd_context.hash('НОВЫЙ_ПАРОЛЬ'))"

# 2. Обновите пароль в БД (не забудьте экранировать $ → \$)
docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
UPDATE \"user\" SET hashed_password = '\$2b\$12\$ОСТАЛЬНАЯ_ЧАСТЬ_ХЕША' WHERE email='user@example.com';
"

Проверка правильности хешей всех пользователей:

docker compose exec postgres psql -U sdlplatform -d sdlplatform -c "
SELECT id, email, length(hashed_password) as hash_length, substring(hashed_password, 1, 7) as hash_start
FROM \"user\";
"

Правильный bcrypt-хеш должен иметь длину 60 символов и начинаться с $2b$12$.

REST API: примеры запросов

Все запросы к API требуют JWT-токена. Задайте переменные окружения один раз и используйте их во всех командах ниже:

BASE_URL="https://<ваш-хост>"

# Получить токен (username — email пользователя)
TOKEN=$(curl -s -X POST "$BASE_URL/api/v1/login/access-token" \
-d "username=demo@example.com&password=demo" | jq -r .access_token)

Healthcheck​

# Проверить состояние сервиса
curl -s "$BASE_URL/api/v1/healthcheck"

Пользователи​

# Текущий пользователь
curl -s "$BASE_URL/api/v1/users/me" \
-H "Authorization: Bearer $TOKEN"

# Список всех пользователей (только администраторы)
curl -s "$BASE_URL/api/v1/users" \
-H "Authorization: Bearer $TOKEN"

# Создать пользователя (только суперадминистратор)
curl -s -X POST "$BASE_URL/api/v1/users" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "newuser@example.com",
"password": "securepassword",
"full_name": "Иван Иванов",
"type": "regular"
}'
# type: "regular" | "admin" | "super_admin"

# Редактировать пользователя (только суперадминистратор)
curl -s -X PATCH "$BASE_URL/api/v1/users/<USER_ID>" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"full_name": "Новое Имя", "type": "admin"}'

# Массово заблокировать пользователей (только суперадминистратор)
curl -s -X POST "$BASE_URL/api/v1/users/bulk/is-active" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [2, 3], "is_active": false}'

# Массово изменить тип пользователей (только суперадминистратор)
curl -s -X POST "$BASE_URL/api/v1/users/bulk/type" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [2, 3], "type": "admin"}'

# Массово сбросить тип пользователей до regular (только суперадминистратор)
curl -s -X POST "$BASE_URL/api/v1/users/bulk/type/reset" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [2, 3]}'

Лицензия​

Жизненный цикл лицензии​

Платформа проверяет состояние лицензии автоматически. Возможные статусы:

СтатусОписание
activeЛицензия действительна
warningДо окончания лицензии осталось менее 30 дней
grace_periodСрок действия истёк, доступен льготный период (14 дней)
blockedЛьготный период истёк — API заблокировано (кроме суперадминистратора)
no_licenseЛицензия не внесена

При статусах blocked и no_license все эндпоинты возвращают 402 Payment Required, кроме:

  • POST /api/v1/auth/login
  • GET /api/v1/license/get_license
  • POST /api/v1/license/import
  • GET /api/v1/users/me

Суперадминистратор может войти в систему и внести лицензию при любом статусе.

При статусах warning и grace_period платформа автоматически рассылает email-уведомления всем суперадминистраторам (не чаще одного раза в 24 часа).

Лимит приложений​

Лицензия ограничивает максимальное количество приложений (max_applications). При превышении лимита создание нового приложения вернёт 402 с кодом license_app_limit_exceeded. Значение -1 означает отсутствие ограничений.

# Просмотр текущего статуса лицензии
curl -s "$BASE_URL/api/v1/license/get_license" \
-H "Authorization: Bearer $TOKEN"
# Пример ответа:
# {
# "status": "warning",
# "license_data": { "license_id": "...", "owner": "...", "valid_until": "2026-03-01T00:00:00Z", ... },
# "days_remaining": 12,
# "grace_period_ends_at": "2026-03-15T00:00:00Z"
# }

# Импорт лицензии (требует прав суперадминистратора)
curl -s -X POST "$BASE_URL/api/v1/license/import" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"license_data": "<ВАШ_КЛЮЧ>"}'

# Удалить лицензию
curl -s -X POST "$BASE_URL/api/v1/license/import" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"license_data": null}'

API-токены​

API-токен — долгоживущий credentials для CI/CD-пайплайнов и скриптов. В отличие от JWT, он не истекает автоматически: его можно отозвать только явным запросом. Токен показывается один раз при создании — сохраните его.

# Создать API-токен (требует активной сессии JWT)
# Возвращает JSON с полем access_token
curl -s -X POST "$BASE_URL/api/v1/tokens" \
-H "Authorization: Bearer $JWT_TOKEN"

Полученный access_token используйте в дальнейших запросах через заголовок X-Integration-Key:

# Пример запроса с API-токеном
curl -s "$BASE_URL/api/v1/applications/" \
-H "X-Integration-Key: Bearer $API_TOKEN"

Заголовок X-Integration-Key: Bearer <token> принимается всеми защищёнными эндпоинтами API наравне со стандартным Authorization: Bearer <jwt>.


Приложения​

# Список приложений
curl -s "$BASE_URL/api/v1/applications/" \
-H "Authorization: Bearer $TOKEN"

# Создать приложение
curl -s -X POST "$BASE_URL/api/v1/applications/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "My App", "description": "Описание проекта"}'

# Удалить приложение
curl -s -X DELETE "$BASE_URL/api/v1/applications/<APP_ID>" \
-H "Authorization: Bearer $TOKEN"

Загрузка архива и сканирование​

# Загрузить архив исходного кода (ZIP) и запустить сканирование
curl -s -X POST "$BASE_URL/api/v1/applications/<APP_ID>/scan_upload" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@/путь/к/архиву.zip"

# Запустить сканирование по последней ревизии приложения
curl -s -X POST "$BASE_URL/api/v1/scans/start?application_id=<APP_ID>" \
-H "Authorization: Bearer $TOKEN"

# Прогресс сканирования
curl -s "$BASE_URL/api/v1/scans/<SCAN_ID>/progress" \
-H "Authorization: Bearer $TOKEN"

# Ошибки сканирования
curl -s "$BASE_URL/api/v1/scans/<SCAN_ID>/errors" \
-H "Authorization: Bearer $TOKEN"

Уязвимости​

# Список уязвимостей по приложению (первые 50)
curl -s "$BASE_URL/api/v1/vulnerability/?application_id=<APP_ID>&limit=50&skip=0" \
-H "Authorization: Bearer $TOKEN"

# Количество уязвимостей
curl -s "$BASE_URL/api/v1/vulnerability/count" \
-H "Authorization: Bearer $TOKEN"

# Лента «Активность» по уязвимости (изменения статуса и критичности)
curl -s "$BASE_URL/api/v1/vulnerability/<VULN_ID>/history?limit=50&skip=0" \
-H "Authorization: Bearer $TOKEN"
# Опциональный фильтр по типу события: ?type=STATUS или ?type=SEVERITY

# Перевод статуса уязвимости (FSM)
curl -s -X POST "$BASE_URL/api/v1/vulnerability/<VULN_ID>/transition" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"CONFIRMED"}'

# Массовый перевод статуса (атомарно для всего набора)
curl -s -X POST "$BASE_URL/api/v1/vulnerability/bulk/transition" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids":[1,2,3],"status":"FALSE_POSITIVE","comment":"Обоснование"}'

# Массовое изменение критичности
curl -s -X POST "$BASE_URL/api/v1/vulnerability/bulk" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids":[1,2,3],"data":{"severity":"high"}}'

Ответ эндпоинта списка уязвимостей содержит ключ "vulnerabilities" (массив) и "count" (общее число).

Допустимые значения status: UNDER_REVIEW, CONFIRMED, IN_PROGRESS, REQUIRES_VERIFICATION, REJECTED_FIX, FIXED, FALSE_POSITIVE, ACCEPTED_RISK, DUPLICATE. Для ряда переходов требуется обязательное comment — иначе вернётся 400. 403 — у пользователя нет права на данный переход; 404 — уязвимость не найдена или недоступна.


Отчёты​

# Создать PDF-отчёт по приложению
curl -s -X POST "$BASE_URL/api/v1/reports" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"app_id": <APP_ID>,
"title": "Отчёт 2026-01-24",
"vuln_filters": {
"statuses": ["UNDER_REVIEW", "CONFIRMED"],
"severities": ["critical", "high"]
}
}'
# statuses — значения единого статуса жизненного цикла: UNDER_REVIEW, CONFIRMED,
# IN_PROGRESS, REQUIRES_VERIFICATION, REJECTED_FIX, FIXED, FALSE_POSITIVE,
# ACCEPTED_RISK, DUPLICATE.

# Список отчётов
curl -s "$BASE_URL/api/v1/reports" \
-H "Authorization: Bearer $TOKEN"

# Отменить генерацию отчёта (доступно пока статус created или processing)
curl -s -X POST "$BASE_URL/api/v1/reports/<REPORT_ID>/cancel" \
-H "Authorization: Bearer $TOKEN"
# 400 — если отчёт уже завершён, упал или отменён

# Скачать PDF-отчёт
curl -s -OJ "$BASE_URL/api/v1/reports/<REPORT_ID>/download" \
-H "Authorization: Bearer $TOKEN"

Ответ эндпоинта списка отчётов содержит ключ "reports" (массив). Статусы отчёта: created → processing → completed / failed / cancelled.

Соответствие ГОСТ (Compliance)​

# Получить дашборд соответствия
curl -s "$BASE_URL/api/v1/compliance/dashboard" \
-H "Authorization: Bearer $TOKEN"

Пример ответа:

{
"total": 25,
"compliant": 5,
"partial": 3,
"non_compliant": 15,
"not_applicable": 2,
"score_percent": 21.7,
"categories": [
{
"category": "planning",
"total": 5,
"compliant": 1,
"partial": 1,
"non_compliant": 3,
"not_applicable": 0
}
],
"requirements": [
{
"id": 1,
"code": "5.1",
"title": "Планирование процессов разработки безопасного программного обеспечения",
"category": "planning",
"sort_order": 1,
"is_automatable": false,
"has_template": true,
"evidence_count": 2,
"status": {
"status": "partial",
"auto_status": null,
"manual_status": "partial"
}
}
]
}

score_percent — процент выполненных требований (compliant / (total - not_applicable) * 100), округлён до одного знака.

AI-интеграции​

# Создать AI-интеграцию и сразу привязать к приложениям
curl -s -X POST "$BASE_URL/api/v1/ml-integration/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "ML Prod", "url": "https://ml.example.com", "app_ids": [1, 2]}'

# Список AI-интеграций (фильтры: name, is_active)
curl -s "$BASE_URL/api/v1/ml-integration/?is_active=true" \
-H "Authorization: Bearer $TOKEN"

# Проверить доступность произвольного URL без сохранения
curl -s -X POST "$BASE_URL/api/v1/ml-integration/check-access" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://ml.example.com"}'

# Привязать или отвязать AI-интеграцию у приложения (null — отвязать)
curl -s -X POST "$BASE_URL/api/v1/applications/<APP_ID>/link-ml-integration" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ml_integration_id": 1}'

Создание и обновление интеграции проверяют доступность AI-сервиса по GET /health. Ответ check-access: {"id": null, "access": "available"|"unavailable"}.

Параметры конвейера AI-триажа задаются переменными окружения backend-сервисов:

ПеременнаяНазначение
ML_API_TIMEOUTТаймаут HTTP-запроса к AI-сервису (по умолчанию 180 с)
ML_TRIAGE_BATCH_SIZEРазмер пачки задач, забираемых из очереди за один опрос
ML_TRIAGE_ANALYZER_CONCURRENCYЧисло параллельных вызовов AI-сервиса в одной реплике
ML_STUCK_AGE_MINВозраст «зависшей» задачи, после которого она возвращается в очередь
ML_MAX_ATTEMPTSМаксимальное число попыток обработки задачи
ML_OUTBOX_TTL_DAYSСрок хранения завершённых задач до удаления

Ограничение: ML_STUCK_AGE_MIN (в секундах) должен быть больше 3 × ML_API_TIMEOUT, иначе backend не запустится. При значениях по умолчанию условие выполняется (1800 с > 540 с).

Jira-интеграции​

# Проверить доступность Jira до сохранения интеграции (token обязателен)
curl -s -X POST "$BASE_URL/api/v1/integrations/check_url" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://jira.example.com", "token": "<PAT>", "auth_type": "pat"}'

# Создать Jira-интеграцию (перед записью проверяется доступность; сохраняется
# только при успехе)
curl -s -X POST "$BASE_URL/api/v1/integrations/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"integration_type": "jira", "name": "Monolit-Jira", "url": "https://jira.example.com", "token": "<PAT>", "config": {"auth_type": "pat"}}'

# Список интеграций (фильтр по типу: ptai | appscreener | jira)
curl -s "$BASE_URL/api/v1/integrations/?integration_type=jira" \
-H "Authorization: Bearer $TOKEN"

# Перепроверить доступ к сохранённой интеграции (опционально с project_key)
curl -s -X POST "$BASE_URL/api/v1/integrations/<INTEGRATION_ID>/check_access" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project_key": "SDL"}'

# Список Jira-проектов, видимых интеграцией
curl -s "$BASE_URL/api/v1/jira/<INTEGRATION_ID>/projects" \
-H "Authorization: Bearer $TOKEN"

# Типы задач для проекта
curl -s "$BASE_URL/api/v1/jira/<INTEGRATION_ID>/issue_types?project_key=SDL" \
-H "Authorization: Bearer $TOKEN"

# Создать тестовый тикет и сразу удалить его (проверка прав и полей)
curl -s -X POST "$BASE_URL/api/v1/integrations/<INTEGRATION_ID>/test_ticket" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project_key": "SDL", "issue_type": "Bug"}'

# Массовое удаление интеграций
curl -s -X POST "$BASE_URL/api/v1/integrations/bulk_delete" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": [1, 2, 3]}'

# Отвязать все приложения от интеграции
curl -s -X POST "$BASE_URL/api/v1/integrations/<INTEGRATION_ID>/detach_applications" \
-H "Authorization: Bearer $TOKEN"

Привязка приложения к Jira выполняется обновлением приложения (PUT /api/v1/applications/<APP_ID>) с полями task_tracker_integration_id, task_tracker_enabled и task_tracker_settings:

# Включить баг-трекинг для приложения
curl -s -X PUT "$BASE_URL/api/v1/applications/<APP_ID>" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"task_tracker_integration_id": 1, "task_tracker_enabled": true, "task_tracker_settings": {"type": "jira", "project_key": "SDL", "issue_type": "Bug"}}'

# Фоновый экспорт всех уязвимостей приложения в Jira (202 Accepted, job_id)
curl -s -X POST "$BASE_URL/api/v1/application/<APP_ID>/export_to_task_tracker" \
-H "Authorization: Bearer $TOKEN"

# Перенести тикеты приложения в другой проект той же интеграции
curl -s -X POST "$BASE_URL/api/v1/applications/<APP_ID>/migrate_task_tracker_project" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"new_project_key": "SDL2", "new_issue_type": "Bug"}'

# Отвязать приложение от трекера
curl -s -X POST "$BASE_URL/api/v1/applications/<APP_ID>/detach_task_tracker" \
-H "Authorization: Bearer $TOKEN"

# Создать тикет в Jira для отдельной уязвимости вручную
curl -s -X POST "$BASE_URL/api/v1/vulnerability/<VULN_ID>/task_tracker_ticket" \
-H "Authorization: Bearer $TOKEN"

# Удалить тикет, привязанный к уязвимости
curl -s -X DELETE "$BASE_URL/api/v1/vulnerability/<VULN_ID>/task_tracker_ticket" \
-H "Authorization: Bearer $TOKEN"

Токен Jira (PAT) должен содержать только ASCII-символы и иметь права на просмотр проекта, создание и редактирование тикетов, добавление комментариев и переходы по статусам. Для аутентификации поддерживаются pat (по умолчанию) и basic (требует username в config).

Полная документация по API доступна в Swagger UI: $BASE_URL/api/v1/docs


Интеграция с CI/CD

Monolit поддерживает интеграцию с CI/CD для автоматического запуска анализа безопасности при сборке кода. Это позволяет внедрить анализ кода в каждую сборку и обнаруживать уязвимости до развёртывания приложения.

Для аутентификации в CI/CD используйте API-токен (см. раздел API-токены). Передавайте его через заголовок X-Integration-Key: Bearer <API_TOKEN>. Переменную API_TOKEN рекомендуется хранить в секретах пайплайна, а не в тексте конфигурации.

Интеграция с GitLab CI​

Для интеграции с GitLab CI необходимо вызвать API Monolit и передать исходный код для сканирования. Пример файла .gitlab-ci.yml:

stages:
- build
- security

variables:
MONOLIT_HOST: "https://<MONOLIT_HOST>"
APPLICATION_ID: "<APPLICATION_ID>"

build:
stage: build
script:
- zip -r /tmp/sources.zip .

security_scan:
stage: security
script:
- |
curl -s -X POST \
-H "X-Integration-Key: Bearer $MONOLIT_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "file=@/tmp/sources.zip" \
"$MONOLIT_HOST/api/v1/applications/$APPLICATION_ID/scan_upload"
- rm /tmp/sources.zip
allow_failure: true

Переменную MONOLIT_API_TOKEN добавьте в настройки проекта GitLab → Settings → CI/CD → Variables (тип: Masked).

  • build — этап сборки, на котором код архивируется для дальнейшей отправки на анализ.
  • security_scan — отправка ZIP-архива с исходным кодом на сервер Monolit для сканирования.

Интеграция с Jenkins​

Для интеграции с Jenkins можно использовать команду curl, чтобы отправить код на анализ в Monolit:

  • Создайте задачу (job) в Jenkins для запуска сканирования.
  • Добавьте переменную MONOLIT_API_TOKEN в Jenkins Credentials (тип: Secret text).
  • В разделе Build Steps добавьте выполнение следующего shell-скрипта:
#!/bin/bash
# Архивирование исходного кода
zip -r /tmp/sources.zip .

# Отправка в Monolit для сканирования
curl -s -X POST \
-H "X-Integration-Key: Bearer $MONOLIT_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "file=@/tmp/sources.zip" \
"https://<MONOLIT_HOST>/api/v1/applications/<APPLICATION_ID>/scan_upload"

# Очистка временных файлов
rm /tmp/sources.zip

Интеграция с другими CI/CD-системами​

Для других систем (CircleCI, Travis CI, TeamCity) используйте аналогичные команды. Пример для CircleCI:

version: 2.1
jobs:
security_scan:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: Архивирование исходного кода
command: zip -r /tmp/sources.zip .
- run:
name: Отправка в Monolit
command: |
curl -s -X POST \
-H "X-Integration-Key: Bearer $MONOLIT_API_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "file=@/tmp/sources.zip" \
"https://<MONOLIT_HOST>/api/v1/applications/<APPLICATION_ID>/scan_upload"
- run:
name: Очистка
command: rm /tmp/sources.zip

Переменную MONOLIT_API_TOKEN добавьте в настройки проекта CircleCI → Project Settings → Environment Variables.

Получение результатов сканирования​

После выполнения сканирования результаты доступны в интерфейсе приложения, а также через API:

# Прогресс сканирования приложения
curl -s -H "X-Integration-Key: Bearer $MONOLIT_API_TOKEN" \
"https://<MONOLIT_HOST>/api/v1/applications/<APPLICATION_ID>/scan_progress"

# Перечень уязвимостей приложения
curl -s -H "X-Integration-Key: Bearer $MONOLIT_API_TOKEN" \
"https://<MONOLIT_HOST>/api/v1/applications/<APPLICATION_ID>/vulnerabilities?type=sast&skip=0&limit=50"
curl -s -H "X-Integration-Key: Bearer $MONOLIT_API_TOKEN" \
"https://<MONOLIT_HOST>/api/v1/applications/<APPLICATION_ID>/vulnerabilities?type=sca&skip=0&limit=50"

Резервное копирование и восстановление данных

Резервное копирование базы данных​

  • Ручное резервное копирование базы данных PostgreSQL из контейнера Docker с помощью pg_dump:

Чтобы выполнить резервное копирование базы данных, работающей в контейнере Docker, выполните следующую команду:

docker compose exec -T postgres \
pg_dump -U sdlplatform sdlplatform > monolit_backup.sql
  • postgres — имя сервиса PostgreSQL в docker-compose.yml.

  • sdlplatform — имя пользователя и базы данных по умолчанию (исторически совпадают).

  • monolit_backup.sql — путь к файлу резервной копии на хосте.

  • Автоматическое резервное копирование: Настройте Cron для регулярного выполнения резервного копирования базы данных. Пример для выполнения резервного копирования каждый день в 2:00:

0 2 * * * cd /path/to/monorepo && docker compose exec -T postgres pg_dump -U sdlplatform sdlplatform > /backups/monolit_db_$(date +\%F).sql

Резервное копирование файлов конфигурации​

Кроме базы данных, важно регулярно сохранять конфигурационные файлы системы. Эти файлы включают:

  • Файлы конфигурации Docker (docker-compose.yml, docker-compose.override.yml)
  • Переменные окружения (.env)
  • Файлы конфигурации Nginx (nginx.conf, nginx-dev.conf)
  • SSL-сертификаты (keys/ssl/)
  • Файлы аутентификации (keys/.htpasswd)

Пример команды для резервного копирования конфигурационных файлов:

tar -czvf /backups/config_backup_$(date +\%F).tar.gz /path/to/configs/

Восстановление базы данных​

Чтобы восстановить базу данных из резервной копии, выполните команду psql внутри контейнера Docker:

docker compose exec -T postgres psql -U sdlplatform -d sdlplatform < monolit_backup.sql

Эта команда восстановит данные из резервной копии базы данных sdlplatform.

Восстановление файлов конфигурации​

Для восстановления файлов конфигурации выполните следующую команду:

tar -xzvf /path/to/backup/config_backup.tar.gz -C /path/to/configs/

Дополнительные рекомендации​

  • Периодичность резервного копирования: Определите частоту резервного копирования в зависимости от объема данных и критичности системы. Рекомендуется выполнять ежедневные резервные копии базы данных и еженедельные полные резервные копии системы.

  • PDF-отчёты: Сформированные отчёты хранятся в MinIO (отдельный бакет для PDF). При необходимости сохранения отчётов включите соответствующий бакет или том MinIO в процедуру резервного копирования (например, копирование тома minio_storage или содержимого бакета).

  • Свидетельства соответствия: Загруженные пользователями документы-свидетельства и предзагруженные шаблоны для модуля «Соответствие ГОСТ» хранятся в бакете MinIO compliance-evidence. Включите этот бакет в процедуру резервного копирования наряду с бакетом PDF-отчётов.

  • Внешние хранилища: Храните резервные копии на внешних носителях или в облаке для защиты от сбоев на сервере (например, AWS S3, Google Cloud Storage).

  • Шифрование резервных копий: Для безопасности рекомендуется шифровать резервные копии с помощью таких инструментов, как gpg:

gpg --encrypt --recipient your_email@example.com /path/to/backup.sql

Мониторинг и диагностика

Журналирование​

Настройте систему журналирования для отслеживания событий в системе и выявления проблем.

Например, используйте docker logs для журналирования событий из контейнеров:

docker compose logs -f

Для просмотра логов конкретного сервиса:

docker compose logs -f backend
docker compose logs -f ml_triage_analyzer
docker compose logs -f worker_semgrep

Системы мониторинга​

Интеграция с системами мониторинга, такими как Prometheus или Grafana, поможет отслеживать состояние системы в реальном времени, нагрузку на CPU, память и другие параметры.

Пример конфигурации для Prometheus:

scrape_configs:
- job_name: 'docker'
static_configs:
- targets: ['localhost:8080']

Диагностика ошибок​

Проверяйте журналы ошибок Nginx и других компонентов системы.

Сбор логов для диагностики​

При обращении в техническую поддержку или самостоятельной диагностике проблем соберите логи ключевых контейнеров. Имена контейнеров зависят от вашей поставки — в примерах ниже используются имена по умолчанию.

Backend (основной сервис):

docker logs --tail=2000 sdlplatform-backend-1 > backend.log 2>&1

Butler (воркер сканирования):

docker logs --tail=2000 sdlplatform-butler_service-1 > butler.log 2>&1

Генератор PDF-отчётов:

docker logs --tail=2000 sdlplatform-pdf_gen-1 > pdf_gen.log 2>&1

Все сервисы сразу:

docker compose logs --tail=2000 > sdlplatform-all.log 2>&1

Если используется кастомный docker-compose.yml, имена контейнеров могут отличаться. Актуальный список запущенных контейнеров можно получить командой docker ps --format '{{.Names}}'.

Обновления и патчи

Обновление приложения Monolit​

  • Обновление кода приложения:

Для обновления Monolit необходимо загрузить последние изменения из репозитория:

git pull origin main

Это обновит код приложения до последней версии.

  • Пересборка Docker-контейнеров с учетом новых изменений:
sudo docker compose up -d --build

Эта команда пересоберет контейнеры с учетом обновленного кода и перезапустит приложение.

Для пересборки конкретного сервиса:

sudo docker compose up -d --build backend
sudo docker compose up -d --build ml_triage_analyzer

Установка патчей безопасности​

Патчи безопасности необходимы для предотвращения уязвимостей в системе. Обычно они могут включать обновления операционной системы, баз данных и серверного ПО.

  • Обновление операционной системы:

На сервере, где запущен Docker, регулярно устанавливайте обновления безопасности операционной системы (например, на Ubuntu):

sudo apt update && sudo apt upgrade -y

Это обеспечит актуальность пакетов и установку критических патчей безопасности.

  • Автоматическое обновление безопасности:

Включите автоматическое обновление безопасности для критических пакетов:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

Проверка состояния после обновлений​

После применения любых обновлений выполните следующие шаги для проверки работоспособности системы:

  • Проверьте статус контейнеров:
docker compose ps

Убедитесь, что все контейнеры запущены и работают корректно.

  • Проверьте логи системы: Используйте следующую команду для просмотра логов контейнеров и поиска возможных ошибок:
docker compose logs -f
  • Тестирование функциональности: Пройдите по основным функциям системы, чтобы убедиться, что обновления не вызвали проблем в работе.

  • Восстановление из резервной копии:

Если откат образов или кода не помогает, выполните восстановление базы данных и файлов конфигурации из резервной копии (см. раздел Восстановление базы данных и Восстановление файлов конфигурации).

Безопасность

Настройка брандмауэра​

Рекомендации по настройке брандмауэра: Откройте только необходимые порты для работы платформы, например, порты для Docker, Nginx, и SSH. Все другие порты должны быть закрыты.

Пример команды для настройки правил брандмауэра на основе UFW (Uncomplicated Firewall):

sudo ufw allow OpenSSH
sudo ufw allow 443/tcp
sudo ufw enable

Политики паролей​

Создание и внедрение сложных политик паролей:

Установите минимальные требования к длине пароля (например, 12 символов), обязательные символы разных типов (заглавные и строчные буквы, цифры и спецсимволы).

Аудит безопасности​

Регулярный аудит безопасности:

Используйте инструменты для анализа безопасности системы, такие как Lynis или OpenSCAP, для выявления уязвимостей и несоответствий конфигурации.

Пример выполнения аудита с помощью Lynis:

sudo lynis audit system

Часто задаваемые вопросы

Техническая поддержка

В случае возникновения проблем свяжитесь с технической поддержкой: support@sdlplatform.ru

Поддержка Cybear

Не нашли ответ в документе?

Техподдержка: support@cybear.ru · +7 (495) 790-66-88, добавочный 3.

Написать в поддержку