Учётные данные Jenkins: credentials в конвейере

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

Учётные данные Jenkins: credentials в конвейере

Сообщение 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
Рано или поздно конвейеру нужно куда-то залогиниться: запушить образ в реестр, выкатить артефакт в Nexus, подключиться по SSH к проду, дёрнуть API облака. И тут начинается самое опасное место в любом CI. Если ты впишешь пароль прямо в Jenkinsfile, он уедет в git, его увидит каждый, у кого есть доступ к репозиторию, и он навсегда останется в истории коммитов. Если выведешь токен через echo - он осядет в логе сборки, а логи в Jenkins по умолчанию читают многие. Утёкший секрет - это не гипотетический риск, это самая частая причина, по которой ломают пайплайны.

В этом уроке разберём, как Jenkins хранит учётные данные и как правильно подсунуть их в конвейер так, чтобы пароль не утёк в лог. Тема jenkins credentials - одна из тех, где мелкая ошибка стоит дорого, поэтому пройдём её основательно.

Хранилище jenkins credentials: типы и области

Jenkins держит секреты в собственном зашифрованном хранилище (плагин Credentials Plugin, он в дефолтной поставке). На диске они лежат в credentials.xml, зашифрованные мастер-ключом из $JENKINS_HOME/secrets. В UI это раздел Manage Jenkins -> Credentials. Ключевая идея: в Jenkinsfile ты никогда не пишешь сам пароль - только его идентификатор (credentialsId). Сам секрет живёт в хранилище.

Типов учётных данных несколько, и под каждую задачу свой:
  • Username with password - классическая пара логин/пароль. Реестры, Nexus, базы, basic-auth API.
  • Secret text - один токен или ключ. GitHub PAT, токен облака, webhook-секрет.
  • SSH Username with private key - приватный ключ плюс юзернейм. Деплой по SSH, git-доступ по ключу.
  • Secret file - целый файл-секрет. kubeconfig, service-account JSON, сертификат как файл.
  • Certificate - клиентский сертификат PKCS#12 для mTLS.
Второй важный параметр - область видимости (scope). Это то, кто вообще может использовать данный секрет:
  • System - доступен только самому Jenkins и его системным задачам (например, конфигурация облачного агента). Конвейеры эти креды не видят. Самая узкая область.
  • Global - доступен любому пайплайну на этом контроллере. Удобно, но опасно: токен прода увидит и левая тестовая джоба.
  • Folder - доступен только джобам внутри конкретной папки (нужен Folders Plugin). Это рабочая лошадка для разграничения: команда A не дотянется до секретов команды B.
Практический вывод: не сваливай всё в Global. Если у тебя несколько команд или окружений, заводи папку под проект и кладёшь jenkins секреты в folder-scope. Тогда деплой-ключ от прода физически недоступен из песочницы соседней команды, даже если кто-то угадает credentialsId.

Изображение

jenkins withcredentials: привязка секрета внутри шага

Базовый и самый универсальный способ подтянуть jenkins учетные данные в конвейер - шаг withCredentials. Он берёт секрет из хранилища, кладёт его в переменные окружения только на время выполнения блока и - что критично - маскирует значение в логах. Если секрет случайно попадёт в вывод, Jenkins заменит его на звёздочки.

Вот рабочий declarative-конвейер, который логинится в Docker-реестр и выкатывает образ:

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

pipeline {
    agent any

    stages {
        stage('Push image') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'registry-creds',
                    usernameVariable: 'REG_USER',
                    passwordVariable: 'REG_PASS'
                )]) {
                    sh '''
                        echo "$REG_PASS" | docker login registry.example.com -u "$REG_USER" --password-stdin
                        docker push registry.example.com/app:$BUILD_NUMBER
                    '''
                }
            }
        }
    }
}
Обрати внимание на детали. Переменные в одинарных кавычках ('''...''') - это shell-переменные, их подставляет sh внутри агента, а не Groovy на контроллере. Это правильно: если бы мы написали двойные кавычки и "$REG_PASS", Groovy подставил бы пароль в текст команды ещё до запуска, и он мог бы засветиться в трассировке. Пароль уходит в docker login через --password-stdin, а не как аргумент - аргументы видны в ps и в логах процессов.

Для SSH-деплоя тип другой, и withCredentials отдаёт путь к временному файлу с ключом:

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

stage('Deploy') {
    steps {
        withCredentials([sshUserPrivateKey(
            credentialsId: 'prod-deploy-key',
            keyFileVariable: 'SSH_KEY',
            usernameVariable: 'SSH_USER'
        )]) {
            sh '''
                scp -i "$SSH_KEY" -o StrictHostKeyChecking=accept-new \
                    build/app.jar "$SSH_USER@prod.example.com:/opt/app/"
            '''
        }
    }
}
Для одиночного токена берём string, для файла - file:

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

withCredentials([string(credentialsId: 'cloud-token', variable: 'CLOUD_TOKEN')]) {
    sh 'curl -H "Authorization: Bearer $CLOUD_TOKEN" https://api.example.com/deploy'
}

withCredentials([file(credentialsId: 'kubeconfig-prod', variable: 'KUBECONFIG')]) {
    sh 'kubectl --kubeconfig "$KUBECONFIG" rollout status deploy/app'
}
Несколько секретов в одном блоке тоже можно - просто перечисли их в списке через запятую.

credentials() в environment: jenkins пароль на весь stage

Второй способ - хелпер credentials() прямо в блоке environment. Он короче, когда секрет нужен на весь stage или весь pipeline, а не на один шаг. Поведение зависит от типа:
  • Для secret text переменная получает само значение токена.
  • Для secret file переменная получает путь к временному файлу.
  • Для username/password переменная получает строку username:password, и дополнительно автоматически создаются две переменные с суффиксами _USR и _PSW.

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

