Всем привет! Меня зовут Александр Барыков, я руковожу платформенной командой DevOps и являюсь лидером DevOps-комьюнити в нашей компании.

Сегодня хочу поделиться опытом, который мы накопили за последние четыре года. Речь пойдет о достаточно специфической, но знакомой многим теме – организации процесса скачивания и проверки внешних артефактов для размещения во внутреннем закрытом контуре. Эта статья будет полезна разработчикам, DevOps-инженерам и архитекторам, которые сталкиваются с необходимостью соблюдения строгих требований безопасности без потери темпа разработки, особенно в финансовом секторе, где есть регуляторные требования.

Сразу оговорюсь: здесь не будет примеров кода или готовых рецептов. Я хочу рассказать именно про эволюцию процесса, про изменения в мышлении команды и про то, как мы совместно с коллегами из информационной безопасности переходили от ручного режима к автоматизированным сервисам.

Начало: 2022 год и первые ограничения

В феврале 2022 году произошли события, которые серьёзно изменили многое и естественно коснулись ИТ сферы. В короткие сроки появилась информация о том, что в различных репозиториях стали появляться различные риски ИБ вплоть до закладок. Для нашей компании это стало неприемлемым. Реакция последовала незамедлительно – возможность скачивать внешние артефакты во внутренний контур закрыли.

Это было правильное решение с точки зрения безопасности, но с точки зрения процессов оно оказалось очень болезненным. Практически мгновенно у многих разработчиков пропала возможность ставить новые зависимости, а у кого-то процесс сборки проектов встал полностью. Мы оказались в ситуации, когда привычные команды npm install, pip install или mvn package переставали работать, так как доступ ко всем репозиториям в интернете был закрыт.

Так мы пришли к самому первому варианту решения – ручному режиму.

Ручной труд и простая автоматизация

На первом этапе мы начали выкачивать артефакты вручную по запросам от разработчиков. Одним из фильтров на тот момент была дата релиза артефакта: мы скачивали для проверки только то, что было выпущено не раньше февраля 2022 года. Логика была простой – условно считалось, что до этого времени в массовых артефактах намеренных закладок быть не должно.

Этот процесс работал, но он требовал огромных временных затрат. Мы быстро поняли, что так жить нельзя: платформенная команда превратилась в «перевалочную базу», а разработчики ждали библиотеки днями или неделями. Мы начали внедрять простейшую автоматизацию для самых популярных типов артефактов: Docker, Python, Maven, NPM.

Алгоритм был прямолинеен: разработчик подавал список пакетов с версиями, скрипт проверял дату релиза, и, если она была до февраля 2022 года, скачанные файлы попадали на изолированное хранилище, специалист ИБ выполнял проверочные мероприятия, принимал решение и если решение было положительным мы переносили артефакты во внутренний контур.

Так мы просуществовали какое-то время, но было сразу очевидно: бесконечно опираться только на «старые» версии невозможно. Старые библиотеки содержат уязвимости, и для их устранения нам требовалось использовать свежие компоненты. Возникла дилемма: нам нужно обновляться ради безопасности, но обновления небезопасны сами по себе.

Выстраивание процесса и необходимость в сервисе

Мы обратились к коллегам из ИБ и разработали с ними новый, более системный подход:

  • Разработчик создает заявку на получение артефакта во внутреннем контуре.

  • Мы скачиваем артефакты во временное хранилище (карантин).

  • Создается заявка в ИБ, артефакты передаются на проверку.

  • ИБ проводит проверку и выносит решение.

  • В случае положительного решения артефакты переносятся во внутренние репозитории, заявка закрывается.

Понятно, что реализовать такой процесс «на коленке» уже не получалось. Нам требовался полноценный сервис с режимом самообслуживания, где разработчик мог бы заказать нужные библиотеки сам.

Так как наша команда в том числе занимается разработкой внутренней DevOps-платформы, выбор места размещения подобного сервиса был очевиден. Подробнее про нашу DevOps платформу можно почитать тут. В процессе проработки решения мы пришли к выводу, что логику по скачиванию, перемещению и прочим шагам лучше вынести из самого сервиса. Нам нужен был отдельный движок процессов, который могли бы оперативно менять инженеры нашей команды, без необходимости переписывать логику сервиса. Выбор пал на workflow-движок Tekton. Заранее скажу: в итоге мы от него отказались в пользу собственной реализации, про это мы напишем отдельную статью.

Почему выбрали Tekton?

