Безопасность сценариев: Groovy sandbox и Vault

Рейтинг: 68.5% · 14 голосов
Подробный курс по Jenkins и CI/CD: установка и настройка, плагины и Configuration as Code, конвейеры (pipeline) и Jenkinsfile, declarative и scripted, агенты, Docker и Kubernetes, общие библиотеки на Groovy, безопасность и credentials, интеграции (SonarQube, артефакты), траблшутинг. Актуально на 2026.
Ответить
Аватара пользователя
Andrey_CICD
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Безопасность сценариев: Groovy sandbox и Vault

Сообщение Andrey_CICD »

Оглавление курса (47)
  1. Что такое Jenkins и зачем нужен CI/CD
  2. Jenkins в 2026: версии, экосистема и сравнение с GitLab CI и GitHub Actions
  3. Архитектура Jenkins: контроллер, агенты, узлы и исполнители
  4. Установка Jenkins: пакеты, Docker и Kubernetes
  5. Первичная настройка Jenkins: мастер, плагины, пользователи
  6. Плагины Jenkins: установка, обновление и ключевой набор
  7. Configuration as Code (JCasC): настройка Jenkins декларативно
  8. Конвейеры Jenkins и Jenkinsfile: pipeline as code
  9. Scripted против Declarative: два синтаксиса конвейера
  10. Структура конвейера: node, stage, steps и первый pipeline
  11. Генератор сниппетов, запуск конвейера и Replay
  12. Типы заданий Jenkins: Freestyle, Pipeline, Multibranch и Organization
  13. Декларативный конвейер: структура pipeline, agent, stages
  14. agent, environment и переменные в конвейере
  15. tools, options, parameters и triggers в декларативном конвейере
  16. stages, parallel и matrix: организация этапов
  17. Условное выполнение when и блок post
  18. Триггеры сборки: webhook от GitHub, SCM polling и расписание
  19. Параметры сборки и пользовательский ввод
  20. Управление потоком: timeout, retry, sleep и waitUntil
  21. Параллелизм и блокировки: parallel, lock, milestone
  22. Постобработка и уведомления о результате сборки
  23. Groovy для Jenkins: основы скриптового конвейера
  24. Скриптовый конвейер: логика, циклы и функции
  25. Общие библиотеки Jenkins: Shared Libraries
  26. Подключение и загрузка общих библиотек
  27. Шаги оболочки: sh, bat, powershell и коды возврата
  28. Переменные среды, withEnv и рабочие пространства
  29. Работа с файлами, артефактами и отпечатками
  30. Сборка проектов в конвейере: Maven, Gradle, npm
  31. Качество кода: SonarQube и покрытие тестами
  32. Управление артефактами: публикация в Nexus и Artifactory
  33. Docker в Jenkins: образы как агенты сборки
  34. Сборка и публикация Docker-образов из конвейера
  35. Jenkins в Kubernetes: динамические pod-агенты
  36. Развёртывание в Kubernetes из конвейера
  37. Безопасность Jenkins: аутентификация и матрица прав
  38. Учётные данные Jenkins: credentials в конвейере
  39. Безопасность сценариев: Groovy sandbox и Vault (вы здесь)
  40. Уведомления и отчёты: email, Slack, Telegram, HTML
  41. Blue Ocean и интерфейс Jenkins в 2026
  42. Автоматизация Jenkins: CLI, REST API и script console
  43. Поиск и устранение неисправностей: читаем логи конвейера
  44. Типичные ошибки конвейера: сериализация и неутверждённый код
  45. Эксплуатация Jenkins: бэкап, обновление, масштабирование
  46. Конвертация и миграция: от Freestyle к Jenkinsfile
  47. Итог: сквозной CI/CD конвейер и Jenkins против альтернатив в 2026