pipeline {
    agent any
    environment {
        NEXUS = credentials('nexus-creds')
    }
    stages {
        stage('Publish') {
            steps {
                sh 'mvn deploy -Dnexus.user="$NEXUS_USR" -Dnexus.pass="$NEXUS_PSW"'
            }
        }
    }
}
Здесь NEXUS_USR и NEXUS_PSW появились сами. Все три переменные маскируются в логах. Выбор между двумя подходами простой: environment удобен для секрета на весь stage, withCredentials - когда нужен точечный, узкий доступ ровно в одном шаге (а это всегда безопаснее - чем короче живёт секрет в окружении, тем меньше шансов утечки).

Грабли: как jenkins пароль утекает в лог

Маскирование - не магия. Jenkins маскирует только точное совпадение значения секрета в выводе. Любое преобразование ломает защиту:
  • echo секрета напрямую. sh 'echo $TOKEN' выведет токен. Маскирование сработает по точному значению, но не делай так в принципе - это плохая привычка, а при отладке легко забыть убрать.
  • Преобразование значения. base64, urlencode, разбивка на части - результат уже не совпадёт с оригиналом, и Jenkins его не замаскирует. Закодировал токен в base64 и вывел - утёк.
  • set -x в shell. При sh 'set -x; ...' shell печатает каждую команду с подставленными значениями. Маскирование может не угнаться. Не включай трассировку в блоках с секретами.
  • Секрет в имени файла или URL с параметром. curl "https://api?token=$TOKEN" - токен уедет в access-логи целевого сервера, и это уже вне контроля Jenkins.
  • Groovy-интерполяция двойными кавычками. sh "deploy --pass=${PASS}" подставляет пароль в команду на контроллере. Используй одинарные кавычки и передавай через переменную окружения - это прямо предупреждение самого Jenkins в логах.
Золотое правило: секрет должен только попадать в переменную окружения и уходить в инструмент через stdin или env, и никогда не печататься и не преобразовываться.

Ещё про ротацию. Любой секрет имеет срок жизни. Заведи привычку обновлять токены и ключи по расписанию - например раз в квартал. В Jenkins это делается через Update в карточке credentials: меняешь значение, credentialsId остаётся прежним, и ни один Jenkinsfile править не нужно. Это и есть главный плюс того, что в коде живёт только ID. При компрометации - немедленно меняешь значение и отзываешь старый токен на стороне сервиса.

Отдельно: само хранилище credentials.xml неплохо для команды, но для серьёзного прода секреты лучше держать во внешнем хранилище (HashiCorp Vault, облачные Secret Manager), а Jenkins ходит туда за ними на лету. Это тема следующего урока - там разберём интеграцию и почему она снимает проблему ротации почти полностью.

Мини-лаба

Руками, на тестовом Jenkins:
  • Заведи Username with password в Global scope с id registry-creds.
  • Напиши конвейер с withCredentials и usernamePassword, выполни sh с echo "***" (не самим паролем) - убедись, что сборка зелёная.
  • Теперь намеренно сделай sh 'echo $REG_PASS' и посмотри в лог: значение замаскировано звёздочками.
  • Сломай маскирование: sh 'echo $REG_PASS | base64' - увидишь, что закодированный пароль утёк в открытую. Зафиксируй для себя этот эффект.
  • Создай Folder, перенеси креды в folder-scope и проверь, что джоба вне папки их больше не видит (сборка падает с ошибкой про отсутствующий credentialsId).
Контрольные вопросы
  • Чем отличаются области system, global и folder и в каком случае выбирать folder-scope?
  • Какие переменные автоматически создаёт credentials() в environment для типа username/password?
  • Почему sh 'echo $TOKEN | base64' сводит на нет маскирование, а прямой echo - нет?
  • Почему пароль надо передавать через --password-stdin или переменную окружения, а не аргументом команды?
Итог

В Jenkinsfile живёт только идентификатор секрета, сам секрет - в зашифрованном хранилище. Точечный доступ дают через withCredentials (маскирование плюс короткое время жизни), на весь stage - через credentials() в environment. Folder-scope разграничивает доступ между командами, ротация делается сменой значения без правки кода. А любое преобразование секрета - base64, set -x, интерполяция двойными кавычками - ломает маскирование и сливает jenkins пароль в лог. Дальше - выносим секреты во внешнее хранилище.
👍4 ❤️3 🔥1 😄 🤔2
Аватара пользователя
Ivanova
Сообщения: 1
Зарегистрирован: 12 май 2026, 05:26

Re: Учётные данные Jenkins: credentials в конвейере

Сообщение Ivanova »

Спасибо, наконец дошло почему именно одинарные кавычки в sh. Раньше копировал из чужих пайплайнов с двойными и Jenkins ругался про небезопасную интерполяцию, а я не понимал в чем дело.
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
DenoAdmin
Сообщения: 1
Зарегистрирован: 06 июн 2026, 03:36

Re: Учётные данные Jenkins: credentials в конвейере

Сообщение DenoAdmin »

Проверил на тесте: echo пароля действительно маскируется, а через base64 вылез в открытую. Жесть, сколько лет так токены текли наверное. Ждем урок про Vault.
👍1 ❤️1 🔥1 😄 🤔1
Ответить
← Предыдущая глава
Безопасность Jenkins: аутентификация и матрица прав
Следующая глава →
Безопасность сценариев: Groovy sandbox и Vault

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

Поделиться темой: ✈ Telegram VK
Похожие запросы: что такое jenkins простыми словамикак установить jenkins на linux и в dockerпервичная настройка jenkins после установкикакие плагины jenkins нужны новичкукак настроить агенты jenkins для сборкиcicd для начинающих с чего начать на jenkins

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

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

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