Документация / Сканирование
Как работает Radar
Radar запускает сканеры в контейнерах Docker и отправляет их отчёты в Core. Что и когда сканировать, решает Core: он передаёт в Radar список джоб и переменные ассета. Radar исполняет джобы по очереди, доставляет отчёты и хранит логи.
Термины:
- Джоба - шаблон запуска одного контейнера: образ, команда, переменные. Подробно - Джобы и последовательности.
- Последовательность - упорядоченный список джоб. Хранится в Core.
- Пайплайн - один запуск последовательности для одного ассета. В Core ему соответствует аудит.
Компоненты
| Компонент | Образ | Что делает |
|---|---|---|
| Веб-интерфейс | sf-radar-front |
nginx на порту 8080: отдаёт интерфейс, запросы /api/v1 проксирует в API Radar, порт 8090 |
| API | sf-radar-back |
FastAPI на порту 8090, API_WORKERS процессов uvicorn (по умолчанию 4). При старте применяет миграции БД и обновляет каталог джоб |
| Воркер | sf-radar-worker |
процессы Celery: исполнитель пайплайнов, утилитарный воркер, планировщик очистки. Запускает контейнеры сканеров в демоне Docker (DOCKER_HOST, по умолчанию unix:///var/run/docker.sock). Образ собран на docker:dind и может поднять демон сам - для этого контейнеру нужен режим privileged |
| PostgreSQL | - | джобы и их настройки, пайплайны, логи завершённых джоб, статистика, токен доступа (хеш), учётные данные реестров, настройки |
| Брокер | RabbitMQ или Redis | очереди Celery |
| Redis | - | живые логи выполняющихся джоб. Нужен и при брокере RabbitMQ |
Параметры окружения компонентов - на странице Параметры конфигурации.
Процессы воркера
| Процесс | Очередь | Что делает | Сколько экземпляров |
|---|---|---|---|
| Исполнитель пайплайнов | pipeline_queue |
исполняет пайплайны | один процесс - один пайплайн. Число процессов - MAX_SCALEWORKERS_COUNT, по умолчанию 2 |
| Утилитарный воркер | utils_queue |
останавливает джобы, отдаёт артефакты, удаляет образы, чистит тома | по числу CPU контейнера (значение Celery по умолчанию) |
| Планировщик | - | раз в сутки в 00:00 UTC ставит задачу очистки | строго один |
Число одновременных пайплайнов равно числу процессов исполнителя на всех воркерах. Отдельного ограничения сверх этого нет. Состояние видно в Radar: "Настройки" → "Воркеры" и строка "Активные Воркеры:" / "Активные Потоки:" на экране "Пайплайны".
Фоновые проверки API
Если API задан ACCESS_TOKEN, он сам вызывает две служебные задачи:
- раз в 10 секунд - проверку таймаутов джоб и пайплайнов;
- раз в час - сбор статистики времени выполнения джоб.
Без ACCESS_TOKEN таймауты не работают
Если ACCESS_TOKEN не задан, джобы и пайплайны не прерываются по таймауту, а оценка длительности не обновляется. Значение должно совпадать с действующим токеном доступа Radar. Если джобы не прерываются по таймауту, сверьте ACCESS_TOKEN с токеном доступа и перезапустите API.
Путь скана
- Core формирует по пайплайну на каждый ассет: имя - название последовательности, джобы - в порядке последовательности, переменные - адрес приёма отчётов, токен, ассет, ветка, номер аудита. Ассеты уходят в Radar пачками до 100 запросом
POST /api/v1/pipelines/bulk-run/. - Radar создаёт пайплайн в статусе "В ожидании" и ставит задачу в очередь
pipeline_queue. Core получает ответ 202. - Свободный процесс исполнителя берёт пайплайн, проверяет доступ к API Radar (
GET /api/v1/auth-health-check/) и переводит пайплайн в "Выполняется". - Джобы идут строго по порядку, по одной. Для каждой воркер создаёт том джобы, скачивает образ и запускает контейнер.
- Когда джоба типа "Сканнер" завершилась, воркер читает её отчёт и отправляет в Core. Отчёт уходит сразу после своей джобы, не дожидаясь остальных.
- Лог джобы переносится из Redis в PostgreSQL.
- Если ни одна джоба не остановила пайплайн, он получает статус "Завершен".
Core разбирает отчёт асинхронно. Статус "Завершен" в Radar значит, что Core принял отчёты, а не что находки уже созданы.
Проверяйте связь с Radar
Если Radar недоступен или отклонил запрос, ошибка записывается в журнал воркера Core, а аудит остаётся без находок. Перед запуском проверяйте связь: в Core "Radar" → "Настройки", блок "Статус подключения".
Как исполняется контейнер
| Параметр | Значение |
|---|---|
| Команда | sh -c "<Команда запуска>" - в образе нужен sh |
| ENTRYPOINT | из образа; пустой, если включено "Перезаписывать Энтрипоинт Контейнера" |
| Рабочий каталог | /code |
| Тома | том джобы → /data, том пайплайна → /code |
| Пользователь | root, даже если в образе задан другой USER |
| Сеть | host - сеть демона Docker, в котором запущен сканер |
| Возможности ядра | добавлена CAP_NET_RAW, режима privileged нет |
| DNS | серверы из "Настройки" → "DNS" |
| Переменные | переменные джобы и переменные пайплайна |
| Лимиты CPU и памяти | не задаются |
| Образ | скачивается перед каждым запуском джобы; при заданных "Учетные данные" перед этим выполняется вход в реестр |
После завершения контейнер удаляется, тома остаются.
Изоляция сканеров
Контейнер сканера работает от root, в сети демона Docker и без лимитов ресурсов. Все переменные пайплайна, включая скрытые (токен Core, SSH-ключ, пароль реестра), доступны каждой джобе. Запускайте Radar на выделенном демоне Docker и выделенных узлах, ограничивайте ресурсы на уровне пода или узла и включайте в последовательности только образы, которым доверяете.
Тома и рабочие каталоги
| Каталог в контейнере | Том | Время жизни | Что там |
|---|---|---|---|
/code |
pipeline_volume-<uuid> - общий том пайплайна |
весь пайплайн и дальше до очистки | код из Code Downloader и артефакты джоб с включённым копированием |
/data |
<Имя_джобы>-<uuid> - том джобы |
до очистки; удаляется сразу, если включено копирование | отчёт сканера /data/$REPORT_FILE_NAME |
- Том пайплайна монтируется в
/codeкаждой джобе. Code Downloader клонирует репозиторий прямо в/code, поэтому код видят все следующие джобы. - Флаг джобы "Копировать артефакты в следующие джобы из дирректории {directory}" после её завершения копирует содержимое
/dataв/code. Так джоба передаёт файлы следующим. - Отчёт должен лежать в
/data. Файл в/codeв Core не уходит.
Тома удаляет ежедневная очистка: всё старше "Дней хранить артефакты до очистки" (по умолчанию 1). Настройка - на странице Настройки Radar.
Очистка затрагивает весь демон Docker
Очистка удаляет все неиспользуемые тома демона Docker старше заданного срока, а не только тома Radar. Не запускайте сканеры на демоне, где хранятся тома других приложений.
Доставка отчёта в Core
Отчёт отправляется, если джоба имеет тип "Сканнер" и завершилась без ошибки воркера. Ненулевой код выхода сканера при включённом "Разрешить падение" отправке не мешает.
- Воркер запускает служебный контейнер из
UTILITY_IMAGE(по умолчаниюalpine) с томом джобы и читает/data/$REPORT_FILE_NAMEчастями по 10 МБ. Файл целиком собирается в памяти воркера. - Если
PORTAL_IMPORT_URLилиPORTAL_TOKENне заданы, воркер пишет об этом в лог и пропускает отправку. Джоба завершается успешно. - Воркер отправляет
POST $PORTAL_IMPORT_URLв форматеmultipart/form-data: файлfileи метаданные из переменных пайплайна. Заголовок -Authorization: Token $PORTAL_TOKEN. - Таймаут запроса - 20 секунд. Сертификат Core проверяется, если воркеру не задан
HTTP_SSL_SKIP_VERIFY. - Ответ не 202 - джоба получает статус "Джоба остановлена".
| Поле запроса | Откуда | Что значит в Core |
|---|---|---|
scanner_name |
SCAN_TYPE |
имя сканера и его импортёр. Допустимы только имена из списка сканеров Core |
product_name, product_type |
PRODUCT_NAME, PRODUCT_TYPE |
продукт |
repository, docker_image, domain, host, cloud_account |
REPOSITORY, DOCKER_IMAGE, DOMAIN, HOST, CLOUD_ACCOUNT |
ассеты |
branch |
BRANCH |
ветка находок |
docker_image_tag |
DOCKER_IMAGE_TAG |
тег образа |
audit_id |
AUDIT_ID |
аудит, к которому относится отчёт |
Адрес и токен подставляет Core:
- адрес - "Внутренний URL приложения" +
api/v1/scan/import/("Глобальные настройки" → "Рабочий процесс"). Он должен открываться из сети, где работают контейнеры сканеров; - токен - API-токен пользователя, запустившего аудит. Для расписания - автора расписания, для вебхуков систем контроля версий и реестров - автора интеграции. Если токена нет, Core создаёт его. У этого пользователя должно быть право "Уязвимости" - "Изменение", иначе Core отклонит отчёт с кодом 403 и джоба будет остановлена.
Поля запроса и ответы приёма отчётов - на странице Загрузка отчётов из CI.
Статусы
| Значение API | Пайплайн | Джоба |
|---|---|---|
PENDING |
"В ожидании" | "Джоба в ожидании" |
IN_PROGRESS |
"Выполняется" | "Джоба выполняется" |
FINISHED |
"Завершен" | "Джоба завершена" |
KILLED |
"Остановлен" | "Джоба остановлена" |
TIMED_OUT |
"Тайм-аут" | "Джоба прервана по тайм-ауту" |
Джоба получает "Джоба остановлена", если:
- контейнер вернул ненулевой код и у джобы выключено "Разрешить падение";
- не задана обязательная переменная (в логе
Missing required variables: [...]); - у джобы-сканера нет файла отчёта в
/data; - Core не принял отчёт.
Остановленная или прерванная по таймауту джоба с выключенным "Разрешить падение" останавливает весь пайплайн. Следующие джобы не запускаются.
При включённом "Разрешить падение" ненулевой код выхода статус не меняет: джоба получает "Джоба завершена", а джоба-сканер всё равно отправляет отчёт. Причину смотрите в логе джобы.
Таймауты
| Таймаут | Где задаётся | Единица | 0 | Как срабатывает |
|---|---|---|---|---|
| Джобы | поле джобы "Таймаут джобы (в минутах)" | минуты | без таймаута | отсчёт от старта джобы; по истечении контейнер останавливается, статус "Джоба прервана по тайм-ауту" |
| Пайплайна | "Настройки" → "Таймаут Пайплайнов" | минуты | без таймаута (значение по умолчанию) | отсчёт от старта пайплайна |
| Проверка таймаутов | API Radar | раз в 10 секунд | - | работает только при заданном ACCESS_TOKEN |
| Отправка отчёта в Core | воркер | 20 секунд | - | ответ не получен - джоба остановлена |
Наблюдение и управление
Экран "Пайплайны":
- фильтры "Статус", "Джоба", "Аудит", "Аудит из списка" и "Поиск" - по тексту логов джоб;
- колонки "Имя", "Статус", "Прогресс", "Оценка", "Дата Запуска", "Дата Завершения", "Аудит";
- кнопки "Логи", "Скачать Артефакты", "Остановить Джобу", "Остановить Пайплайн", "Остановить все пайплайны".
"Оценка" - ожидаемая длительность: сумма средних времён джоб за последние сутки.
Логи:
- выполняющейся джобы - из Redis, завершённой - из PostgreSQL;
- в начале лога печатаются видимые переменные джобы целиком, значения скрытых заменяются на
***MASKED***; - лог живёт столько же, сколько пайплайн: "Дней хранить пайплайны до очистки", по умолчанию 1 день.
Секреты - только в скрытых переменных
Видимая переменная попадает в лог. Не передавайте токен в URL репозитория: для доступа к репозиториям используйте SSH-ключ из настроек Radar в Core.
"Скачать Артефакты" отдаёт tar-архив тома джобы. Если у джобы включено копирование артефактов - архив тома пайплайна.
"Остановить все пайплайны" переводит ожидающие пайплайны в "Остановлен", очищает очередь и останавливает выполняющиеся. Кнопка останавливает все сканы, в том числе запущенные из Core другими пользователями.
Перезапуск
Перезапуск API Radar прерывает сканы
При каждом старте sf-radar-back останавливает все пайплайны в статусах "В ожидании" и "Выполняется" и очищает очередь. Обновляйте и перезапускайте API, когда на экране "Пайплайны" нет активных сканов. Прерванные аудиты запустите заново из Core.
При старте API также:
- применяет миграции БД (
alembic upgrade head); - создаёт недостающие стандартные джобы каталога и обновляет их "Настройки Поставщика";
- записывает хеш токена из
ACCESS_TOKEN, если токена в БД ещё нет.
Порядок первичной настройки
Создайте токен доступа до того, как добавлять свои джобы: пока токена в БД нет, API при старте пересоздаёт каталог джоб из поставки. Как создать токен - Настройки Radar.
API Radar
- Аутентификация - общий токен доступа Radar в заголовке
Authorization: Bearer <токен>. Пользователей и ролей в Radar нет. - Описание API:
/api/v1/docs(Swagger),/api/v1/redoc, схема -/api/v1/openapi.json. - Проверка живости без токена:
GET /api/v1/health-check/→{"is_healthy": true}. - Core обращается к API Radar сам и проксирует его для своего интерфейса через
/api/v1/ci/proxy/<путь>.
Куда дальше
- Джобы и последовательности - поля джобы, переменные, последовательности, расписание.
- Справочник сканеров - джобы каталога и импортёры Core.
- Свой и коммерческий сканер - как подключить свой образ.
- Настройки Radar - воркеры, реестры, DNS, таймауты, очистка, токен.