Представь: ты пишешь невинный pipeline, прогоняешь его, а Jenkins падает с ошибкой "Scripts not permitted to use method ...". Первый порыв - загуглить, найти галочку "Use Groovy Sandbox", снять её и забыть. Не делай так. Эта галочка - не баг, а единственное, что стоит между чужим pull request с Jenkinsfile и полным захватом твоего контроллера. В этом уроке разберём, как устроена безопасность сценариев в Jenkins: почему Groovy-код в конвейере живёт в клетке, как работает утверждение методов, чем доверенные библиотеки отличаются от недоверенных, и почему секреты вообще не должны лежать в Jenkins - их место в Vault.

Почему Jenkins groovy sandbox держит твой код в клетке

Pipeline в Jenkins - это не конфиг, а живой Groovy-скрипт, который исполняется прямо на контроллере. А контроллер - это JVM с полным доступом к файловой системе, к credentials всех проектов, к API самого Jenkins. Если бы любой Jenkinsfile мог звать произвольные Java-методы, то строчка вроде

Код: Выделить всё

Jenkins.instance.securityRealm = null
в чьём-то конвейере отключила бы вообще всю аутентификацию. Поэтому появился jenkins groovy sandbox - песочница из плагина Script Security.

Механика простая и жёсткая. Когда конвейер исполняется в песочнице (по умолчанию для всех declarative pipeline и для scripted из SCM), движок перехватывает КАЖДЫЙ вызов метода и обращение к полю и сверяет его с белым списком разрешённых сигнатур. Безопасное подмножество - работа со строками, списками, числами, стандартные pipeline-шаги - проходит молча. А вот попытка дёрнуть

Код: Выделить всё

new File('/etc/passwd').text
или залезть в

Код: Выделить всё

Jenkins.instance
упрётся в исключение RejectedAccessException. Песочница не доверяет коду в принципе - она доверяет только конкретным сигнатурам из списка.

Изображение

Jenkins script approval: как утверждать методы и не выстрелить себе в ногу

Когда твой код упёрся в незнакомую сигнатуру, она не пропадает - она попадает в очередь. Открой Manage Jenkins -> In-process Script Approval, и увидишь список ожидающих утверждения вызовов. Администратор может нажать "Approve" - и сигнатура добавится в глобальный белый список, после чего ЛЮБОЙ конвейер сможет её использовать. Вот тут и кроется главная опасность jenkins script approval: ты утверждаешь не "этому проекту такой вызов", а "всем и навсегда".

Поэтому к каждой записи относись как к запросу на повышение привилегий. Утверждение

Код: Выделить всё

staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods execute java.lang.String
(то есть возможность из строки запустить shell-команду) фактически отдаёт исполнение произвольного кода любому, кто умеет править Jenkinsfile. Хорошее правило: если для шага есть штатный pipeline-step (sh, readFile, httpRequest), используй его, а не сырой Java-вызов. Сырые сигнатуры одобряй только когда понимаешь, что именно делает метод и кто имеет доступ к конвейеру.

Отдельная ловушка - @NonCPS. Этот аннотированный метод исполняется не пошаговым CPS-движком, а как обычный Groovy. Он нужен, когда внутри логика, которую CPS не умеет сериализовать (итерация по сложным структурам, регулярки, работа со списками). Но запомни: @NonCPS не выключает песочницу. Сигнатуры внутри такого метода всё равно проверяются. Зато @NonCPS приносит свои грабли - внутри нельзя вызывать pipeline-шаги вроде sh или echo, потому что они требуют CPS. Метод просто молча отработает не так, как ты ждёшь.

Код: Выделить всё

// scripted-фрагмент: @NonCPS для несериализуемой логики
@NonCPS
def parseVersions(String json) {
    // тут можно тяжёлый Groovy, но НЕЛЬЗЯ sh/echo
    def data = new groovy.json.JsonSlurper().parseText(json)
    return data.versions.findAll { it.startsWith('2.') }.join(', ')
}
Доверенные и недоверенные библиотеки: где проходит граница доверия

