SecurityFlow Кабинет лицензий , откроется в новой вкладке

Документация / Сканирование

Джобы и последовательности

Обновлено 20 октября 2026

Джоба - шаблон запуска одного контейнера в Radar: образ, команда, переменные и правила поведения. Последовательность - упорядоченный список джоб в Core. Запуск последовательности для одного ассета - пайплайн. Как пайплайн исполняется, описано на странице Как работает Radar.

Где находится:

  • джобы - в Radar, раздел "Джобы": "Создать Джобу", "Копировать", "Импорт Джоб";
  • последовательности и расписание - в Core: "Radar" → "Последовательности" и "Radar" → "Расписание".

Права в Core: для последовательностей, расписания и запуска аудитов нужна роль с правом "Radar" - "Изменение" и лицензия с доступом к Radar. Подробно - Роли и права, Лицензирование.

Поля джобы

Поле в интерфейсе Поле API Что задаёт По умолчанию
"Имя джобы" name уникальное имя. По нему последовательности Core ссылаются на джобу -
"Образ" image образ с реестром и тегом, например registry.example.ru/sf-scan-gitleaks:<версия> -
"Команда запуска" run_command команда, выполняется как sh -c -
"Переменные окружения:" environment_variables_dict переменные джобы, см. ниже -
"Тип джобы" type "Сканнер" (SCANNER) или "Техническая" (TECHNICAL) "Сканнер"
"Таймаут джобы (в минутах)" timeout предел времени джобы, 0 - без предела. Отрицательное значение не принимается 0
"Разрешить падение" allow_failure выключено - ненулевой код выхода, таймаут или ошибка джобы останавливают весь пайплайн включено
"Копировать артефакты в следующие джобы из дирректории {directory}" use_pipeline_volume после джобы копировать содержимое /data в общий том /code выключено
"Перезаписывать Энтрипоинт Контейнера" overwrite_entrypoint заменить ENTRYPOINT образа пустым, чтобы команда шла через sh -c выключено
"Учетные данные" docker_credentials_id учётные данные реестра для скачивания образа. Заводятся в "Настройки" → "Уч. Данные Docker", см. Настройки Radar не заданы
"Использовать настройки поставщика" use_vendor_settings брать "Настройки Поставщика" вместо "Пользовательские Настройки" выключено

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

У джобы два набора полей: "Пользовательские Настройки" и "Настройки Поставщика". Пайплайн берёт пользовательские, если не включено "Использовать настройки поставщика".

  • Правьте "Пользовательские Настройки".
  • "Настройки Поставщика" - справочный набор стандартной джобы каталога. API Radar перезаписывает его при каждом старте.
  • Смена образа в пользовательских настройках удаляет старый образ из демона Docker.

Каталог и перезапуск

При каждом старте API Radar сверяет каталог стандартных джоб:

  • недостающие стандартные джобы создаются заново. Удалённая стандартная джоба вернётся после перезапуска;
  • "Настройки Поставщика" стандартных джоб перезаписываются;
  • ваши джобы и "Пользовательские Настройки" не меняются.

Порядок первичной настройки

Создайте токен доступа Radar до того, как добавлять свои джобы: пока токена нет, API при старте пересоздаёт каталог джоб из поставки. См. Настройки Radar.

Список стандартных джоб - Справочник сканеров.

Типы джоб

Тип Что делает Пример
"Сканнер" выполняет команду, затем отправляет файл /data/$REPORT_FILE_NAME в Core Gitleaks Scan, Semgrep
"Техническая" только выполняет команду. Отчёт в Core не отправляется Code Downloader, Httpx

Code Downloader и пустой код

У Code Downloader в каталоге включено "Разрешить падение". Если клонирование не удалось, джоба получит статус "Джоба завершена", сканеры запустятся на пустом /code и отправят в Core пустые отчёты. Пустой отчёт неотличим от чистого кода, а при включённом автозакрытии закроет найденные ранее уязвимости. Выключите у Code Downloader "Разрешить падение": тогда ошибка клонирования остановит пайплайн.

Таймаут Code Downloader в каталоге - 1 минута. Для больших репозиториев увеличьте его.

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

Свойства переменной

Свойство Значения Что делает
Видимость "Видимая" / "Скрытая" видимая печатается в начале лога джобы целиком. Значение скрытой в логе заменяется на ***MASKED***
Обязательность "Обязательна для запуска Джобы" / "Не обязательна для запуска Джобы" пустая обязательная переменная останавливает джобу с сообщением Missing required variables: [...]