Изначально Tekton казался идеальным решением:

  • Нативная поддержка Go. Tekton написан на Go и отлично интегрировался с нашей платформой, которая также использует этот язык. Это упрощало интеграцию и разработку.

  • Быстрый старт. У нас не было готового решения, и нужен был инструмент, который позволил бы быстро реализовать базовый пайплайн «скачать -> проверить». На Tekton-е первый вариант мы собрали достаточно оперативно.

  • Модульность проверок. Планировалось, что кроме скачивания мы будем постепенно добавлять новые шаги: подписи, целостность и прогонять антивирус. Tekton позволял легко добавлять эти шаги в виде отдельных задач.

Почему отказались от Tekton?

  • Ограничение на объём данных. Жесткое ограничение в 4 КБ на данные, передаваемые между этапами пайплайна. Когда мы начали передавать списки зависимостей и метаданные проверок, этот лимит стал серьезным препятствием. Пришлось использовать обходные пути, которые усложняли архитектуру.

  • Архитектурные ограничения. Мы не могли выходить за рамки логики работы пайплайнов Tekton. А часть дополнений, которые мы хотели вносить, превращались в сложно поддерживаемые костыли.

Tekton был хорош как прототип, но для продакшен-сервиса с серьезными требованиями к безопасности он оказался неподходящим инструментом.

Развитие функционала

Как только базовый движок заработал, началось постепенное улучшение процесса. Первым шагом стала стандартизация полей заявки. Чтобы сотрудник ИБ не тратил время на уточнение, мы добавили в форму обязательные вопросы: где будет использоваться артефакт (Dev или Prod), будет ли внешнее сетевое взаимодействие, ссылка на репозиторий проекта, номер задачи в трекере, по которой и потребовались артефакты.

Дальше последовала волна улучшений:

  • Расширение типов артефактов. Мы начали поддерживать все самые популярные в нашей компании типы артефактов: npm, python, maven, go, docker-образы, git-репозитории и нестандартные форматы.

  • Глубокая интеграция с экосистемами:

    • NPM: выбор версии Node, менеджера пакетов (npm/yarn), передача package.json и package-lock для выкачивания всего дерева зависимостей.

    • Python: поддержка requirements.txt, выбор версии Python и целевой платформы (manylinux, musllinux).

    • Maven: возможность передачи на вход pom.xml.

    • Docker: скачивание из приватных репозиториев по логину/паролю.

    • Git: указание ветки или коммита, выкачивание сабмодулей с автоматическим переписыванием путей на относительные (что позволяет нам перемещать скачанные репозитории, не переписывая каждый раз пути до сабмодулей).

  • Автоматизация проверок. Мы старались максимально автоматизировать рутину ИБ. Сейчас используем:

    • Антивирусные проверки.

    • Проверка аутентичности (цифровых подписей и контрольных сумм).

    • Выявление вредоносных паттернов в исходных кодах (malware analysis).

    • Проверка наличия известных уязвимостей в основных БДУ – входной композиционный анализ.

    • Проверка инструкций по сборке docker-образов на предмет наличия ошибок конфигурации, уязвимостей и избыточности.

    • Поиск секретов (паролей, токенов) в коде и образах.

    • Проверка лицензий на ограничения использования в коммерческой среде.

    • И другие проверки

Все результаты формируются в единый отчет, что значительно облегчает принятие решения специалистами ИБ.

Жизненный цикл заявки

Рассмотрим, как выглядит процесс на практике, на примере Python-библиотеки requests==2.32.0 для Python 3.14 на платформе manylinux.

  • Разработчик заходит на портал, выбирает сервис скачивания, тип «Python» и вводит необходимые данные о библиотеке.

  • Система автоматически строит полное дерево зависимостей:

    • requests-2.32.0-py3-none-any.whl

    • certifi-2026.1.4-py3-none-any.whl

    • charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.whl

    • idna-3.11-py3-none-any.whl

    • urllib3-2.6.3-py3-none-any.whl

  • Система сверяет список с внутренним контуром и исключает уже существующие библиотеки (например, certifi, idna, urllib3). К скачиванию остаются только уникальные пакеты.

  •  В таск-трекере создается задача, а в карантинном хранилище – временные репозитории.

  • Артефакты попадают в карантин и параллельно проходят все автоматические проверки.

Общая схема параллельных проверок
Общая схема параллельных проверок
  • Отчеты с результатами проверок загружаются в задачу таск-трекера. Специалист ИБ видит сводную таблицу с отмеченными проблемами (если они есть).

Пример отчета с результатами проверок
Пример отчета с результатами проверок
  • Специалист ИБ выполняет оставшиеся проверочные мероприятия и принимает решение.

  • При одобрении артефакты автоматически переносятся во внутренние репозитории, становясь доступными для всех. В нашем примере с requests==2.32.0 загрузка была отклонена, так как  были найдены уязвимости.

WhiteList: доверенные артефакты