Дублировать Groovy по всем Jenkinsfile - боль, поэтому общий код выносят в Shared Library. И вот ключевой для jenkins безопасность сценариев момент: библиотеки бывают двух сортов, и это определяет, исполняются они в песочнице или нет.
  • Глобальные (Global) Shared Libraries - настраиваются на уровне Manage Jenkins администратором. Они считаются ДОВЕРЕННЫМИ и выполняются ВНЕ песочницы, с полным доступом к Jenkins API. Логика проста: их правит только админ, через защищённый репозиторий, значит, им можно доверять как самому Jenkins.
  • Папочные (Folder-level) Shared Libraries - привязаны к папке проекта и могут редактироваться обычными пользователями. Они НЕДОВЕРЕННЫЕ и крутятся внутри песочницы с теми же ограничениями, что и пользовательский Jenkinsfile.
Вывод для практики: не суй в глобальную библиотеку код, авторство которого не контролируешь. Любой коммит в её репозиторий - это код, исполняемый с правами контроллера в обход всех проверок. Доступ на запись к репозиторию глобальной библиотеки = root на Jenkins. Защищай его protected branch и обязательным ревью так же серьёзно, как продакшен.

Код: Выделить всё

// Jenkinsfile: подключение доверенной глобальной библиотеки
@Library('platform-ci@v3') _

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                // шаг из глобальной библиотеки, исполняется вне песочницы
                buildDockerImage(name: 'web', tag: env.GIT_COMMIT)
            }
        }
    }
}
Jenkins секреты в Vault: почему хранилище должно быть снаружи

Теперь про секреты. У Jenkins есть свой credentials store, и для пары токенов его хватает. Но как единственное хранилище паролей он плох: секреты лежат статично, шифрованы ключом, который валяется рядом на том же диске; ротация - ручная; кто имел права в момент кражи бэкапа, тот и получил всё разом. Современный подход на 2026 год - секреты снаружи, Jenkins только тянет их в момент сборки и тут же забывает. Реализуется это связкой jenkins vault через плагин HashiCorp Vault.

Идея в том, что Vault - центральный сейф, а Jenkins аутентифицируется в нём (по AppRole или Kubernetes-токену агента) и забирает значения на лету. Плагин даёт build wrapper и pipeline-шаг withVault: он читает путь в Vault, подставляет значения в переменные окружения на время блока и маскирует их в логе сборки, чтобы случайный echo не слил пароль в консоль.

Код: Выделить всё

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                withVault(configuration: [
                    vaultUrl: 'https://vault.cyberlake.internal:8200',
                    vaultCredentialId: 'vault-approle'
                ], vaultSecrets: [[
                    path: 'secret/data/ci/registry',
                    secretValues: [
                        [envVar: 'REG_USER', vaultKey: 'username'],
                        [envVar: 'REG_PASS', vaultKey: 'password']
                    ]
                ]]) {
                    sh 'echo "$REG_PASS" | docker login -u "$REG_USER" --password-stdin registry.cyberlake.ru'
                }
            }
        }
    }
}
Самое вкусное - динамические секреты. Вместо вечного пароля от базы Vault по запросу генерирует временную пару логин/пароль со сроком жизни, скажем, 30 минут, и сам отзывает её после. Утёкший из лога такой секрет уже протух. Конфигурацию подключения к Vault удобно задавать декларативно через JCasC, чтобы не кликать руками:

Код: Выделить всё

unclassified:
  hashicorpVault:
    configuration:
      vaultUrl: "https://vault.cyberlake.internal:8200"
      vaultCredentialId: "vault-approle"
      engineVersion: 2
И не забывай про гигиену самого Jenkins: держи актуальный LTS (на середину 2026 это линейка 2.555.x, которой нужна уже Java 21 или 25 - Java 17 отвалилась), настрой Content Security Policy, чтобы артефакты сборки не могли исполнять произвольный JS в твоём интерфейсе, и не плоди лишних админов.

