Практическое руководство по простой подписи программных артефактов с помощью проекта sigstore и интерфейса командной строки cosign.

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

Однако подписать программное обеспечение может быть легко благодаря sigstore и его cosign CLI! В этой статье мы узнаем, как cosign работает и интегрируется с другими компонентами хранилища сигнатур (fulcio и rekor). Что еще более важно, мы узнаем, как использовать его для простой подписи образа контейнера, как с ключами, так и без них, а также как мы можем использовать его для проверки созданных подписей и целостности подписанного программного обеспечения.

Примечание. Это практическое продолжение моей предыдущей статьи Sigstore: решение для безопасности цепочки поставок программного обеспечения, в которой объясняется, что такое sigstore и как работают его компоненты.

Настройка

Прежде чем подписывать что-либо, нам сначала понадобятся все инструменты CLI для каждого из компонентов sigstore, то есть cosign, fulcio и rekor. Первый из них - cosign, который нам нужен для подписи чего-либо, может быть установлен как бинарный файл или как образ Docker. Для первого варианта загрузите соответствующий двоичный файл со страницы выпуска и поместите его где-нибудь в свой $PATH. Кроме того, учитывая, что мы имеем дело с инструментами безопасности, рекомендуется проверить подлинность и целостность двоичного файла. Вы можете сделать это с помощью команд, показанных на странице выпуска.

Если вы предпочитаете использовать образ Docker, вы можете использовать следующее:

Для второго компонента - fulcio - нам не нужно ничего устанавливать, потому что мы будем использовать общедоступный экземпляр fulcio. Служба общественного блага доступна по адресу https://fulcio.sigstore.dev/api/v1, а документацию по API можно найти здесь.

Наконец, есть rekor и его интерфейс командной строки под названием rekor-cli. Как и в случае с fulcio, нам не нужно устанавливать rekor, поскольку он доступен по адресу https://rekor.sigstore.dev вместе с определением Swagger здесь.

Однако мы захотим установить CLI, чтобы взаимодействовать с rekor сервером. Бинарные файлы доступны на странице выпуска GitHub. Если вы используете Linux, вы можете использовать следующее:

И снова, как упоминалось с cosign, вы должны быть осторожны с тем, какие двоичные файлы вы используете. Поэтому вы можете захотеть проверить rekor-cli двоичный файл, используя процесс, описанный здесь.

Трудный путь

Когда все инструменты готовы, мы можем начать подписывать артефакты. Чтобы лучше понять, что происходит под обложками, мы сначала попробуем сделать это «трудным путем», то есть - без всех причудливых инструментов.

Для начала нам понадобится артефакт. Для этой демонстрации мы будем использовать «hello world» образ Docker, созданный с использованием следующего Dockerfile:

Однако мы не можем подписать само изображение, вместо этого мы подпишем его дайджест:

Затем нам понадобится эфемерная пара ключей для подписи дайджеста. Для этого мы можем использовать cosign команд, но, учитывая, что это «сложный путь», давайте использовать openssl напрямую:

Теперь мы готовы подписать его, а пока мы можем проверить подпись:

Теперь, когда мы подписали артефакт нашим закрытым ключом, мы хотим получить доказательство того, что это мы действительно сделали. Для этого нам понадобится сертификат подписи кода от fulcio. Чтобы получить его, мы должны пройти аутентификацию у поставщика OIDC, чтобы получить токен идентификатора, который служит доказательством нашей личности для fulcio.

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

Наконец, мы просим fulcio предоставить сертификат подписи кода, предоставив ему идентификационный токен в качестве формы авторизации, подписанный адрес электронной почты и наш открытый ключ:

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

В качестве альтернативы вы также можете полностью пропустить взаимодействие с fulcio и использовать вместо этого свой открытый ключ. Этот подход показан в https://github.com/sigstore/rekor/blob/main/types.md#pkixx509.