Правила:

  • Подстановка. Значение вида $ИМЯ заменяется значением переменной ИМЯ той же джобы или пайплайна. Сначала ищется среди видимых, затем среди скрытых. Если подставлено значение скрытой переменной, результат тоже становится скрытым. Не нашлось - подставляется пустая строка. Подстановка одноуровневая. Пример из каталога: переменная TRIVY_PASSWORD со значением $DOCKER_REGISTRY_PASSWORD.
  • Приоритет. Переменная пайплайна перекрывает одноимённую переменную джобы. Core передаёт переменные пайплайна при каждом запуске, см. таблицу ниже.
  • Контейнер получает все переменные: джобы и пайплайна, видимые и скрытые.

Секреты

Пароли, токены и ключи храните только в скрытых переменных. Видимая переменная попадает в лог джобы.

Служебные переменные джобы-сканера

Джобе типа "Сканнер" нужны две переменные:

Переменная Что задаёт Пример
REPORT_FILE_NAME имя файла отчёта в /data, без подкаталогов. Воркер читает ровно /data/$REPORT_FILE_NAME gitleaks.json
SCAN_TYPE имя сканера в Core. По нему Core выбирает импортёр. Должно точно совпадать с именем из "Глобальные настройки" → "Сканеры", иначе Core отклонит отчёт и джоба будет остановлена Gitleaks Scan

Список имён - Справочник сканеров.

Переменные, которые передаёт Core

Core добавляет их к каждому пайплайну. Джоба может ссылаться на них в команде ($REPOSITORY) или через подстановку.

Переменная Скрытая Когда передаётся Что содержит
PORTAL_IMPORT_URL нет всегда адрес приёма отчётов: "Внутренний URL приложения" + api/v1/scan/import/
PORTAL_TOKEN да всегда API-токен пользователя, от имени которого запущен аудит
AUDIT_ID нет всегда номер аудита в Core
PRODUCT_NAME, PRODUCT_TYPE нет всегда продукт ассета и его тип
REPOSITORY нет ассет типа "Репозиторий" SSH URL репозитория
DOCKER_IMAGE нет ассет типа "Docker-образ" образ без тега
DOMAIN нет ассет типа "Домен" домен
HOST нет ассет типа "Хост" хост
CLOUD_ACCOUNT, CLOUD_KEY_ID нет ассет типа "Облачный аккаунт" аккаунт и ID ключа
CLOUD_KEY_SECRET да ассет типа "Облачный аккаунт" секрет ключа облака
BRANCH нет если при запуске указана ветка ветка. Security checker передаёт <ветка>:<sha>
DOCKER_IMAGE_TAG нет если при запуске указан тег тег образа
DOCKER_REGISTRY_USER, DOCKER_REGISTRY_ADDRESS нет если заданы в Core: "Radar" → "Настройки" пользователь и адрес реестра для сканирования образов
DOCKER_REGISTRY_PASSWORD да если задан там же пароль реестра
PRIVATE_SSH_KEY да если задан там же SSH-ключ для клонирования репозиториев

Переменные, которые воркер отправляет в Core

После джобы-сканера воркер берёт метаданные отчёта из переменных джобы и пайплайна: SCAN_TYPE, PRODUCT_NAME, PRODUCT_TYPE, REPOSITORY, DOCKER_IMAGE, DOMAIN, HOST, CLOUD_ACCOUNT, BRANCH, DOCKER_IMAGE_TAG, AUDIT_ID. Адрес и токен - из PORTAL_IMPORT_URL и PORTAL_TOKEN. Соответствие полям Core - Доставка отчёта в Core.

Каталоги /data и /code

Каталог Для чего Правило
/code рабочий каталог джобы, общий том пайплайна здесь код из Code Downloader и файлы, которые передают друг другу джобы
/data личный том джобы сюда сканер кладёт отчёт. Только файл из /data уходит в Core

Пример команды сканера: gitleaks detect -s ./$SEC_CODE_FOLDER -r /data/$REPORT_FILE_NAME.

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

  • записать их прямо в /code - так делает Subfinder с domains.txt и urls.txt;
  • записать в /data и включить "Копировать артефакты в следующие джобы из дирректории {directory}". После джобы содержимое /data скопируется в /code, а том джобы удалится.