Типичные грабли
  • Сняли галочку песочницы "чтобы заработало". Это эквивалент chmod 777 на проде: любой Jenkinsfile получает полный доступ к контроллеру.
  • Утвердили опасную сигнатуру (execute, getClass, ClassLoader) не глядя. Откати лишнее в In-process Script Approval - там же есть кнопка удаления одобренных записей.
  • Положили код в глобальную библиотеку, думая что он в песочнице. Он НЕ в песочнице - он доверенный и всемогущий.
  • Захардкодили пароль в Jenkinsfile или в переменную окружения job. Он попадёт в git и в логи. Только Vault или хотя бы credentials с маскировкой.
  • Забыли, что внутри @NonCPS не работают sh/echo - метод "молча" ведёт себя не так.
  • Сравнение с соседями: в GitLab CI и GitHub Actions нет исполняемого Groovy на сервере, поверхность атаки уже, но проблема секретов та же - там тоже выносят их во внешний Vault через OIDC. Концепция "секреты снаружи" универсальна.
Мини-лаба
  • Напиши scripted-шаг с заведомо запрещённым вызовом (например, new File(...)), запусти и поймай ошибку. Зайди в In-process Script Approval, посмотри запись - и НЕ утверждай её.
  • Создай папочную и глобальную Shared Library с одинаковым кодом, который пробует Jenkins.instance. Убедись, что папочная падает в песочнице, а глобальная проходит.
  • Подними dev-инстанс Vault в режиме -dev, заведи AppRole, добавь credential в Jenkins и прочитай секрет через withVault. Проверь, что в логе значение замаскировано звёздочками.
Контрольные вопросы
  • Почему отключать Groovy sandbox опасно и что именно проверяет песочница при исполнении конвейера?
  • В чём разница между глобальной и папочной Shared Library с точки зрения доверия и песочницы?
  • Что делает шаг withVault и почему хранить секреты во внешнем Vault безопаснее, чем в Jenkins credentials?
  • Почему @NonCPS не является способом обойти проверку безопасности и какие у него ограничения?
Итог

Безопасность сценариев Jenkins держится на двух китах. Первый - изоляция кода: песочница и script approval не дают чужому Jenkinsfile дотянуться до контроллера, а граница доверия проходит ровно по тому, кто может править библиотеку. Второй - изоляция секретов: их место снаружи, в Vault, а Jenkins лишь тянет нужное на время сборки и сразу забывает. Не снимай галочку песочницы, не одобряй сигнатуры вслепую и не держи пароли внутри Jenkins - и твой CI перестанет быть самым лакомым куском инфраструктуры для атакующего.
👍4 ❤️1 🔥1 😄 🤔2
Аватара пользователя
sharke
Сообщения: 1
Зарегистрирован: 11 май 2026, 07:13

Re: Безопасность сценариев: Groovy sandbox и Vault

Сообщение sharke »

Снимал я эту галочку песочницы когда то, потом неделю не мог понять как у нас в Jenkinsfile из чужого PR появился левый шаг с curl на непонятный хост. Спасибо что разжевали про trusted библиотеки, до меня только сейчас дошло почему глобальная всемогущая.
👍2 ❤️1 🔥 😄 🤔1
Аватара пользователя
mmueller
Сообщения: 1
Зарегистрирован: 09 июн 2026, 11:27

Re: Безопасность сценариев: Groovy sandbox и Vault

Сообщение mmueller »

А подскажите, если Vault в том же кластере Kubernetes что и агенты, лучше через AppRole авторизоваться или сразу через kubernetes auth по service account токену пода? withVault оба умеет?
👍2 ❤️ 🔥1 😄 🤔
Ответить
← Предыдущая глава
Учётные данные Jenkins: credentials в конвейере
Следующая глава →
Уведомления и отчёты: email, Slack, Telegram, HTML

Все главы курса «Jenkins: конвейеры CI/CD от основ до продакшена»

Поделиться темой: ✈ Telegram VK
Похожие запросы: groovy в jenkins scripted pipeline как написатьjenkins credentials как хранить секреты в пайплайне

Вернуться в «Jenkins: конвейеры CI/CD от основ до продакшена»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость