Руководство по реализации сервера NuGet

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

Протокол развивается с течением времени, и это руководство предназначено для тех, кто хочет или уже реализовал сервер пакетов NuGet.

С момента первоначального выпуска протокола NuGet версии 3 в 2015 году NuGet развивалась, чтобы предоставить разработчикам более широкий интерфейс, и это требует, чтобы репозитории пакетов выполнялись дополнительные действия, чтобы обеспечить дополнительную ценность для потребителей пакетов, помимо простой точной точности метаданных из размещенных пакетов и возврата метаданных в различных формах. Например, конечные точки поиска и метаданных пакета содержат больше, чем только метаданные, найденные в файле nuspec nupkg.

Обратите внимание, что это руководство сосредоточено на протоколе NuGet версии 3, так как протокол V2 по сути не выполняется и с 2015 года рекомендуемый протокол для взаимодействия с клиентом и сервером NuGet является протоколом V3. Дополнительные сведения о управление версиями протокола.

Хронология

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

Year Функция
2013 Запись блога, объясняющая, как управлять владельцами пакетов на nuget.org уточнили, что владельцы, отображаемые на веб-сайте, являются учетными записями, имеющими разрешение на отправку новых версий, и поэтому owners метаданные в пакете игнорируются.
2017 Добавлено verified в SearchQueryService ответы.
Поддержка семантического управления версиями 2.0.0
2018 Внедренные лицензии
2019 Внедренные значки
Прекращение использования RegistrationBaseUrl пакета (ресурс метаданных пакета)
2020 Сведения об уязвимостях пакета ( RegistrationsBaseUrl ресурс метаданных пакета)
packageTypes Добавлен параметр запроса для SearchQueryService запросов
2021 Внедренное чтение
2023 Запросы, прошедшие проверку подлинности предварительной проверки подлинности
VulnerabilityInfo Ресурсов

Поле владельца

Рассмотрим два поля файла манифеста пакета (.nuspec) и <owners>. <authors> Авторы пакетов, которые упаковывают стороннее содержимое, часто помещают в поле имя стороннего <authors> производителя. Поле <owners> предназначено для обозначения того, кто опубликовал пакет в репозитории, и поэтому кто должен обращаться в случае проблем упаковки или вопросов.

Это было описано в записи блога с 2013 года, поэтому <owners> поле считается устаревшим в .nuspec файле. Если манифест пакета содержит эти метаданные, его следует игнорировать. Не возвращайте значение .nuspec поля файла <owners> в свойстве owners в ответе JSON ресурса поиска или метаданных пакета.

Если у репозитория есть разрешения на пакет, рекомендуется сообщить учетным записям, имеющим разрешения на публикацию новых версий в owner метаданных для ответов JSON для поиска и ресурсов метаданных пакета.

verified Поле ответа поиска

В пользовательском интерфейсе visual Studio диспетчер пакетов отображается синий проверка марк рядом с пакетами в результатах службы поиска, когда для нового поля задано trueзначение verified .

NuGet.org использует это с данными префикса пакета (серверными данными, а не частью API NuGet), поэтому этот проверка mark отображается только клиентам, когда учетная запись, которая владеет пакетом, отправленным пакетом. Например, любой пакет с префиксом microsoft.* проверяется только в том случае, если пакет принадлежит учетной записи Майкрософт в nuget.org. Любой пользователь, отправивший пакет с идентификатором пакета, начиная с microsoft. предварительно зарезервированных префиксов, не будет иметь этот проверенный проверка mark. NuGet.org также позволяет префиксам не быть эксклюзивными, чтобы любой пользователь мог отправить пакет в Contoso.ToolWithPlugins.Community.*папку, но не получит проверенный проверка марк.

Поддержка семантического управления версиями 2.0.0

NuGet поддерживает гибридную версию между System.Version семантической версией и семантической версией, но в 2017 году добавлена поддержка семантической версии 2.0.0. Поэтому ресурсы API NuGet, возвращающие версии клиентским версиям ниже 3.6.0, не должны возвращать пакеты, использующие функции семантики 2.0.0.0, несовместимые с семантической версией 1.0.0.