Последовательности

Последовательность хранит только имена джоб Radar и их порядок. Настройки самих джоб живут в Radar.

Где: Core, "Radar" → "Последовательности", окно "Добавить последовательность сканирования".

Поле Что задаёт
"Название" имя последовательности. Им же называется пайплайн в Radar
"Установить как последовательность по умолчанию" последовательность предлагается в форме запуска аудита и используется для ассетов без своей. По умолчанию может быть только одна: новая снимает флаг со старой
"Джоб Radar" имя джобы в Radar, точно как в поле "Имя джобы"

Порядок джоб меняют пункты "Переместить вверх" и "Переместить вниз" в меню джобы. Джобы выполняются сверху вниз.

Переключатель общих артефактов у джобы в последовательности меняет флаг "Копировать артефакты..." в самой джобе Radar. Он действует во всех последовательностях, где есть эта джоба.

Последовательность по умолчанию после установки: Code Downloader, Trufflehog3 Scan, Gitleaks Scan, Semgrep, Trivy Code Dependencies.

Выбор последовательности при запуске

  1. Последовательность, указанная при запуске.
  2. Последовательность, привязанная к ассету.
  3. Последовательность по умолчанию.

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

Типовые последовательности

Тип ассета Порядок джоб
Репозиторий Code Downloader → сканеры кода: Gitleaks Scan, Trufflehog3 Scan, Semgrep, Bandit, Gosec, ESlint, Checkov, Terrascan, Trivy Code Dependencies, Retirejs
Docker-образ Trivy Image Dependencies
Домен Subfinder → Naabu → Httpx → Nuclei Scan

Code Downloader всегда первый: без него у сканеров кода пустой /code. Джобы внешнего периметра читают файлы предыдущих, поэтому их порядок фиксирован, см. Справочник сканеров.

Один импортёр в двух джобах

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

Удаление последовательности

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

Переименование джобы

Последовательность ссылается на джобу по имени. После переименования джобы в Radar поправьте последовательности: иначе Radar отклонит запуск, а Core покажет "Radar не содержит джобы с именем {name}".

Расписание

Своего планировщика сканов в Radar нет. Регулярные сканы запускает Core.

Где: Core, "Radar" → "Расписание", окно "Создать запланированное задание".

Поле Что задаёт
"Название" имя задания
"Активно" включено ли задание
"Последовательность джоб" какую последовательность запускать
"Расписание в формате Crontab" когда запускать. Конструктор "Настроить расписание" (поля "Повтор" и "Время") или ручной ввод - "Установить вручную"
"Тип области видимости" "Продукты" или "Ассеты"
"Глобально" все текущие и будущие продукты или ассеты выбранных типов. Включить может только роль с доступом ко всем продуктам
выбор продуктов или ассетов, "Применить к {target} с тегами", "Типы ассетов" что сканировать

Порядок полей Crontab

Порядок полей не как в стандартном cron

Core хранит и показывает выражение в порядке минута час день_недели день_месяца месяц. В стандартном cron третье поле - день месяца, четвёртое - месяц.

Когда Выражение в Core Стандартный cron
каждый день в 02:30 30 2 * * * 30 2 * * *
по понедельникам в 03:00 0 3 1 * * 0 3 * * 1
1-го числа каждого месяца в 04:00 0 4 * 1 * 0 4 1 * *
по будням в 21:00 0 21 1-5 * * 0 21 * * 1-5
  • Поля разделяйте ровно одним пробелом.
  • Время - UTC.

Как выполняется задание

  • Аудит запускается от имени автора задания. Его токен уходит в Radar как PORTAL_TOKEN, поэтому автору нужно право "Уязвимости" - "Изменение".
  • Без области сканирования задание ничего не запускает.
  • При удалении пользователя удаляются и его задания.
  • API: /api/v1/ci/schedules/, поле crontab_expr.

Способы запуска

