NuGet

パッケージマネージャー.NETC#Visual StudiodotnetCLIPackageReferenceセキュリティ監査

パッケージマネージャー

NuGet

概要

NuGetは、.NETエコシステムの公式パッケージマネージャーで、.NET開発者がライブラリの共有・利用を効率化するためのツールです。Visual Studioとdotnet CLIに完全統合され、PackageReference形式による現代的な依存関係管理、中央パッケージ管理(CPM)、グローバルパッケージフォルダによる効率的なストレージを提供します。2024年リリースのNuGet 6.8以降では、NuGetAudit機能による脆弱性検出、セキュリティ強化、HTTPS接続の徹底などが実装され、より安全で信頼性の高い.NET開発環境を実現しています。

詳細

NuGetは2010年にMicrosoftによって開発され、.NETエコシステムの標準パッケージマネージャーとして確立されました。従来のpackages.config形式からPackageReference形式への移行により、MSBuildとの統合が深化し、依存関係の管理がプロジェクトファイル内で直接行えるようになりました。NuGet 6.8以降では、NuGetAudit機能により既知の脆弱性を持つパッケージを自動検出し、開発者に警告を表示します。中央パッケージ管理(CPM)機能により、大規模プロジェクトでのバージョン統一と推移的依存関係のセキュリティ管理が可能になりました。Visual Studio、Visual Studio Code、dotnet CLIとの完全統合により、GUI・CLIの両方からシームレスなパッケージ操作を実現しています。

メリット・デメリット

メリット

  • Visual Studio完全統合: GUI・CLIの両方から統一された操作体験
  • PackageReference形式: プロジェクトファイル内での直接依存関係管理
  • 自動復元: ビルド時の自動パッケージ復元で手動操作不要
  • 脆弱性検出: NuGetAudit機能による自動セキュリティ監査
  • 中央パッケージ管理: 大規模プロジェクトでのバージョン統一管理
  • グローバルキャッシュ: Global Packages Folderによる効率的なストレージ
  • 豊富なエコシステム: NuGet.orgを中心とした膨大なパッケージライブラリ

デメリット

  • Windows依存: 主にWindows/.NET環境向けに最適化
  • 学習コスト: PackageReference移行時の概念理解が必要
  • バージョン競合: 複雑な依存関係での競合解決の困難さ
  • パフォーマンス: 大量パッケージでの復元時間の増加
  • セキュリティリスク: サードパーティパッケージの脆弱性リスク
  • ネットワーク依存: オンラインパッケージソースへの依存

参考ページ

書き方の例

基本的なパッケージ管理

# .NET CLIでのパッケージ操作
dotnet add package Newtonsoft.Json
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package AutoMapper

# バージョン指定でのインストール
dotnet add package Serilog --version 3.1.1
dotnet add package Microsoft.Extensions.Logging --version 8.0.0

# パッケージの削除
dotnet remove package Newtonsoft.Json

# パッケージ復元
dotnet restore

# パッケージ一覧表示
dotnet list package
dotnet list package --outdated
dotnet list package --vulnerable

PackageReference(プロジェクトファイル)設定

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
    <PackageReference Include="AutoMapper" Version="12.0.1" />
    <PackageReference Include="Serilog" Version="3.1.1" />
    <PackageReference Include="FluentValidation" Version="11.9.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <!-- 開発用パッケージ -->
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="xunit" Version="2.6.6" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

中央パッケージ管理(CPM)設定

<!-- Directory.Packages.props -->
<Project>
  
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
    <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
  </PropertyGroup>

  <ItemGroup>
    <!-- 中央でバージョン管理 -->
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
    <PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
    <PackageVersion Include="AutoMapper" Version="12.0.1" />
    <PackageVersion Include="Serilog" Version="3.1.1" />
    <PackageVersion Include="FluentValidation" Version="11.9.0" />
    
    <!-- テスト用パッケージ -->
    <PackageVersion Include="xunit" Version="2.6.6" />
    <PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
  </ItemGroup>

</Project>
<!-- プロジェクトファイル(CPM使用時) -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <!-- バージョンは Directory.Packages.props で管理 -->
    <PackageReference Include="Newtonsoft.Json" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" />
    <PackageReference Include="AutoMapper" />
    <PackageReference Include="Serilog" />
  </ItemGroup>

</Project>

セキュリティ監査とNuGetAudit

# 脆弱性スキャン
dotnet list package --vulnerable
dotnet list package --vulnerable --include-transitive