Наиболее важными различиями между двумя версиями являются метки предварительного выпуска и строка метаданных. Семантическая спецификация versioning 1.0.0 предоставляет [0-9A-Za-z-] в качестве примера строку регулярного выражения для только символов, разрешенных в рамках метки предварительного выпуска, и не поддерживает строки метаданных. Спецификация "Семантическая версия 2.0.0 ", что позволяет разделять . идентификаторы предварительного выпуска символами (и запрещать числовый идентификатор с начальным нулем), а также позволяет добавлять метаданные сборки после значения +.

В ресурсе метаданных пакета (RegistrationsBaseUrl)версии ресурсов ниже 3.6.0 должны возвращать только пакеты, соответствующие требованиям. System.Version Net или семантическое управление версиями 1.0.0. Это означает, что пакеты, версии которых соответствуют только семантической версии версии 2.0.0, невидимы для этих клиентских версий.

Аналогичным образом, служба запросов поиска (SearchQueryService) и служба автозавершения (SearchAutocompleteService) добавили &semVerLevel={version} параметры запроса. Если semVerLevel отсутствует, предположим, что значение 1.0.0отсутствует. Как и ресурс метаданных пакета, пакеты, версия которых совместима только с семантической версией 2.0.0.0, не должны быть возвращены, если semVerLevel значение ниже 2.0.0.

Внедренные файлы

Значки пакетов, лицензии и файлы readme могут быть внедрены (и рекомендуется) в пакет. Эти файлы нуждаются в конечной точке URL-адреса, извлеченной и помещенной на статический файловый сервер, или URL-адрес, который динамически извлекает файлы из .nupkg запроса, чтобы их можно было просматривать без скачивания всего nupkg. Если репозиторий пакетов предоставляет сведения о пакете и просмотр сведений о пакете, вы можете использовать URL-адреса, чтобы показать клиентам внедренное содержимое на веб-сайте.

Наконец, ресурс метаданных пакета и ресурс поиска должен содержать размещенный URL-адрес в iconUrllicenseUrlreadmeUrl свойствах ответа JSON. Пакеты (.nupkg файлы) не должны быть изменены, так как клиентские функции (файлы блокировки и подписанные пакеты) будут обнаруживать изменения, так как пакет был изменен.

Обратите внимание, что лицензия может быть выражением SPDX или внедренным файлом (но не обоими). Пакеты, использующие выражение лицензии, если они представлены в результатах поиска и метаданных пакета, могут иметь licenseUrl набор для выражения лицензии, URL-адреса, закодированного и добавленного в конец https://licenses.nuget.org/. Например, https://licenses.nuget.org/Apache-2.0. Команда сервера NuGet.org имеет дополнительную документацию по licenses.nuget.org.

Известные данные об уязвимостях и устаревших данных

Ресурс метаданных пакета (RegistrationsBaseUrl)

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

Если репозиторий пакетов является "up-sourcing" пакеты из другого репозитория, чтобы зеркало пакеты в собственном веб-канале, рекомендуется периодически проверка исходного источника, если есть устаревшие или данные уязвимостей, и зеркало эти метаданные в собственном репозитории. Если репозиторий пакетов работает с nuget.org в частности, сохраняя состояние последнего проверка (курсора), можно использовать Catalog ресурс для эффективного проверка, если есть какие-либо обновления пакетов для пакетов, которые вы зеркало, не загружая большое количество JSON-файлов метаданных пакета из веб-канала вышестоящий. Существует руководство по использованию ресурса каталога с примером кода, который поможет вам приступить к работе.

Известные уязвимости базы данных (VulnerabilityInfo)

Чтобы обеспечить высокопроизводительную проверку уязвимостей во время восстановления пакета, NuGet скачивает полный список известных уязвимостей из VulnerabilityInfo ресурса. Nuget.org предоставляет данные об уязвимости для всех проверенных помощников GitHub из базы данных GitHub Advisories, которая включает пакеты, не размещенные в nuget.org.