Затем мы можем продолжить загрузку записи в журнал прозрачности (rekor). Здесь мы показываем как вариант с нашим открытым ключом, так и сертификат подписи от fulcio. При использовании сертификата от fulcio мы также можем удалить пару ключей, поскольку она нам больше не нужна:

Помимо выгрузки мы также можем проверить наличие записи в журнале прозрачности. В приведенном выше фрагменте кода используются как rekor-cli, так и curl для прямого доступа к общедоступному API.

Все, что осталось сделать, это загрузить подпись в реестр, которая будет храниться вместе с образом контейнера:

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

Легкий путь

«Трудный путь» был несложным, но он станет намного проще, если мы воспользуемся предоставленными инструментами:

Все, что нам нужно сделать, это создать пару ключей, а затем подписать артефакт. После подписания cosign автоматически загружает подпись в реестр, где находится образ. В приведенном выше примере мы решили не загружать подпись, а просто сохранить ее в файл, потому что мы уже подписали ее в предыдущем разделе. Если позже мы все же решим загрузить его, то сможем сделать это с помощью cosign attach, как показано выше.

Также стоит отметить, что на данный момент (cosign версия 1.0) приведенный выше фрагмент не будет загружать данные в rekor журнал прозрачности, для этого нам нужно установить COSIGN_EXPERIMENTAL=1, например, COSIGN_EXPERIMENTAL=1 cosign sign -key cosign.key ....

Есть также другие способы использовать cosign для подписи артефактов в зависимости от вашего варианта использования и рабочего процесса. Они подробно описаны на странице использования в GitHub.

«Бесключевой»

Еще проще, чем простой способ, - использовать метод «без ключа», в котором используются только эфемерные ключи, а это означает, что вам не нужно создавать и поддерживать свои собственные ключи:

Все, что нам нужно сделать, это запустить cosign sign с COSIGN_EXPERIMENTAL, установленным на 1, опуская при этом аргумент -key. В приведенном выше примере мы также указали конечные точки поставщика OIDC, сервера fulcio и сервера rekor - это значения по умолчанию для общественных услуг, предоставляемых sigstore, поэтому их можно не указывать, но они показаны здесь для ясности и выделения, какие службы доступны / используются. Вы также можете заменить их своими собственными экземплярами - это имело бы смысл, если бы вы хотели запускать все за брандмауэром.

Проверить все

Теперь, когда мы подписали артефакт всеми возможными способами, мы также должны попытаться проверить его, иначе какой смысл подписывать его в первую очередь, верно?

Сначала давайте рассмотрим результаты подписания дайджеста изображения «трудным путем». Для этого мы можем использовать rekor-cli:

Здесь у нас есть 2 случая - если мы подписали артефакт нашим открытым ключом, мы используем его при проверке. С другой стороны, если бы мы использовали сертификат подписи, предоставленный fulcio, мы бы использовали его вместо открытого ключа.

Далее идет проверка с использованием cosign, который подходит для базовой подписи с ключами. Все, что нам нужно сделать, это запустить cosign verify, указав ключ и URL-адрес изображения:

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

Заключительные мысли

В этой статье я попытался обрисовать и объяснить основные варианты использования и подходы для подписи образов контейнеров с использованием sigstore и, в частности, cosign. Однако есть много других опций и функций cosign, которые могут быть вам полезны, например, работа с другими типами артефактов, использование аппаратных токенов или подписание git коммитов, поэтому я рекомендую вам поиграть с инструментом и посмотреть, что еще вы можете использовать его для. Многие из этих параметров описаны в очень хорошо написанной документации по использованию здесь, так что не забудьте проверить и это.

Кроме того, если вы хотите копнуть еще глубже, вы можете проверить sigstore the hard way, который представляет собой руководство по настройке всего с нуля, включая fulcio CA и rekor сервер журнала прозрачности.

Эта статья изначально была размещена на martinheinz.dev