Share via


NuGet サーバー 実装ガイド

場合によっては、独自の NuGet パッケージ フィードを実装する必要性が生じることがあります。 さまざまな方法で独自フィードのホスティングを可能にする実装が多く存在しますが、公式の NuGet クライアント ソフトウェアとパッケージ フィードの間のプロトコルはドキュメント化されているので、独自のフィード実装を最初から構築することも可能になっています。

プロトコルは時間の経過と同時に進化します。そして、このガイドは、NuGet パッケージ サーバーを実装したい、または既に実装しているユーザーを対象としたものです。

2015 年の NuGet V3 プロトコルの最初のリリース以降、NuGet は開発者に豊富なエクスペリエンスを提供するように進化してきました。つまり、ホストされたパッケージから単純にメタデータを取り出し、そのデータを各種形式で返すだけでなく、パッケージの コンシューマーに新たな価値を提供するための追加的な作業が、パッケージ リポジトリに要求されています。 たとえば、検索とパッケージのメタデータ エンドポイントには、nupkg の nuspec ファイルに記述されているメタデータ以上のものが含まれています。

V2 プロトコルは基本的に文書化されておらず、2015 年以降、NuGet クライアントとサーバーの通信プロトコルには V3 が推奨されているため、このガイドは NuGet V3 プロトコルに焦点を当てるものとなっていることにご注意ください。 詳細については、「プロトコルのバージョン管理」をご覧ください。

年表

既存の NuGet リポジトリの作成者が NuGet の機能を最新の状態に保てるようにするために、ドキュメントの残りで言及された関連機能を以下に時系列で示します。

Year 機能
2013 nuget.org でパッケージの所有者を管理する方法を説明するブログ投稿で、Web サイトに表示される所有者が新しいバージョンをアップロードするアクセス許可を持つアカウントであることが明示されており、そのため、パッケージ内の owners メタデータは無視されています
2017 verified 応答に SearchQueryService が追加されました。
セマンティック バージョニング 2.0.0 のサポート
2018 埋め込みライセンス
2019 埋め込みアイコン
RegistrationBaseUrl でのパッケージ非推奨化 (パッケージ メタデータ リソース)
2020 RegistrationsBaseUrl のパッケージについての脆弱性情報 (パッケージ メタデータ リソース)
SearchQueryService 要求に packageTypes クエリ パラメーターを追加
2021 埋め込み readme
2023 PreAuthenticate で認証された要求
VulnerabilityInfo リソース

オーナー フィールド

2 つのパッケージ マニフェスト ファイル (.nuspec) フィールド、<authors> および <owners> を考えてみます。 サード パーティのコンテンツをパッケージ化するパッケージ作成者は、多くの場合、<authors> フィールドにサード パーティの名前を配置します。 この <owners> フィールドは、パッケージをリポジトリに発行したユーザー、つまり、パッキングで問題や質問が発生した場合に連絡すべき相手を示すことを目的としています。

この点は 2013 年のブログ投稿で説明されているため、.nuspec ファイルでは <owners> フィールドが非推奨と見なされます。 このメタデータがパッケージのマニフェストに含まれている場合は、それを無視してください。 検索リソースまたはパッケージ メタデータ リソースの JSON 応答の、owners プロパティ内にある、.nuspec ファイルの <owners> フィールドの値は返さないでください。

リポジトリでパッケージごとのアクセス許可を使用している場合は、検索およびパッケージ メタデータ リソースの JSON 応答にある、owner メタデータで新しいバージョンを発行するアクセス許可を持つアカウントに、報告することをお勧めします。

verified 検索応答フィールド

新しいフィールド verifiedtrue に設定されている場合、Visual Studio の パッケージ マネージャー UI では、検索サービスの結果内にあるパッケージの横に青いチェックマークが表示されます。

NuGet.org では、パッケージ プレフィックス データ (NuGet API の一部ではなくサーバー側のデータ) でこのチェックマークを使用するため、パッケージを所有するアカウントがパッケージをアップロードしたときにのみ、ユーザーに対し表示されます。 たとえば、プレフィックス microsoft.* を持つパッケージは、そのパッケージが nuget.org 上の Microsoft アカウントによって所有されている場合にのみ検証されます。予約済みプレフィックスが実装される前の、microsoft. で始まるパッケージ ID を持つパッケージをアップロードしたユーザーには、この検証済みのチェックマークは提供されません。 NuGet.org では、排他的でないプレフィックスも許可されます。つまり、誰でも Contoso.ToolWithPlugins.Community.* の下のパッケージをアップロードできますが、検証済みのチェックマークは付与されません。

