Прочитать о сертификатах (Code signing) можно тут.
На Хабре уже рассказывалось о бесплатной (уже давно не бесплатной) возможности подписать свои открытые проекты: https://habr.com/ru/articles/242267/.
Компания SignPath GmbH предлагает бесплатную сертификацию проектов с открытым исходным кодом (https://about.signpath.io/product/open-source). Есть возможность подписывать как исполняемые файлы Windows, так и контейнеры Docker. Сборка проекта должна выполняться с помощью GitHub Actions. Вся документация доступна по адресу https://about.signpath.io/documentation/getting-started.
Я прошёл этот путь и вот как это было.
Проект
О своём проекте я уже немного рассказывал на Хабре.
Весь код написан на Python с использованием PySide6 и другими пакетами. Для сборки под Windows используется PyInstaller и Nuitka (с Nuitka работает быстрее, но иногда бывают странные ошибки, поэтому пока не отказался от PyInstaller), а инсталляционный пакет собирается с помощью Inno Setup. Весь процесс сборки настроен на GitHub Actions.
При запуске инсталлятора или приложения Windows выдает всем знакомое предупреждение:
Чтобы избавится от него, исполняемый файл должен быть подписан доверенным сертификатом разработчика. Большинство сертификационных центров требуют оплату, но есть вариант получить подпись бесплатно.
Регистрация
Для того чтобы получить бесплатный сертификат необходимо отправить запрос на почту oss-support@signpath.org. Я написал буквально пару предложений с описанием и ссылкой на проект.
Через пару дней пришла форма в файле Excel. Её нужно заполнить и отправить обратно. Самым интересным был пункт Репутация:
Опишите, как мы можем проверить, что ваш проект используется и заслуживает доверия.
Предоставьте источники и ссылки, включая
* Обзоры в СМИ
* Статьи в блогах
* Статьи Википедии на других языках (см. ниже для английского), Softpedia и т. д.
* Данные об использовании, такие как количество загрузок, форков или зависимостей
* Аналитика, такая как GitHub Insights
* Доказательство права собственности на товарный знак, если вы используете зарегистрированное название
Если доступно, мы также рассмотрим статью в Википедии на английском языке и OpenHub, а также данные сообщества, такие как GitHub Insights.
Спустя 2 недели проект был зарегистрирован о чем пришло два письма с уведомлениями о привязке почты и регистрации организации. Получив подтверждение регистрации не спешите подтверждать, видимо какие-то проблемы с синхрониpацией, мне удалось попасть в аккаунт только часов через 8 причём через Google аккаунт моей почты.
Никакой идентификации личности, проверки банковских карт не проводится.
SignPath предоставляет два сертификата: тестовый и сертификат выпуска (release sertificate). Тестовый сертификат (само-подписанный и не является доверенным) предназначен для настройки инфраструктуры и дальнейшего использования для тестовых сборок. Сертификат выпуска при регистрации не активен - имеет статус CSR PENDING. Для его активации необходимо выполнить настройку сборки проекта с тестовым сертификатом и дождаться "завершения внутреннего аудита безопасности" (в чем он заключается осталось загадкой).
Настройка GitHub Actions
Подписывать артефакты проекта можно как вручную загружая через сайт (доступно только для тестового сертификата), так и интегрировав процесс подписания в CI, например GitHub Actions или AppVeyor.
В этом разделе для большей наглядности я приведу пример для простого гипотетического приложения, собирающегося скриптом build.bat и состоящего из единственного исполняемого exe-файла. Конфигурация процесса сборки, перед добавлением шагов подписи, будет выглядеть следующим образом:
on: # Запускать процесс сборки при каждом выполнении git push
push:
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build
run: build.bat # Запуск скрипта сборки
- name: Upload artifact
id: build # Этот ID будет использоваться на шаге подписания
uses: actions/upload-artifact@v4
with:
name: my_program
path: my_program.exe # Путь и имя файла - результат сборки
Для интеграции с GitHub Actions необходимо получить API токен для CI. Для этого на странице Users and Groups необходимо выбрать пользователя CI builds и сгенерировать токен. Полученный токен добавляем в секреты репозитория GitHub как SIGNPATH_API_TOKEN
(Settings - Secrets and variables - Actions - Repository secrets).
Так же для настройки сборки на сайте SignPath необходимо найти Organization ID (на странице организации), Project slug (на странице проекта, по умолчанию совпадает с названием проекта) и Signing policy (на странице проекта, по умолчанию test-signing и release-signing).
Отправить файл на сертификацию можно только из артефактов сборки (в примере выполняется на шаге Upload artifact). Артефакты GitHub загружаются в zip-архиве, а SignPath, по умолчанию, работает только с исполняемыми файлами. Поэтому необходимо добавить конфигурацию описывающую артефакт. В приведенном примере артефакт состоит из zip-архива, содержащего единственный exe-файл. Чтобы добавить конфигурацию артефакта необходимо на странице проекта в разделе Artifact Configurations нажать кнопку Add. На открывшейся странице ввести название новой конфигурации (в примере это test-zip), у поля Artifact configuration нажать кнопку Customize или выбрать Zip archive + sign nested files и ввести следующую конфигурацию:
<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1">
<!-- Define that the uploaded artifact is a ZIP file -->
<zip-file>
<pe-file-set>
<!-- Inside this uploaded ZIP file sign three PE files with Authenticode
(PE = Portable Executable, e.g., .exe or .dll file) -->
<include path="*.exe" />
<for-each>
<authenticode-sign />
</for-each>
</pe-file-set>
</zip-file>
</artifact-configuration>
SignPath позволяет подписывать и внутренности MSI-пакетов, достаточно описать структуру пакета в конфигурации артефакта.
После этого нужно добавить шаг подписания в процесс сборки со следующим действием (action) https://github.com/SignPath/github-action-submit-signing-request:
- name: Signing
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '3b087850-3844-4d25-8407-cf81e731f8d1'
project-slug: 'open-numismat'
signing-policy-slug: 'test-signing'
artifact-configuration-slug: 'test-zip'
github-artifact-id: '${{steps.upload.outputs.artifact-id}}'
output-artifact-directory: . # Результат заменит исходный файл
wait-for-completion: true
Этот шаг должен выполняться после шага с выгрузкой артефакта - Upload artifact в нашем примере.
Это действие отправляет артефакт в SignPath где он подписывается и результат загружается обратно. Есть ограничение на загрузку артефактов на проверку - 4Гб в месяц. Обратите внимание, что в SignPath отправляется zip-архив, а когда результат скачивается обратно он распаковывается автоматически по указанному в output-artifact-directory
пути.
После шага подписи полученный подписанный файл вновь загружаем в артефакты:
- name: Upload signed
uses: actions/upload-artifact@v4
with:
name: my_program-signed
path: my_program.exe
Далее следующими шагами артефакты можно загрузить в релиз.
Получившаяся минимальная конфигурация процесса сборки будет выглядеть так:
on: # Запускать процесс сборки при каждом выполнении git push
push:
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build
run: build.bat # Запуск скрипта сборки
- name: Upload artifact
id: build # Этот ID используется на шаге Signing
uses: actions/upload-artifact@v4
with:
name: my_program
path: my_program.exe # Путь и имя файла - результат сборки
- name: Signing
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '3b087850-3844-4d25-8407-cf81e731f8d1'
project-slug: 'open-numismat'
signing-policy-slug: 'test-signing'
artifact-configuration-slug: 'test-zip'
github-artifact-id: '${{steps.upload.outputs.artifact-id}}'
output-artifact-directory: . # Результат заменит исходный файл
wait-for-completion: true
- name: Upload signed
uses: actions/upload-artifact@v4
with:
name: my_program-signed
path: my_program.exe
Теперь можно запустить тестовую сборку (в данном случае запустится сразу после выполнения git push). В логе сборки процесс подписания тестовым сертификатом выглядит так:
Submitting the signing request to SignPath CI connector...
SignPath signing request has been successfully submitted
The signing request id is 29add6f6-d0c7-48c7-963d-3e1f7a8853c9
You can view the signing request here: https://app.signpath.io/Web/3b087850-3844-4d25-8407-cf81e731f8d1/SigningRequests/29add6f6-d0c7-48c7-963d-3e1f7a8853c9
Checking the signing request status...
The signing request status is InProgress, which is not a final status; after a delay, we will check again...
Next check in a few seconds
Signing request status is Completed
Signed artifact url https://app.signpath.io/API/v1/3b087850-3844-4d25-8407-cf81e731f8d1/SigningRequests/29add6f6-d0c7-48c7-963d-3e1f7a8853c9/SignedArtifact
The signed artifact is being downloaded from SignPath and will be saved to D:\a\open-numismat\open-numismat\dist\OpenNumismat
Going to download signed artifact
The signed artifact has been successfully downloaded from SignPath and extracted to D:\a\open-numismat\open-numismat\dist\OpenNumismat
Поскольку я использую Nuitka и PyInstaller и упаковываю результат в zip-архив для портативной версии и в инсталлятор с помощью Inno Setup, то мой вариант несколько сложнее. Перед упаковкой Inno Setup отправляю основной exe-файл на сертификацию, после получения упаковываю в инсталлятор и отправляю получившийся инсталлятор на сертификацию еще раз.
Ошибки с которыми я столкнулся
Error: Could not authorize against SignPath API. Trusted build system cannot be used in conjunction with an interactive user.
или
Error: Only runners in the groups "GitHub Actions" are allowed.
Использован SignPath токен обычного пользователя (interactive user), а не пользователя CI.
Другая ошибка:
There is no signing policy with slug '<…>' in the project with slug '<…>'.
Неверные значения slug - вместо значения Signing policy указал Sertificate slug.
Error: The signing request is not completed. The final status is "Failed"
В случае этой ошибки искать причину нужно на сайте SignPath в разделе Signing Requests.
Сертификат выпуска
После того как все заработало с тестовым сертификатом я написал в поддержку, что у меня все работает и как бы мне получить доверенный сертификат выпуска. Через пару дней получил не очень внятный ответ: "Есть ли у вас в настоящее время на рассмотрении CSR? Если да, дайте нам ответ, чтобы мы могли заказать сертификат продукта". Написал подтверждение, что у меня уже есть сертификат выпуска в состоянии "CSR PENDING". На это получил ответ, что в течении недели я получу свой сертификат выпуска. И через пару часов получил письмо о том, что мой сертификат готов. Не могу сказать, что в этой процедуре было лишним, но в конечном итоге я увидел свой сертификат выпуска на сайте.
После этого обновил значение поле signing-policy-slug
в шаге Signing конфигурации процесса сборки и запустил сборку на GitHub.
Подпись сертификатом выпуска требует ручного подтверждения. Поэтому процесс сборки приостановится на шаге Signing, а в логе сборки появятся следующие строки:
Submitting the signing request to SignPath CI connector...
SignPath signing request has been successfully submitted
The signing request id is 220a33ea-9fc9-4b53-b3b4-2bc176b4e5e2
You can view the signing request here: https://app.signpath.io/Web/3b087850-3844-4d25-8407-cf81e731f8d1/SigningRequests/220a33ea-9fc9-4b53-b3b4-2bc176b4e5e2
Checking the signing request status...
The signing request status is InProgress, which is not a final status; after a delay, we will check again...
Next check in a few seconds
The signing request status is WaitingForApproval, which is not a final status; after a delay, we will check again...
Next check in a few seconds
The signing request status is WaitingForApproval, which is not a final status; after a delay, we will check again...
Next check in a minute
Для подтверждения необходимо перейти по ссылке из лога сборки или на странице Signing Requests найти ваш запрос со статусом Waiting for approval, щелкнуть по его ID:
нажать кнопку Approve. Через несколько секунд статус изменится на Completed:
После этого процесс сборки продолжится и в логе отобразится следующая строка:
Signing request status is Completed
Дальше процесс завершается и полученные подписанные артефакты загружаются в релиз проекта. После скачивания видно, что все что было указано подписано доверенной цифровой подписью:
Запуск приложения теперь происходит более приятным образом, без предупреждений о неизвестном издателе.
Получившаяся конфигурация процесса сборки доступна в репозитории проекта: https://github.com/OpenNumismat/open-numismat/blob/master/.github/workflows/release.yml.
Заключительные штрихи
В требованиях для открытых проектов (https://signpath.org/terms) указано, что на сайте программы необходимо указывать Code signing policy со следующей информацией:
Free code signing provided by SignPath.io, certificate by SignPath Foundation
Что и было сделано.
При активации сертификата выпуска была опубликована ссылка на мой проект на сайте SignPath https://signpath.org/projects - здесь я в приятной компании?
Надеюсь эта статья поможет и вам сделать мир свободных приложений более доступным и безопасным для широкого круга пользователей.
Комментарии (4)
9241304
11.10.2024 22:26Надеюсь эта статья поможет и вам сделать мир свободных приложений более доступным и безопасным для широкого круга пользователей.
Тут нет никакой связи. Они доступны в любом случае. И безопасность у них одинаковая, разница только в реакции так называемых антивирусов.
adeshere
Прошу прощения за дилетантский вопрос. Я тоже заинтересован в получении сертификата разработчика для своего проекта, но опасаюсь, что в моем случае это полностью нереально. Поэтому прежде, чем начинать курить эту тему, хотел бы получить советы (мнения) тех, кто уже прошел этот путь.
Вводная такая. Есть некоммерческий проект, очень похожий на опенсорс: рабочие сборки доступны для всех желающих, исходные коды формально открыты (все пользователи имеют к ним доступ). Документация тоже
общедоступна
Помимо объемной, на 500 страниц, справки, проект описан в нескольких рецензируемых публикациях (например 1, 2, 3), а еще есть десятки публикаций (причем не только моих), где описано его применение для обработки научных рядов
Но, выложено это все не на Гите, а на Я-диске. Продублировать все на Гит - не проблема (я просто не работал с ним никогда). Однако, там будет именно эхо-копия проекта, а не первооригинал, так как сейчас у меня есть налаженная система сборки, и менять ее не хочется
а в нее Гит не вписывается - он там просто не нужен
Более конкретно, сборка проекта у меня сейчас идет сугубо локально, под Виндой, в среде VS 2008. При этом требуется настройка кучи внутренних зависимостей. Переносимость организована так: на каждой машине настраивается логический диск O:\, туда кладется все дерево папок, и все эти пути явным образом прописаны в конфигах сборки. Это позволяет нам выполнять сборку проекта на разных машинах (дерево папок, включая и папку с настройками проектов, синхронизируется через Я-диск или как-то еще). Такая система у нас работает еще с 1990г. При этом разработчиков изначально было два с половиной человека (а сейчас и вообще полтора), поэтому никакой необходимости мерджить ветки или контролировать версии не возникает вообще. Все изменения всегда делаются только на мастер-машине с актуальной копией проекта. То есть, мастер-машины могут меняться, но мы всегда работаем с кодом строго поочередно.
Отсюда первый вопрос: я правильно понял, что для использования описанной в статье схемы сертификации сборка должна происходить непосредственно из репозитория Git? Онлайн-сборку мне наладить
почти нереально
Во-первых, я этого просто не умею, так как всегда все собирал локально, а Гитом не пользовался (когда он появился, у нас уже лет 15 как все работало, а как известно, "если работает-то не трогай").
Во-вторых, у меня проприетарный компилятор. Я вообще не уверен, что он может компилировать файлы, лежащие где-то в сети, и выкладывать туда результат. Но даже если это можно как-то настроить, то тогда появляется
В-третьих: у меня даже на локальном компе сборка занимает определенное время... а когда идет активная работа над проектом, то я порой делаю полную пересборку по несколько раз в день. И мне очень бы не хотелось, чтобы этот процесс как-то зависел от доступности онлайн-ресурсов, или просто тормозил из-за этого.
Ну и еще один нюанс: мой проект включает около 40 субпроектов, для каждого из которых есть свои настройки сборки, которые я иногда меняю. Сейчас они прописаны в vfproj-файлах VS 2008. А для онлайн-сборки все это надо будет прописать в батниках? В принципе, я умею копировать команды сборки из VS куда-то еще, но делать это регулярно (при каждом изменении любой настройки) и безошибочно - это точно не мой конек. А более новую VS (которая вроде бы уже что-то знает про Git) я так и не установил, т.к. не сумел справиться с известными ограничениями....
В общем, хочется сборку по-прежнему делать локально...
Ну и второй вопрос: проект у меня компилируется в примерно 40 exe-шников (их число понемногу растет, но не быстро). Конечно, стабильную сборку я делаю не каждый день, и ради этого я готов иногда сделать 40 "Signing" вручную. Но достаточно ли будет для этого получить сертификат один раз?
P.S. Проект у меня очень узконишевый и
некоммерческий
хотя я и занимаюсь его развитием на работе примерно 20% времени, а еще 60% моей работы состоит в использовании этих программ для решения разных научных задач
Поэтому платные или чересчур времязатратратные способы получения сертификата не рассматриваются вообще. Но некоторое количество активных пользователей проект имеет, и если бы я сумел облегчить им жизнь ценой нескольких дней борьбы, то было бы здорово...
9241304
Не гит, а гитхаб. Вам не нужен гит для версионирования, но при этом очень нужен сертификат разработчика?)
Зачем?
adeshere
Не гит, а гитхаб. Вам не нужен гит для версионирования,
Да, спасибо за уточнение. Я же говорю, что никогда гитхабом не пользовался, т.к. необходимости не было, и лишь очень примерно представляю себе общую идею (а в терминах путаюсь).
но при этом очень нужен сертификат разработчика?) Зачем?
Простите, я наверно был чересчур многословен, и причина моего вопроса при чтении поста ускользает. Я - автор большой самодельной программной системы, у которой есть определенное количество пользователей. Эта система регулярно (несколько раз в год) обновляется, после чего каждому пользователю приходится объяснять своей Винде, что он хочет запускать только что скачанные с моего Я-диска программы. Причем, их там целая куча (в пакете - 40 exe-шников, которые все время вызывают друг друга), поэтому обычный способ "нажал-подтвердил" не очень удобен. Вдобавок у нас есть одна особенность архитектуры: взаимодействие всех программ координирует скрытый процесс (у него нет собственного окна, оно бы просто мешалось при работе, как мусор). Вероятно, поэтому некоторые версии 10-ки
точнее, некоторые комбинации 10-ка + установленный поверх антивирус
тот же антивирус с другой сборкой 10-ки, а так же та же самая сборка, но с другим антивирусом - работали
вообще отказывались запускать программу без очень настойчивых танцев с бубном.
В общем, я всего лишь хочу упростить жизнь своим пользователям, чтобы собранные мной программы просто запускались и делали нужное юзеру дело без лишних вопросов. Мой собственный "статус разработчика" мне при этом до фени, естественно. Если этой цели можно добиться каким-то другим способом (применив какой-то не слишком заумный трюк на моей стороне) - расскажите, буду благодарен за советы.