Hardening Jenkins: как подать блюдо, чтобы оставили чаевые
Привет! Я Лев Хакимов — техлид команды безопасности в Wildberries, а в прошлом — DevOps (хотя говорят, что бывших DevOps не бывает). А ещё я организатор VrnCTF, CentralCTF, кубка CTF, MiaCTF, OmCTF. Автор дисциплин DevOps в ВГУ и ИТМО. Меня можно найти в соцсетях по имени: @devijoe. Пишите вопросы, отвечу в любое время, если не отдыхаю и не сплю.
В этой статье по одноимённому докладу для конференции «DevOpsConf»:
расскажу про Jenkins и его экосистему (для тех, у кого Jenkins нет, либо он мало с ним работал, это будет особенно полезно);
покажу, как мыслит и действует злоумышленник;.
разберу проблемы безопасности и уязвимости в Jenkins;
научу, как защититься от угроз, выстроив тактику защиты;
познакомлю с хорошими практиками по базовой конфигурации, если вы ещё не сталкивались с разворачиванием Jenkins;
сформирую чек-лист, как сделать Jenkins безопаснее. С его помощью вы сможете посмотреть на свою инсталляцию и понять, защищены ли вы от большей части самых распространённых атак.
Пара слов о Jenkins
Jenkins — это CI/CD сервер, распространяющийся по MIT лицензии. У Jenkins есть мастер, который может иметь несколько агентов. Они могут быть самыми разными, и на них мы можем запускать свои сборки.
За что мы любим Jenkins? За бесконечное количество плагинов, конечно. А если даже не нашли нужный плагин, но имеете разработчика с прямыми руками, то сможете его самостоятельно написать и запустить. С Jenkins вы можете делать всё, что душе угодно и чего другие CI/CD-платформы часто лишены.
В Jenkins используются Groovy и частично JavaScript. Groovy — весьма приятный язычок, который выглядит примерно так:
Groovy создан для людей, которые в программировании — панки. На прошлой DevOpsConf даже был доклад о том, как писать на нём пайплайны так, чтобы разработчики вас понимали.
История Jenkins
Будущий Jenkins появился в известной в Java-кругах компания Sun Microsystems. Она сделала прекрасный язык программирования под названием Java. А ещё, чтобы тестировать свои внутренние сборки, когда слова DevOps и CI/CD ещё не существовали, ребята в нулевых годах сделали платформу, которая называлась Hudson. Её разработал прекрасный человек — Кохсуке Кавагути.
Это единственное его фото, которое я нашёл в интернете — сделал его студент. Но мы хотя бы можем посмотреть на причину наших бессонных ночей. А потом компания Oracle поглотила компанию Sun со всеми её разработками.
Товарищ Кохсуке Кавагути позарился на самое святое, что есть — на деньги, и захотел на своей разработке заработать. Он создал собственную компанию и сказал ребятам из Oracle, что хочет разворачивать и делать менеджер-поддержку для Hudson типа GitLab Enterprise. Компания Oracle ответила что-то вроде: «код забирай, название мы себе оставим и все права тоже, но попробуй». Кавагути возмутился, форкнул Hudson и выложил его в Open Source. После этого форка Oracle резко охладела к коду на Hudson и отдала его в Eclipse Foundation, где он благополучно канул в небытие и умер окончательно, перестав поддерживаться в 2017 году.
А вот Jenkins сегодня многие используют, в том числе Программный Комитет конференции DevOpsConf. Но при этом большинство пользователей не знают, как его защитить.
Сказка
Итак, у нас есть компания и сисадмин, который занимается в ней железками, BareMetal, VM«очками. Админов может быть как один, так и несколько. Хороший сисадмин решает задачи бизнеса, в которых безопасность стоит на первом месте, далеко не всегда.
Админу было нужно катить свои сборки, и он поставил BareMetal, а на него установил Jenkins. На самом деле он мог взять и VM, но для простоты пусть будет BareMetal. Развернул GitLab, и получилась красота: сборочки работают, всё катится, компания довольна.
А потом, однажды ночью случается вот это:
Он просыпается утром и обнаруживает, что все разработки компании внезапно перешли в разряд опенсорса. Более того, базы тоже стали достоянием общественности. И при разборе инцидента выясняется, что виной стал CI/CD-сервер. Злоумышленник попал в инфраструктуру, получил доступ до CI/CD, а дальше добрался до всего остального, что есть в компании. Надо исправлять ситуацию!
Что же могло пойти не так? Правильный ответ — всё. Разберёмся конкретно.
Глава 1. Уязвимости Jenkins Core: официанты тоже болеют коронавирусом
Мы понимаем, что Jenkins — это 90% плагины и лишь 10% — Jenkins Core, в котором нет ничего. Ведь Jenkins — это платформа для установки плагинов, веб-сервер, мастер-нода. Посмотрим, что с ним не так.
Представьте, что вы — админ, любите Jenkins, поставили и развернули его в базовой конфигурации. Возможно, даже плагины не устанавливали, либо установили лишь несколько базовых вроде Groovy Pipelines, чтобы запускать пайплайны. Поставив все свежие версии, ушли спать, а наутро вас взломали. Да, как-то некрасиво получилось. При том, что поставили вы только всё самое свежее, и этого просто не должно было случиться.
Тот, кто следит за CVE Jenkins, знает историю про Args4J. А для остальных — подсвечу.
Args4J
Jenkins написан на Java. В нём есть Jenkins CLI, который использует парсер аргументов в командной строке. Его задача — передать команду с аргументами, а затем распарсить и выполнить. У некоторых Java-утилит, например, у Log4J, есть возможности, которыми практически никто не пользуется, кроме хакеров. У Args4J была такая же. Сюрприз: если мы в качестве аргумента напишем @/path/to/file (путь до файла), то он любезно этот файл откроет, считает из него всё и поместит в вывод. Казалось бы: всё замечательно, нам не надо думать над открытием файлов. Только вот и хакерам тоже не надо думать, как до них добраться.
Работает это буквально так:
Просто вызовем jenkins-cli, в примере — localhost, но это не суть важно. Затем вызовем etc/passwd и в случае модуля help получим только первую строчку. А дальше всё зависит от того, какие модули злоумышленник сможет вызывать. Но если у него есть anonymous read access, то он сможет вызвать, например, connect node. На самом деле он к ней, скорее всего, не сможет подключиться. Зато получит »@/etc/passwd», который везде хорошо читается. Это говорит о том, что файлы прочитать возможно.
Можно перечитать всё, что лежит внутри, вытянуть все секреты Jenkins. Так ваш Jenkins превращается в достояние общественности. А дальше вопрос лишь в том, как расшифровать полученные данные.
Как это работает?
Args4J достает по @ контент файла, помещает это в Java_Options, а Java любезно при запуске нам этот Java_Options показывает. При выводе команды она обязательно его выведет вместе с содержимым этого файла в разряде аргументов. По статистике, которую я смог найти, атаковали 46 тысяч таких Jenkins по миру. Есть даже exploit на Python:
Так любой школьник, который доберётся до вашей инфраструктуры, сможет подобное провернуть. Сейчас эту уязвимость устранили, но на первых порах от неё вообще никак нельзя было защититься, кроме как отключив Jenkins CLI.
Получаем такой красивый вывод:
Check List №1: Сканируйте любые версии на наличие в них CVE, следите за комьюнити продукта
Нельзя сказать, что в комьюнити Jenkins всё выкладывается сразу в удобном виде. Тем не менее на Jenkins.io можно посмотреть по месяцам основные сводки по CVE, подсетям (от «поседеть») и продумать, как эти дыры закрыть.
Глава 2. Groovy Sandbox Escaping: сбегаем из детской «песочницы», не привлекая внимания админа
Когда я вижу слово Sandbox, то представляю форк, изоляцию, как Docker по namespace, и код, который выполняется в изолированной среде и не может сбежать на хост. Я всегда так думал, когда пользовался Jenkins. Но стоит посмотреть, как всё устроено на самом деле.
Представьте, вы приходите утром на работу, открываете рабочую почту и видите там вместо Night Build письмо счастья, где обнаруживаете куски Groovy кода. Например, такого:
Это Groovy shell код, как получить shell из Groovy. А значит, настало время погрузиться в Groovy Sandbox и понять, как это возможно.
Я приведу пример на одной из уязвимостей, которая есть в плагинах. Но если вы посмотрите CVE по различным плагинам, то увидите, что таких возможностей на самом деле очень много. Также CVE, которые имеют в Jenkins степень угрозы high, а не critical, только потому, что это плагины, и они не у всех по умолчанию могут стоять. Но там или RCE, или есть возможность запросто читать и переписывать файлы на Jenkins. Таких уязвимостей было очень много в 2023 году, и они относительно свежие. Учитывая, что обновлять Jenkins и плагины любят не все — считают, что если всё работает, то зачем.
Как работает Groovy Sandbox by design
позволяет запускать Groovy код изолированно;
по умолчанию работает из коробки;
код не может запустить привилегированные операции;
все опасные функции — только по согласованию с администратором.
Если какая-то потенциально опасная функция есть, то она приходит администратору с просьбой согласовать, что это можно запускать.
Выглядит это примерно вот так:
Вроде бы всё как привыкли, нормальная изоляция. Но на самом деле нет.
Как это работает на самом деле
У нас есть JVM. Мы знаем, что JVM — изолирована. Там у нас выполняется Java-байткод, и туда, куда ей не разрешили, она не залезет. Произвольно по памяти она не гуляет, как в C, и не даёт особо далеко заходить. Но иногда этого и не требуется.
Есть специальный модуль groovy-sandbox. Этот модуль начинал писать еще Кавагути. Его коммиты есть на GitHub. Имеем примерно такой код:
Вообще, даже для джавистов этот код страшный, потому что написан давно, и кажется, что люди из JS пришли и написали код на Java. Подсвечено самое интересное:
checkedStaticCall — функция, которая проверяет StaticCall, то есть все статические функции.
есть некий класс receiver, общая обёрточка — то, что мы получаем.
findCheckedReplacement — функция, которая проверяет различные замены. В частности, разворачивает более сложные функции до простых, собирает из этого итерируемый объект. В том числе, разворачивает все Groovy Clojure s до базовых функций.
Потом функция findCheckedReplacement итерируется в чейнах по hasNext по базовым функциям, вызывает их. И дальше мы видим следующее:
собираем некий итерируемый объект;
делаем замены (там на самом деле распаковываются Clojure s);
для каждого объекта в Iterables вызываем call () (с этого момента изоляцией уже не пахнет);
Смотрим, когда все рванёт.
На самом деле, с точки зрения пользователя это выглядит так:
Если pipeline падает из-за того, что у него что-то не сработало, то появляется это:
То есть scripts not permitted (не разрешён), и мы видим StaticWhitelist и rejectStaticMethod. Фактически у Jenkins есть список Groovy-функций, которые разрешены из коробки, и всё, что не разрешено — запрещено по умолчанию. Он парсит до базовых функций, смотрит, какие базовые объекты и функции разрешены, а какие — запрещены, и вызывает метод call. Так он просто перебирает все существующие функции. Проблема в том, что это не очень похоже на Sandbox.
Со стороны админа это выглядит примерно так:
То есть можно аппрувнуть, и функция добавится в список разрешённых, а дальше триггериться для pipeline уже не будет.
Резюмируем:
JVM не позволяет вам свободно адресоваться во всей памяти;
Класс Checker фактически построчно запускает наш Groovy скрипт;
если команда потенциально опасная — админ получит уведомление;
если опасности нет — скрипт выполняется в ОБЩЕМ адресном пространстве JVM;
фактически это не настоящий sandbox, а валидатор.
Да, JVM передвигаться по памяти нам не разрешит, но у Groovy Sandbox есть класс Checker, который это проверяет. Потенциально опасная команда отправляется админу, и если опасности нет, скрипт выполнится в общем адресном пространстве JVM.
То есть, если мы найдём способ забайпасить эту проверку, потому что это не Sandbox, а валидатор обычный валидатор, то получим возможность исполнять какой-то код. Правда здорово?
Посмотрим, как это эксплуатируется на примере одной из уязвимостей.
Есть config-файл-провайдер, в который обычно помещают базовые maven-файлы, а затем их линкуют к Java-коду как основные. У config есть фишка: туда можно писать всё, что угодно — в частности темплейтируемые файлы.
Есть Email-Extension, потому что письма мы отправляем всем на почту. Если мы передадим Email-Extension template из config-файла провайдера и добавим туда переменных, то заработает одна из старых как мир уязвимостей — уязвимость шаблонизатора. Так вы запросто можете исполнять код в обход Sandbox. Всё проходит за байпас и выполняется непосредственно в JVM. Так вы получаете фактически RCE на Jenkins.
Разработчики плагина забыли подключить скрипт Security Protection, который экранирует все опасности и проверяет на уязвимость шаблонизатора. Должно быть вот так:
Вопрос: как часто люди обновляют плагины в Jenkins? Следующий пункт чек-листа — штука важная, и в основном её все игнорируют.
Check List №2: Сканируйте все плагины, составляйте SBOM
Есть стандартный формат Software Bill of Materials (SBOM). Это один из множества инструментов для Trivy. Составьте SBOM и положите в свой Git. Периодически сканируйте при обновлении плагинов Trivy и смотрите, какие уязвимости появились в плагинах. Также следить за обновлениями на сайтах Jenkins и CVE, потому что обнаруживать, что Jenkins оказался дырявым, просто потому, что нормально не обновлялся — очень неприятно.
Глава 3. А что там с инфраструктурой: best practice встречается с реальностью
Если кто-то из вас использует не Jenkins, то эти советы тоже будут кстати — они универсальны для всех.
Напомню, как всё выглядело:
Как известно, не все плагины хорошо друг с другом сочетаются. Периодически может случаться так, что вы обновите один плагин, и у вас посыплются другие. А вы о таком даже не подозревали. Чтобы проверять плагины, добавьте тестовый Jenkins.
Потенциально сеть сейчас выглядит плоской, а значит, от неё пора избавиться, чтобы если у вас что-нибудь случится на тестовом Jenkins, то прод от этого не загорелся. Тогда даже если dev горит, проду будет нормально.
Check List №3: сделайте себе тестовый Jenkins и отгородите его от продуктовой среды по сети
Делаем тестовый Jenkins, отгораживаем его, изолируем. Да, злоумышленнику будет проще туда попасть. Ведь при тестировании мы не всегда задумываемся о безопасности. Но в этом случае он хотя бы не попадёт в прод и поломает не так много, как мог бы.
А ещё лучше разделять Jenkins CI и Jenkins CD. Потому что Jenkins CI может смотреть на mirrors и периодически поглядывать в интернет. Мы тестируем пакеты, которые не успели добавить на зеркала. Там проводятся сборочки, а сборочный Jenkins много куда смотрит. Но по-хорошему, мы должны в CI собирать сборки и отправлять в registry наши образы, складывать дистрибутивы. Только в этот registry может заглядывать CD Jenkins из отдельной изолированной среды и больше никуда, кроме registry и необходимых ему зависимостей. Туда попадает только то, что проверено и верифицировано — за этим следят безопасники.
Таким образом, вы изолируетесь от того, что непроверенный код может раскатиться на прод. Соответственно, CI/CD мы тоже отгораживаем.
Check List №4: CI и CD тоже должны быть отгорожены
Чтобы убедиться, что не произошло атаки типа supply chain, когда злоумышленник подменяет что-нибудь в registry, когда вы того не ожидаете. То есть у вас сложилась нормальная сборка, а потом вы получили на проде что-то плохое. Тогда воспользуйтесь cosign и проверьте подписи. Cosign интегрирован в Kyverno, если вы используете Kubernetus.
Вам нужно подписать свой образ при сборке. А потом уже на деплое вы посмотрите, что получилось — сверяете механизм сертификатов и узнаете, насколько у вас совпадает образ.
Команда для верификации из документации cosign:
В Kyverno есть встроенный cosign, поэтому для деплоя в Kubernetus эта команда подойдёт.
Check List №5: Подпись артефактов позволит избежать подмены образов и добавит дополнительный эшелон обороны
Глава 4. Пара слов о безопасной конфигурации или как правильно входить в Jenkins
Поговорим о том, что сделать, чтобы Jenkins был безопасным. Опытные дженкинсоводы, которые держат его не первый день, наверняка о многом уже слышали. Я вряд ли открою Америку в конфигурации. Но если вы Jenkins поставили просто «потому что» и базово его не конфигурировали, то это будет полезно.
Есть 3 A в security:
Authorization,
Authentication,
Auditing.
В рамках этой главы мы поговорим только про авторизацию и аутентификацию. Напомню, что авторизация — это проверка, что к нам пришёл конкретный человек, а не тот, кто выдаёт себя за него. Аутентификация проверяет, что человек получил действительно те права, которые ему положены.
Authentication
Из коробки есть два realm«а аутентификации:
Jenkins Database
Servlet Container
В Servlet Container аутентификация даётся контейнеру Servlet, будь то Apach или Jetty — всё, где это есть, можно запустить, и аутентификация будет проходить его средствами. А Jenkins Database содержит локальную базу с данными о пользователях, и она защищена токенами, которые хранятся на файловой системе. Как мы уже поняли, токен на файловой системе — это очень ненадёжная штука, и эти два realm«а мы даже не рассматриваем всерьёз, поскольку есть стандартные способы проверить аутентификацию, куда лучше.
Также не забываем выключить анонимные входы на Jenkins (Allow users to sign up). Про это вообще многие забывают. Периодически бывает так, что все realm«ы подключены, всё нормально работает.
Но всё равно какую-то базовую беспарольную учетную запись, которая всем известна, злоумышленник может попасть и просматривать сборки.
Воспользуйтесь стандартными механизмами аутентификации (LDAP, oAUTH, SAML, etc.). Те же LDAP почти у всех есть в Active Directory всё нормально подключается. Правда, не очень хорошо работает oAUTH на KeyCloak — с ним периодически бывают проблемы с подтюниванием, но с LDAP проблем нет вообще никаких. И многие в Jenkins спускаются по LDAP.
Check List №6: аутентификация всегда должна быть на стороне вендора (LDAP/oAuth). Не используйте встроенные механизмы
У Jenkins Database нет ни политики смены паролей, ничего такого, только пароль юзера. Всё менеджерить приходится на стороне Jenkins. Делать это из LDAP откровенно удобнее.
Авторизация
У Jenkins уже несколько политик авторизации:
Anyone can do anything означает, что все могут делать всё, что можно.
Legacy mode даёт нам права администратора.
Logged in users can do anything могут делать всё — то есть, если у вас есть логин-пароль, вы можете делать всё.
Matrix-based security — наверное, самая популярная и всем доступная политика.
RBAC-системой она была какое-то время в коммерчески поддерживаемом Jenkins. RBAC, по-моему, в общий доступ так и не вышел и особо не распространен. Поэтому стандартно используют практически всегда Matrix-based систему авторизации, потому что все остальные откровенно не подходят. В ней можно достаточно гибко всё настроить.
Это не очень удобно делать вручную, потому что если у вас много пользователей, матрица очень тяжело грузится в интерфейсе. Ведь она — тяжёлая, большая и нам не очень удобно ей пользоваться. Но к счасью, у Jenkins есть нормальный REST AP. Если у вас есть сторонний сервис типа IDM, который занимается вопросом предоставления доступа в авторизации, то вы должны были озадачилиться вопросом предоставления массового доступа к вашему Jenkins, а не только одной команды. То есть потенциально всем стоит задуматься о том, что можно просто по REST отправлять запросы к Jenkins, добавлять и убирать пользователей. В целом это достаточно удобная система по настройке доступов, если ей пользоваться по REST, а не делать всё вручную.
Project-based Matrix Authorization Strategy — это аналогичная описанной выше стратегия, которая применяется на конкретную папочку на Project, а не в целом на весь Jenkins. То есть доступы с помощью этой модели можно настроить весьма гранулярно до конкретной папки. Отсюда мы добавляем еще один пункт в наш чек-лист.
Check List №7: используйте матричную стратегию доступа
Матричная стратегия доступа хорошо проверена и много где используется. Если её нормально приготовить и удобно автоматизировать, то можно забыть про вопросы доступа к Jenkins на достаточно долгое время.
CSRF & Markup formatters стоит включать из коробки по умолчанию, потому что из коробки по умолчанию настройка не включена. Как бы странно это не было.
Markup Formatters позволят проигнорировать небезопасные HTML-символы, например »<» и «&» (защита от XSS)
В случае Markup Formatters Jenkins позволяет конфигурить сами сборки при помощи HTML. Это очень классно, потому что мы можем фактически генерировать произвольный HTML-код и делать очень красивые страницы сборки с самописными статусами. Можно включить в себе внутреннего фронтендера и порадовать его. Но, тем не менее, в случае, когда мы делаем HTML, есть вероятность инжекта кода, а Markup Formatter это как раз экранирует.
CSRF защита позволит запретить Jenkins обрабатывать неподписанные им же самим запросы
Всё это можно настроить непосредственно из интерфейса, но по умолчанию не включено. Поэтому помните, что надо включить.
CSRF — это очень важно. В чем её суть?
Представьте, что злоумышленник присылает вам картинку с котиками, а внутри встроена ссылка, например, на сайт Сбербанка или любого другого банка, которая заставит триггернуть перевод денег. Очень неприятно открыть картинку с котиками и лишиться денег. Поэтому обязательно есть проверка, что запрос пришёл от верифицированной системы. CSRF токены нужны нам для этого. Отсюда делаем вывод — включаем защиту от атак XSS и CSRF токены.
Check List №8: включите защиту от XSS и CSRF
Секрет, который знают опытные дженкинсоводы
Если вы записали секрет, но забыли, что в нём лежит, то by design мы можем им пользоваться, вызывать его из сборки, но не можем, например, его логировать. Если мы попытаемся вывести Jenkins-секрет, то получим звездочки и ничего не увидим.
Но на самом деле нет! Было бы скучно, если бы всё обстояло именно так. Должен же быть путь посмотреть, что там лежит. Поэтому я даже в некоторых Jenkins видел сборку «Посмотри секрет». Выбираешь из списка секрет и тебе в логе выпадают все секретные токены. Поэтому больше двух секретов говорят вслух. Задание, которое давал на одну CTF, очень неплохо зашло, его легко поломали школьники. Как вы думаете, злоумышленник тоже про это знает?
Из интересного есть ещё clojure withCredential. Кто не знает, Clojure — это фактически обёртка, которая позволяет выполнить какой-то рамочный код и внутрь этого рамочного кода поместить вашу логику. Это называется функциональный интерфейс в Java, а в Groove его написали очень красиво и лаконично, как в JS. Но не суть. Здесь мы можем указать, какой credential используем и в какой variable хотим записать секрет, чтобы потом его вызвать. Если мы его вызываем из clojure, то все правила сработают. Если же пытаемся его прочитать, увидим звёздочки. Но если мы его запишем в txt-файл, а потом попытаемся сделать cat, секрет прекрасно распечатается. Таких байпасов в withCredential очень много. Это лишь один из них. При этом все функции разрешены.
Check List №9: строго контролируйте доступ на создание джоб
Поэтому лучше джобы тянуть из Git и не давать доступ людям в консоли Sandbox, если это не нужно. На самом деле на все эти страшные функции и их аргументы можно посмотреть в pipeline-конфигураторе в Jenkins, но при этом их не вызывать. Поэтому лучше не давать доступ к анонимным Sandbox и в принципе возможность исполнять Groovy-код там, где есть credentials.
И ещё несколько советов:
Включите запись Audit Logs хотя бы для того, чтобы знать, что происходит в вашем Jenkins. Там хранится информация об аутентификациях, действиях пользователей, запуске и статусе джоб, а также изменения конфигурации.
Настройте TLS между мастер-нодой и агентами, по умолчанию.
Отключите возможность запуска сборок на мастере. Некоторые в больших компаниях используют сборки на мастере и даже долго потом хранят их результаты. Если злоумышленник получит возможность их прочитать, то это не самая приятная ситуация. С одной стороны, отключая, например, долговременное хранение, мы лишаемся возможности заходить, передвигаться по папочкам и смотреть, что происходит внутри сборки, а при дебаге Jenkins это бывает полезно. Но с другой стороны, у нас есть эфемерный ранер в Docker или Kubernetes — мы его запустили, он выполнил код и аккуратно завершился.
Чтобы решить эту проблему, есть эфемерные ранеры. Запускаются и настраиваются они легко через плагины.
Что использовать?
Но стоит помнить, что Docker тоже нуждается в харденинге, и, добавляя какую-то новую систему, её тоже нужно харденить. Если у вас контейнеры запускаются с отключенной изоляцией в Docker, внутри root, то значит вы не особо и заизолировались. Более подробно можно посмотреть в докладе, который мы делали вместе с Лешей Федулаевым для Highload.
Там подробно говорится про эфемерные ранеры и в целом про процесс приемки open source и CI/CD. Можно найти для себя несколько полезных советов. В целом про Hardening Docker уже не раз были доклады. Можно найти их в открытом доступе или прийти ко мне — я поделюсь полезной информацией.
Check List №10: никаких сборок на мастере
Подведём итоги
Сканируем версии на наличие в них CVE, следим за комьюнити продукта.
Сканируем все плагины, составляем SBOM, смотрим уязвимости в Java-либах.
Делаем себе тестовый Jenkins, отгораживаем его по сети от прода.
CI и CD разграничиваем.
Подписываем артефакты, это несложно.
Аутентификацию настраиваем на стороне стороннего вендора — не в смысле какой-то компании, а просто разворачиваем LDAP или что-то ещё, на стороне.
Используем матричную стратегию доступа.
Включаем защиту от CSRF и XSS.
Строго контролируем доступ на создание джоб. Лучше права отобрать и запускать джобы только через Git, добавлять их через доверенного пользователя, который подключит ваш проект, либо воспользоваться, например, IDM, решить вопрос быстро интегрировать джобу. Вы можете посмотреть на уровне Git, что у вас там происходит и кто что коммитит.
Никаких сборок на мастере.
Всё это можно сделать быстро, легко и сильно повысить зрелость вашей Jenkins-инсталляции.