Если репозиторий пакетов размещает сторонние пакеты и вы хотите предоставить клиентам информацию об уязвимостях с помощью собственного веб-канала, но у вас еще нет уязвимостей пакета, необходимо предоставить индекс уязвимостей с одной или несколькими страницами уязвимостей, содержимое которых является пустым массивом JSON ([]).

Если репозиторий пакетов предназначен для использования приложениями в качестве репозитория по умолчанию (вместо nuget.org), можно использовать данные об уязвимостях nuget.org. Один из вариантов — использовать URL-адрес индекса уязвимостей nuget.org в индексе службы. Другой вариант — периодически проверка индекс nuget.org VulnerabilityInfo и скачать все измененные страницы в зеркало локально.

packageTypes поисковый запрос

Интерфейс командной dotnet tool search строки .NET позволяет выполнять поиск пакетов инструментов .NET с помощью команды. Это реализуется путем добавления &packageTypes={value} параметра запроса в ресурс поискового запроса, который считывает значения из поля файла <packageTypes> пакета.nuspec.

Структура URL-адресов для проверенных веб-каналов

Как описано в обзоре API NuGet, начальный URL-адрес для всех подключений к серверу NuGet является индексом службы. Этот документ содержит URL-адреса для всех остальных ресурсов, которые клиенты NuGet запрашивают. Начиная с NuGet 6.7 (Visual Studio и MSBuild 17.7 и пакета SDK для .NET 7.0.400), NuGet использует . HttpClientHandler.PreAuthenticateNET, который позволяет избежать анонимных HTTP-запросов, если последующие URL-адреса находятся в том же виртуальном каталоге или подкаталоге URL-адреса, который ранее прошел проверку подлинности. Это значительно уменьшит количество неавторизованных HTTP-запросов, отправленных на сервер, и, следовательно, уменьшит рабочую нагрузку сервера.

Далее приводятся некоторые примеры.

URL Будет ли preAuthenticate?
https://pkgs.contoso.com/nuget/v3/feed/index.json N/A— это индекс службы.
https://pkgs.contoso.com/nuget/v3/search Нет, а не в том же или вложенном каталоге, что и индекс службы.
https://search.pkgs.contoso.com/nuget/v3/feed/ Нет, а не в том же имени узла, что и индекс службы.
https://pkgs.contoso.com/nuget/v3/feed/search Да, в том же каталоге, что и индекс службы.
https://pkgs.contoso.com/nuget/v3/registration/ Нет, а не в подкаталоге индекса службы.
https://pkgs.contoso.com/nuget/v3/feed/registration/ Да, в подкаталоге индекса службы.
https://pkgs.contoso.com/nuget/v3/{guid}/registration/ См. ниже

В последнем примере сервер может иметь каноническое (в этом примере guid) имя и иметь один или несколько псевдонимов. Если запрос индекса службы прошел проверку подлинности по неканическому URL-адресу (понятное имя, в нашем примере feed), то никакие запросы к ресурсам в каноническом URL-адресе не будут соответствовать HttpClientHandlerправилам PreAuthenticate. Однако если не канонический URL-адрес является перенаправлением HTTP на канонический URL-адрес, https://pkgs.contoso.com/nuget/v3/{guid}/index.jsonэтот URL-адрес будет использоваться в HttpClientHandlerкэше учетных данных. В этом случае каждый запрос к индексу службы будет иметь дополнительную задержку из-за перенаправления.

Хотя API NuGet версии 3 был разработан для работы на статичном файловом сервере, ресурс поиска является исключением, которое всегда требует динамической веб-службы для обработки запросов. Если вы хотите разместить поиск или действительно любой другой ресурс API NuGet на разных серверах, чтобы воспользоваться преимуществамиHttpClientHandlerPreAuthenticate, необходимо использовать обратный прокси-сервер, чтобы убедиться, что все URL-адреса клиента в индексе службы соответствуют правилу "одинаковый или подкаталог".