セマンティック バージョニング 2.0.0 のサポート

NuGet ではSystem.Version と セマンティック バージョン間のハイブリッドがサポートされていますが、セマンティック バージョニング 2.0.0 のサポートは 2017 年に追加されたものです。 そのため、3.6.0 より低いバージョンのクライアントにバージョンを返す NuGet API リソースは、セマンティック 2.0.0 機能を使用するパッケージを返すことはできません。これは、セマンティック バージョニング 1.0.0 とは互換性がないからです。

これら 2 つのバージョンにおける最も重要な違いは、プレリリース ラベルとメタデータ文字列です。 セマンティック バージョニング 1.0.0 の仕様では、プレリリース ラベルの一部としてのみ許可される文字のサンプル正規表現文字列として、[0-9A-Za-z-] を提供しており、メタデータ文字列はサポートしていません。 セマンティック バージョニング 2.0.0 仕様では、プレリリース識別子を . 文字で区切ることが許可 (および、先行ゼロを持つ数値識別子は禁止) され、加えて、+ に続くビルド メタデータを追加できます。

パッケージ メタデータ リソース (RegistrationsBaseUrl) の 3.6.0 より低いバージョンのリソースでは、.NET の System.Version またはセマンティック バージョニング 1.0.0 に準拠するパッケージのみを返す必要があります。 つまり、バージョンがセマンティック バージョニング 2.0.0 にのみ準拠しているパッケージは、これらのクライアント バージョンで認識することはできません。

同様に、検索クエリ サービス (SearchQueryService)オートコンプリート サービス (SearchAutocompleteService) が、&semVerLevel={version} クエリ パラメーターを追加しています。 semVerLevel が欠落している場合は、その値に 1.0.0 を想定します。 パッケージ メタデータ リソースと同様に、semVerLevel 値が 2.0.0 未満の場合には、セマンティック バージョニング 2.0.0 とのみ互換性があるバージョンのパッケージを返すことはできません。

埋め込みファイル

パッケージの アイコンライセンス、および Readme ファイルは、パッケージに埋め込むことができ (また、それが推奨され) ます 。 これらのファイルには、静的ファイル サーバーで抽出および配置された URL エンドポイント、あるいは、要求の .nupkg からファイルを動的に抽出する URL が必要です。これにより、nupkg 全体をダウンロードしなくてもこれらを表示できます。 パッケージ リポジトリで、パッケージの閲覧とパッケージの詳細の表示ができる場合は、前出のURL を使用して、Web サイトに埋め込まれたコンテンツを顧客に表示できます。

さらに、パッケージ メタデータ リソース検索リソースには、iconUrllicenseUrl でホストされた URL、および (または) JSON 応答の readmeUrl プロパティが含まれている必要があります。 パッケージ (.nupkg ファイル) を変更することはできません。クライアント機能 (ロック ファイルと署名済みパッケージ) が、その変更をパッケージが改ざんされたものとして検出するからです。

