パッケージ ソース マッピング
パッケージ ソース マッピングは、特にパブリックとプライベートの両方のパッケージ ソースを使用する場合に、サプライ チェーンのセキュリティを向上させるために使用できるツールです。
既定では、NuGet はパッケージをダウンロードする必要があるときに、構成されているすべてのパッケージ ソースを検索します。 パッケージが複数のソースに存在する場合、どのソースからパッケージをダウンロードするかは決定論的でない可能性があります。 パッケージ ソース マッピングを使用すると、NuGet が検索するソースをパッケージごとにフィルター処理できます。
また、攻撃に対するサプライ チェーンの強化に役立つその他のベスト プラクティスに関する提案も用意されています。
パッケージ ソース マッピングは NuGet 6.0 で追加されました。 Visual Studio 17.5 以降では、Visual Studio の [オプション] ダイアログでパッケージ ソース マッピングを追加および削除できます。
Visual Studio のサポート
Visual Studio | パッケージ ソース マッピング | ツールのサポート - > オプション | パッケージ マネージャー UI でのサポート |
---|---|---|---|
17.0 - 17.4 | ✅ 対応可能 | ❌ 使用可能 | ❌ 使用可能 |
17.5 | ✅ 対応可能 | ✅ 対応可能 | ❌ 使用可能 |
17.7 Preview 3 | ✅ 対応可能 | ✅ 対応可能 | ✅ 状態が表示される |
この機能は、すべての NuGet 統合ツールで使用できます。
これらより前のツールでは、パッケージ ソース マッピング構成が無視されます。 この機能を使用するには、すべてのビルド環境で、互換性のあるツールのバージョンが使用されていることを確認してください。
パッケージ ソース マッピングは、互換性のあるツールが使用されている限り、すべてのプロジェクトの種類 (.NET Framework を含む) に適用されます。
ビデオ チュートリアル
パッケージ ソース マッピング機能のビデオベースの概要については、YouTube の パッケージ ソース マッピングを使った NuGet パッケージのセキュリティ保護のビデオをご覧ください。
パッケージ ソース マッピングの有効化
この機能を利用するには、nuget.config
ファイルを用意する必要があります。 リポジトリのルートに単一の nuget.config
を配置することがベスト プラクティスとされています。 詳細については、nuget.config に関するドキュメントを参照してください。
Visual Studio の [オプション] ダイアログを使用して有効にする
- Visual Studio でソリューションを開きます。
Package Source Mappings
の [オプション] ダイアログに 移動します。
パッケージ マネージャー UI から
- 一覧からパッケージを選択して、詳細ウィンドウに表示します。
Configure
ボタンを押して、パッケージ ソース マッピングのオプション ページを開きます。
Visual Studio の [オプション] ダイアログから
- メイン Visual Studio ツール バーの
Tools
メニューに移動し、NuGet Package Manager
->Package Manager Settings
を選択します。 Package Source Mappings
ページに移動します。
Package Source Mappings
ページ内のAdd
ボタンを押してAdd Package Source Mappings
ダイアログを開きます。
4. パッケージ ID またはパッケージ パターンを入力し、目的のソースのチェックボックスを切り替えて、1 つ以上のパッケージ ソースを選択します。
Package Source Mapping
のオプション ページには、新しく作成されたソース マッピングが表示されます。
- [オプション] ダイアログボックスの
OK
を押して、該当するnuget.config
の変更を保存します。 - NuGet パッケージ マネージャー ウィンドウが更新され、選択したパッケージのソース マッピングの新しい状態が反映されます。
nuget.config
を手動で編集して有効にする
nuget.config
ファイルで、対象のパッケージ ソースを宣言します。- ソース宣言の次に、
<packageSourceMapping>
要素を追加します。これにより、各ソースに必要なマッピングを指定します。 - 使用中のソースごとに厳密に 1 つの
packageSource
要素を宣言します。- 必要な数のパターンを追加します。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- Define the package sources, nuget.org and contoso.com. -->
<!-- `clear` ensures no additional sources are inherited from another config file. -->
<packageSources>
<clear />
<!-- `key` can be any identifier for your source. -->
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="contoso.com" value="https://contoso.com/packages/" />
</packageSources>
<!-- Define mappings by adding package patterns beneath the target source. -->
<!-- Contoso.* packages and NuGet.Common will be restored from contoso.com,
everything else from nuget.org. -->
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="contoso.com">
<package pattern="Contoso.*" />
<package pattern="NuGet.Common" />
</packageSource>
</packageSourceMapping>
</configuration>
さまざまなレベル (マシン レベル、ユーザー レベル、リポジトリ レベル) で複数の nuget.config
ファイルが存在する場合、パッケージ ソース マッピング設定は、nuget.config の優先順位規則に従って適用されます。
パッケージ ソース マッピング規則
NuGet で、最適な柔軟性と制御性を得るために、すべてのパッケージを、適切に定義された優先順位に従ってパッケージ パターンと一致させる必要があります。
パッケージ パターンの要件
要求されたすべてのパッケージを、定義済みのパッケージ パターンと一致させて 1 つ以上のソースにマップする必要があります。 つまり、packageSourceMapping
要素を定義したら、すべてのパッケージ (推移的なパッケージを含む) の復元元となるソースを明示的に定義する必要があります。
- 最上位および推移的なパッケージの両方を、定義済みのパターンと一致させる必要があります。 最上位パッケージとその依存関係は同じソースからのものでなければならない、という要件はありません。
- 同じ ID パターンを複数のソースに対して定義することで、そのパターンが定義されているいずれのフィードからも、一致したパッケージ ID を復元できます。 ただし、復元の予測可能性に影響があるため、この方法はお勧めしません (指定のパッケージが複数のソースから取得される可能性があります)。 各ソースをすべて信頼できる場合には、この方法が有効な構成である可能性があります。
パッケージ パターンの構文
パターン | 構文例 | 説明 |
---|---|---|
パッケージ プレフィックス パターン | * 、NuGet.* |
末尾を * にする必要があります。* は 0 個以上の文字と一致します。 * は、指定可能な最短のプレフィックス パターンで、すべてのパッケージ ID と一致します。 |
パッケージ ID パターン | NuGet.Common 、Contoso.Contracts |
完全一致のパッケージ ID。 |
パッケージ パターンの優先順位
パッケージ ID と一致する一意のパターンが複数ある場合は、最も具体的なパターンが優先されます。 パッケージ ID パターンは常に優先順位が最も高く、汎用的な *
は優先順位が最も低くなります。 パッケージ プレフィックス パターンの場合、最長のものが優先されます。
既定のソースの設定
*
パターンを使用すると、宣言を事実上の既定のソースとすることができます。これにより、指定されている他のパターンと一致しないパッケージは、エラーのスローなしでそのソースから復元されます。
この構成は、たとえば nuget.org
からのパッケージを主に使用し、内部パッケージは少ししかないか、すべての内部パッケージに対して標準プレフィックス (Contoso.*
など) を使用するような場合に便利です。
チームが、内部パッケージ ID に対して標準プレフィックスを使用しない場合、またはインストール前に nuget.org
パッケージを詳しく調査する場合は、プライベート ソースを既定にする方がニーズに合うでしょう。
Note
要求されたパッケージがグローバル パッケージ フォルダーに既に存在する場合、ソースの参照は行われず、マッピングは無視されます。 リポジトリのグローバル パッケージ フォルダーを宣言して、この機能のセキュリティ上のメリットを生かすことを検討してください。 次のイテレーションで、既定のグローバル パッケージ フォルダーを使用するエクスペリエンスを向上させる取り組みが予定されています。 パッケージのインストールが機能する仕組みの詳細については、概念ドキュメントを参照してください。
作業の開始
リポジトリを完全にオンボードするには、手動または NuGet.PackageSourceMapper ツールを使用する方法の 2 つあります。
手動オンボード
手動オンボードの場合は、次の手順を実行できます。
- 新しいリポジトリのグローバル パッケージ フォルダーを宣言します。
- dotnet restore を実行して依存関係を復元します。
dotnet list package --include-transitive
を実行して、ソリューション内のすべての最上位および推移的なパッケージを表示します。packages.config
を使用した .NET フレームワーク プロジェクトの場合、packages.config
ファイルに、すべての直接的および推移的なパッケージの単純なリストが含まれます。
- ソリューション内のすべてのパッケージ ID (推移的なパッケージを含む) がターゲット ソースのパターンと一致するように、マッピングを定義します。
- dotnet nuget locals global-packages -c を実行して、global-packages ディレクトリをクリアします。
- マッピングが正しく構成されていることを確認するために、復元を実行します。 マッピングによってソリューション内のすべてのパッケージ ID が完全に網羅されない場合は、問題を特定するのにエラー メッセージが役立ちます。
- 復元が成功したら、完了です。 必要に応じて次のことを検討します。
- 可能な場合に、より広範囲なパッケージ ID プレフィックスを使用するか、既定のソースを設定することで、宣言の数を減らして構成を簡略化する。
- グローバル パッケージ フォルダー内のメタデータ ファイルを確認するか、復元ログを確認することによって、各パッケージの復元元となったソースを確認する。
ツールを使用した自動オンボード
多くのリポジトリには多数のパッケージがあり、手動で作業を行うと時間がかかる場合があります。 NuGet.PackageSourceMapper ツールは、プロジェクトの既知のパッケージとソースに基づいて、自動的に NuGet.config を生成できます。
パッケージ ソース マッパー ツールでは、パッケージの復元が正常に完了している必要があります。ここでそれぞれのパッケージとソースをマップする方法を最もよく理解するために、ビルドの一部として生成された各 .nupkg.metadata
ファイルが読み取られます。 ツールでは、上位の依存関係だけでなく、マッピングの生成時にすべての推移的な依存関係も考慮されます。
ツールには、ニーズに応じてマッピング パターンを生成する方法がいくつか用意されています。詳細については、ブログの投稿とツールの readme の手順を確認してください。
ソース マッピングがどのように記述されるかについては、サンプルのリポジトリを参照してください。
Note
- パッケージ ソース マッピング構成を管理するための nuget.exe または dotnet.exe コマンドはありません。NuGet/Home#10735 を参照してください。
- パッケージのインストール時にパッケージをマッピングする手段はありません。NuGet/Home#10730 を参照してください。
DotNetCoreCLI@2
Azure Pipelines タスクを使う場合は制限があります。これは、ソース マッピング構成でfeed-
プレフィックスを使うことで回避できます。 ただし、認証が必要な場合はNuGetAuthenticate
を使い、スクリプト タスクから直接 dotnet cli を呼び出すことをお勧めします。 microsoft/azure-pipelines-tasks#15542 を参照してください。