Способ Где Что передаётся в Radar
Кнопка "Запустить аудит" Core: продукт или ассет. Поля "Ветка (необязательно)", "Тег докер образа (необязательно)", последовательность один пайплайн на ассет
API Core POST /api/v1/ci/pipelines/run/, POST /api/v1/products/bulk/run-audit/, POST /api/v1/product-assets/bulk/run-audit/ то же, см. API Core
Расписание Core: "Radar" → "Расписание" ассеты из области задания
Push в репозиторий вебхук интеграции системы контроля версий, флаг "Включить сканирование при пуше коммита" ветка. Хеш коммита Core сохраняет в аудите, а Code Downloader клонирует ветку на момент запуска, см. Системы контроля версий
Новый тег образа интеграция реестра контейнеров GitLab DOCKER_IMAGE_TAG
Security checker джоба CI <ветка>:<sha>, см. Security checker
Напрямую в Radar "Пайплайны" → "Запустить новый пайплайн"; API POST /api/v1/pipelines/run/ джобы и переменные, которые вы указали

Запуск напрямую в Radar

Окно "Запуск Пайплайна": выберите "Джобы", задайте "Переменные окружения", нажмите "Запустить пайплайн".

Чтобы отчёт дошёл до Core, передайте переменные, которые обычно подставляет Core. Пример через API, токен - общий токен доступа Radar:

curl -X POST "https://radar.example.ru/api/v1/pipelines/run/" \
  -H "Authorization: Bearer <токен Radar>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "manual-gitleaks",
    "jobs": [{"name": "Code Downloader"}, {"name": "Gitleaks Scan"}],
    "pipeline_variables": [
      {"name": "REPOSITORY", "value": "git@gitlab.example.ru:team/payments.git", "masked": false},
      {"name": "BRANCH", "value": "main", "masked": false},
      {"name": "PRIVATE_SSH_KEY", "value": "<SSH-ключ>", "masked": true},
      {"name": "PORTAL_IMPORT_URL", "value": "https://core.example.ru/api/v1/scan/import/", "masked": false},
      {"name": "PORTAL_TOKEN", "value": "<токен Core>", "masked": true},
      {"name": "PRODUCT_NAME", "value": "payments", "masked": false},
      {"name": "PRODUCT_TYPE", "value": "Common", "masked": false}
    ]
  }'

Ответ 202:

{"message": "Pipeline has been triggered to start!", "ids": [42]}
  • Джобы выполняются в порядке списка jobs.
  • POST /api/v1/pipelines/bulk-run/ принимает список таких объектов.
  • Имя джобы, которой нет в Radar, - ответ 400 Jobs with these names do not exist.
  • Без AUDIT_ID Core создаёт отдельный аудит на каждый принятый отчёт с ассетом.

Импорт и экспорт джоб

Импорт

Где: Radar, "Импорт Джоб". Выберите файл .json и нажмите "Отправить {count} джоб". API: POST /api/v1/jobs/import/.

Формат - JSON-массив джоб:

[
  {
    "name": "My Scanner",
    "docker_credentials_id": null,
    "user_settings": {
      "image": "registry.example.ru/my-scanner:1.0",
      "run_command": "my-scanner --output /data/$REPORT_FILE_NAME ./$SEC_CODE_FOLDER",
      "environment_variables_dict": "[{\"name\":\"REPORT_FILE_NAME\",\"value\":\"my-scanner.json\",\"masked\":false,\"required\":false},{\"name\":\"SCAN_TYPE\",\"value\":\"My Scanner\",\"masked\":false,\"required\":false},{\"name\":\"SEC_CODE_FOLDER\",\"value\":\"\",\"masked\":false,\"required\":false},{\"name\":\"REPOSITORY\",\"value\":\"\",\"masked\":false,\"required\":true}]",
      "use_pipeline_volume": false,
      "type": "SCANNER",
      "allow_failure": true,
      "timeout": 10,
      "overwrite_entrypoint": false
    }
  }
]
  • environment_variables_dict - строка с JSON, а не массив.
  • docker_credentials_id - id учётных данных реестра в этом Radar или null.
  • Имена должны быть уникальными. Если хотя бы одно имя уже занято, ответ 400 с номерами конфликтующих элементов, и ни одна джоба не создаётся. Успех - 201.

Экспорт

Выгружайте джобы через API:

curl -s "https://radar.example.ru/api/v1/jobs/?name=My%20Scanner" \
  -H "Authorization: Bearer <токен Radar>" > jobs.json

Без параметра name возвращаются все джобы. Ответ - массив в том же формате плюс служебные поля (id, use_vendor_settings, vendor_settings), которые импорт пропускает. Перед импортом на другую установку замените docker_credentials_id на null или на id учётных данных целевого Radar.

Чтобы сделать вариант существующей джобы, нажмите "Копировать" в её карточке и поменяйте копию.