ライセンスは、SPDX 式または埋め込みファイルの (両方ではなく) どちらかの形を取ることに注意してください。 検索およびパッケージ メタデータの結果に出力されており、ライセンス式を使用しているパッケージには、ライセンス式 (エンコードされ https://licenses.nuget.org/ の末尾に追加された URL) に設定された licenseUrl を含むことができます。 たとえば、https://licenses.nuget.org/Apache-2.0 のようにします。 NuGet.org サーバー チームでは、他にも licenses.nuget.org に関するドキュメントを用意しています。

脆弱性と非推奨についての既知のデータ

パッケージ メタデータ リソース (RegistrationsBaseUrl)

パッケージ メタデータ リソースには、非推奨脆弱性の情報が含まれることがあります。 これにより、Visual Studio の パッケージ マネージャー ユーザー インターフェイス、または他の同等の IDE でパッケージを閲覧しているユーザーは、セキュリティまたはメンテナンスに関する重要な問題についての通知を受けられます。

パッケージ リポジトリが別のリポジトリからの "アップソーシング" パッケージである場合で、独自のフィードでパッケージをミラーリングするには、非推奨または脆弱性データがあるかを元のソースで定期的にチェックし、そのメタデータを独自のリポジトリに反映することをお勧めします。 特に、パッケージ リポジトリが nuget.org からアップソーシングされている場合は、最後にチェックした時点の状態 (カーソル) を維持することで、ミラーリングしているパッケージに更新があるかのチェックを Catalogリソースを使用して効率的に行えます。アップストリーム フィードから、パッケージ メタデータの多数の JSON ファイルをダウンロードする必要はありません。 使用の開始に役立つサンプル コードを記載した、カタログ リソースの使用に関するガイドが用意されています。

既知の脆弱性に関するデータベース (VulnerabilityInfo)

パッケージの復元中、脆弱性についてのハイ パフォーマンスなスキャンを実現するために、NuGet は VulnerabilityInfo リソースから 既知の脆弱性の完全なリストをダウンロードします。 Nuget.org は、GitHub でレビューされたすべてのアドバイザリについての脆弱性データを、GitHub アドバイザリ データベースから提供しています。これには、nuget.org でホストされていないパッケージも含まれています。

パッケージ リポジトリがファースト パーティ のパッケージをホストしていて、独自のフィードを使用して顧客に脆弱性情報を提供したいものの、まだパッケージの脆弱性が公開されていない場合には、空の JSON 配列 ([]) をコンテンツとする 1 つ以上の脆弱性ページを含む、脆弱性インデックスを指定する必要があります。

パッケージ リポジトリが (nuget.org ではなく) デフォルトのリポジトリとしてアプリによって使用されることを意図している場合は、nuget.org の脆弱性データを使用できます。 1 つのオプションは、サービス インデックスで nuget.org の脆弱性インデックス URL を使用することです。 別のオプションとしては、nuget.org の VulnerabilityInfo インデックスを定期的にチェックし、変更されたページをダウンロードしてローカルに反映することもできます。

packageTypes 検索クエリ

.NET CLI では、dotnet tool search コマンドを使用して .NET ツール パッケージを検索できます。 これは、パッケージの .nuspec ファイルの <packageTypes> フィールドから値を読み取る検索クエリ リソースに、&packageTypes={value} クエリ パラメーターを追加することによって実装されます。

認証されたフィードの URL 構造

NuGet API の概要」で説明されているように、すべての NuGet サーバー コミュニケーションを開始する URL はサービス インデックスです。 このドキュメントには、NuGet クライアントがクエリを実行する他のすべてのリソースの URL が記載されています。 NuGet 6.7 (Visual Studio MSBuild 17.7、および .NET SDK 7.0.400) の時点で、NuGet では .NET のHttpClientHandler.PreAuthenticate を使用しています。これは、認証された URL と以降に続く URL が同じ仮想ディレクトリ (またはサブディレクトリ) に存在する場合にのみ、匿名の HTTP 要求を防止します。 これは、サーバーに送信される非認証の 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) 名前があり、1 つ以上のエイリアスを持つと考えられます。 サービス インデックス要求が正規 URL 以外 ("フレンドリ" な名前、この例では feed) で認証された場合は「いいえ」です。正規 URL の下にあるリソースに対するすべての要求は、PreAuthenticate のための HttpClientHandler の規則と一致しません。 ただし、この非正規 URL が、正規 URL である https://pkgs.contoso.com/nuget/v3/{guid}/index.json への HTTP リダイレクトである場合、この URL は HttpClientHandler の資格証明キャッシュで使用されます。 この場合、リダイレクトが原因で、サービス インデックスに対するすべての要求に追加の待機時間が発生します。

NuGet の V3 API は静的ファイル サーバー上で動作するように設計されたものですが、検索リソースはその例外で、要求を処理するために常に動的 Web サービスを必要とします。 検索や (実際には) 他の NuGet API リソースをさまざまなサーバーでホストする場合で、HttpClientHandlerPreAuthenticate からのメリットを得るためには、リバース プロキシを使用して、サービス インデックス内のすべての顧客向け URL が、確実に「同じディレクトリまたはサブディレクトリ」でのルールを満たすようにする必要があります。