# セキュリティ監査レポート
dotnet restore --verbosity normal  # 復元時に自動監査

# 特定の脆弱性の詳細確認
dotnet list package --vulnerable --source nuget.org
<!-- NuGetAudit設定 -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <!-- 監査レベル設定 -->
    <NuGetAudit>true</NuGetAudit>
    <NuGetAuditMode>all</NuGetAuditMode>
    <NuGetAuditLevel>low</NuGetAuditLevel>
    
    <!-- 警告をエラーとして扱う -->
    <WarningsAsErrors />
    <WarningsNotAsErrors>NU1901;NU1902;NU1903;NU1904</WarningsNotAsErrors>
  </PropertyGroup>

</Project>

パッケージソース設定

<!-- nuget.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="MyGet V3" value="https://www.myget.org/F/my-feed/api/v3/index.json" />
    <add key="Private Feed" value="https://pkgs.dev.azure.com/myorg/_packaging/my-feed/nuget/v3/index.json" />
  </packageSources>
  
  <packageSourceMapping>
    <packageSource key="nuget.org">
      <package pattern="*" />
    </packageSource>
    <packageSource key="Private Feed">
      <package pattern="MyCompany.*" />
      <package pattern="Internal.*" />
    </packageSource>
  </packageSourceMapping>

  <packageSourceCredentials>
    <Private_Feed>
      <add key="Username" value="[TOKEN]" />
      <add key="ClearTextPassword" value="[PERSONAL_ACCESS_TOKEN]" />
    </Private_Feed>
  </packageSourceCredentials>

  <config>
    <add key="globalPackagesFolder" value="C:\nuget\packages" />
    <add key="repositoryPath" value="packages" />
    <add key="defaultPushSource" value="https://api.nuget.org/v3/index.json" />
  </config>

</configuration>

パッケージ作成と公開

# パッケージ作成
dotnet pack --configuration Release

# 特定の出力ディレクトリ
dotnet pack --output ./nupkgs

# バージョン指定
dotnet pack -p:PackageVersion=1.2.3

# NuGet.orgへの公開
dotnet nuget push MyPackage.1.0.0.nupkg --api-key [API_KEY] --source https://api.nuget.org/v3/index.json

# プライベートフィードへの公開
dotnet nuget push MyPackage.1.0.0.nupkg --source "Private Feed"
<!-- パッケージメタデータ設定 -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    
    <!-- パッケージ情報 -->
    <PackageId>MyCompany.MyLibrary</PackageId>
    <PackageVersion>1.2.3</PackageVersion>
    <Authors>My Company</Authors>
    <Company>My Company Inc.</Company>
    <Product>My Library</Product>
    <Description>A useful library for .NET development</Description>
    <PackageTags>utility;helper;dotnet</PackageTags>
    <PackageProjectUrl>https://github.com/mycompany/mylibrary</PackageProjectUrl>
    <RepositoryUrl>https://github.com/mycompany/mylibrary</RepositoryUrl>
    <RepositoryType>git</RepositoryType>
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
    
    <!-- パッケージング設定 -->
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
  </PropertyGroup>

</Project>

高度な設定とトラブルシューティング

# キャッシュクリア
dotnet nuget locals all --clear
dotnet nuget locals http-cache --clear
dotnet nuget locals global-packages --clear

# 詳細ログ出力
dotnet restore --verbosity detailed
dotnet restore --no-cache

# オフライン復元
dotnet restore --source ./packages --source https://api.nuget.org/v3/index.json

# 複数ターゲットフレームワーク
dotnet restore --framework net8.0
dotnet restore --framework net48

# パッケージ依存関係の表示
dotnet list package --include-transitive
dotnet list package --framework net8.0

Visual Studio統合

// PackageReference使用例
using Newtonsoft.Json;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
using Serilog;

public class ExampleService
{
    private readonly ILogger _logger;
    private readonly IMapper _mapper;

    public ExampleService(IMapper mapper)
    {
        _logger = Log.ForContext<ExampleService>();
        _mapper = mapper;
    }

    public async Task<string> ProcessDataAsync(object data)
    {
        _logger.Information("Processing data: {@Data}", data);
        
        // Newtonsoft.Json使用
        var jsonData = JsonConvert.SerializeObject(data);
        
        // AutoMapper使用
        var mappedData = _mapper.Map<TargetType>(data);
        
        return jsonData;
    }
}