Мы заметили, что многие артефакты запрашиваются часто и используются только в локальных средах разработчиков и тестировщиков (например, ChromeDriver). Проверять их вручную каждый раз  непродуктивно.

Также выделились артефакты от вендоров, которые предоставили доказательства наличия у них безопасных процессов разработки (SDLC) или имеют у себя сертификат аккредитации регулятора, которому доверяют наши сотрудники ИБ. Для таких артефактов мы ввели сервис WhiteList (белый список).

Логика работы:

  • Сервис автоматически проверяет наличие новых минорных версий доверенных артефактов.

  • При появлении версии сервис скачивает её, создает заявку, проводит все автоматические проверки.

  • Если проверки пройдены успешно, публикует во внутренний контур. Если нет – стоп, требуется вмешательство человека.

  • Новые мажорные версии добавляются только после полноценной ручной проверки специалистом ИБ.

  • Периодически артефакты из WhiteList проходят повторные проверки для подтверждения их статуса.

Это существенно снизило нагрузку и ускорило доступ к инструментам, которые нужны разработчикам каждый день. Фактически такие артефакты появляются во внутреннем контуре раньше, чем их бы запросили.

Песочница (Sandbox): решение сложных кейсов

Даже с автоматизированным скачиванием остаются сложные случаи. Представьте новый проект с сотнями зависимостей. В закрытом контуре вы начинаете сборку, она падает на отсутствующей библиотеке, вы заказываете её, ждете проверки, снова запускаете, падаете на следующей… Итераций может быть очень много, а процесс затягивается на недели.

Чтобы решить эту проблему, мы ввели сервис Песочница (Sandbox). Это позволяет безопасно собрать проект и получить все зависимости за один раз.

Процесс выглядит так:

  • Разработчик получает временную виртуальную машину в строго изолированном контуре, из которого невозможна утечка.

  • Доступ к машине осуществляется только через веб-платформу (GUI/консоль), прямого терминального доступа нет.

  • При создании VM на неё копируется проект разработчика.

  • Поднимается инфраструктура репозиториев:

    • Создается группа в карантинном хранилище.

    • Подключается прокси-репозиторий, который смотрит во внутренний контур (чтобы не скачивать лишнее из сети).

    • Подключается прокси-репозиторий, который может ходить в Интернет. Именно в его кэш попадут все внешние артефакты.

  • Разработчик собирает проект в песочнице, отлаживает код, пока все не заработает.

  • После нажатия кнопки «Отправить на проверку» доступ разработчика к VM блокируется, права передаются специалистам ИБ.

  • Всё, что осело в кэшах прокси-репозиториев, выгружается и отправляется на автоматические проверки.

  • ИБ проводит аудит, подключается к VM при необходимости и выносит решение.

  • При согласии артефакты переносятся во внутренний контур. VM и временные репозитории уничтожаются.

Каждая проверка – это новая, чистая виртуальная машина. Этот подход обеспечивает отсутствие персистентности, невозможность пронести во внутренний контур что-то вручную, воспроизводимость среды и возможность получить полный список зависимостей проекта за один заход, что уменьшает трудозатраты как разработчиков, так и специалистов ИБ.

Результаты

Через несколько лет работы мы получили управляемую систему:

  • Управляемый поток. Множество случайных скачиваний превратилось в упорядоченный процесс с очередями и статусами.

  • Снижение нагрузки на ИБ. Ручная работа, где это возможно, сведена к минимуму, специалисты фокусируются на сложных и опасных артефактах.

  • Прозрачность. Разработчики видят, на каком этапе находится их заявка, понимают причины отказов.

  • Воспроизводимость. Проверки стандартизированы и документированы.

  • Масштабируемость. Мы можем добавлять новые проверки и поддерживать новые языки программирования, не перестраивая всю систему заново.

Самое важное – мы перестали просто реагировать на внешние обстоятельства и начали осознанно строить инженерный процесс, адаптированный под работу в закрытом контуре.

Что дальше?

Работа не стоит на месте. Мы планируем развивать автоматическое построение деревьев зависимостей, расширять список поддерживаемых типов артефактов и сервис WhiteList, внедрять новые проверки, вводим период охлаждения (не скачиваем артефакты, которые выпустили только что, а выжидаем некоторое время, на случай если там будет обнаружена уязвимость) а также продолжать улучшать пользовательский опыт портала.

История началась с простого «закрыли интернет», но превратилась в полноценный security-сервис для поддержки разработки. Если 2022 год заставил нас действовать быстро и импульсивно, то последующие годы позволили превратить вынужденную меру в налаженный процесс, который помогает максимально комфортно жить нашей компании в закрытом контуре.

Спасибо за внимание! Буду рад ответить на вопросы.