ASP.NET Core でのキー ストレージ プロバイダー
データ保護システムでは、暗号化キーを永続化する必要がある場所を決定するために、既定で検出メカニズムが使用されます。 開発者は、既定の検出メカニズムをオーバーライドし、手動で場所を指定できます。
警告
明示的なキー永続化の場所を指定した場合、データ保護システムでは rest メカニズムにおける既定のキー暗号化が登録解除されるため、キーは rest で暗号化されなくなります。 運用展開のためには、追加で明示的なキー暗号化メカニズムを指定することをお勧めします。
ファイル システム
ファイル システム ベースのキー リポジトリを構成するには、次に示すように PersistKeysToFileSystem 構成ルーチンを呼び出します。 キーを格納する必要があるリポジトリを指し示す DirectoryInfo を指定します。
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys\"));
}
DirectoryInfo
を使用すると、ローカル マシンのディレクトリを指し示すことも、ネットワーク共有上のフォルダーを指し示すこともできます。 ローカル コンピューター上のディレクトリをポイントする場合 (そしてローカル コンピューター上のアプリだけがこのリポジトリを使用するためのアクセスを必要とするというシナリオで) は、(Windows 上で) Windows DPAPI を使用して、保存時のキーを暗号化することを検討してください。 それ以外の場合は、X.509 証明書を使用して保存時のキーを暗号化することを検討してください。
Azure Storage
Azure.Extensions.AspNetCore.DataProtection.Blobs パッケージを使用すると、Azure Blob Storage にデータ保護キーを格納できます。 キーは、Web アプリの複数のインスタンス間で共有できます。 アプリは、複数のサーバー間で認証 Cookie や CSRF 保護を共有できます。
Azure Blob Storage プロバイダーを構成するには、いずれかの PersistKeysToAzureBlobStorage オーバーロードを呼び出します。
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("<blob URI including SAS token>"));
}
Web アプリが Azure サービスとして実行されている場合は、Azure.Storage.Blobs の利用によって接続文字列を使用して、Azure ストレージに対する認証を行うことができます。
警告
この記事では、接続文字列の使用方法について説明します。 ローカル データベースでは、ユーザーを認証する必要はありませんが、運用環境では、接続文字列認証用のパスワードが含まれる場合があります。 リソース所有者パスワード資格情報 (ROPC) は、運用データベースで回避する必要があるセキュリティ リスクです。 運用アプリでは、使用可能な最も安全な認証フローを使用する必要があります。 テスト環境または運用環境にデプロイされたアプリの認証の詳細については、「 安全な認証フロー」を参照してください。
string connectionString = "<connection_string>";
string containerName = "my-key-container";
string blobName = "keys.xml";
BlobContainerClient container = new BlobContainerClient(connectionString, containerName);
// optional - provision the container automatically
await container.CreateIfNotExistsAsync();
BlobClient blobClient = container.GetBlobClient(blobName);
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(blobClient);
Note
ストレージ アカウントへの接続文字列は、Azure Portal の [アクセス キー] セクションで、または次の CLI コマンドを実行することによって確認できます。
az storage account show-connection-string --name <account_name> --resource-group <resource_group>
Redis
Microsoft.AspNetCore.DataProtection.StackExchangeRedis パッケージを使用すると、Redis キャッシュにデータ保護キーを格納できます。 キーは、Web アプリの複数のインスタンス間で共有できます。 アプリは、複数のサーバー間で認証 Cookie や CSRF 保護を共有できます。
Microsoft.AspNetCore.DataProtection.Redis パッケージを使用すると、Redis キャッシュにデータ保護キーを格納できます。 キーは、Web アプリの複数のインスタンス間で共有できます。 アプリは、複数のサーバー間で認証 Cookie や CSRF 保護を共有できます。
Redis に関する構成を行うには、いずれかの PersistKeysToStackExchangeRedis を呼び出します。
public void ConfigureServices(IServiceCollection services)
{
var redis = ConnectionMultiplexer.Connect("<URI>");
services.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
}
Redis に関する構成を行うには、いずれかの PersistKeysToRedis を呼び出します。
public void ConfigureServices(IServiceCollection services)
{
var redis = ConnectionMultiplexer.Connect("<URI>");
services.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys");
}
詳細については、次のトピックを参照してください。
Registry
Windows の展開にのみ適用されます。
アプリに、ファイル システムへの書き込みアクセスがない場合があります。 アプリが仮想サービス アカウント (w3wp.exe のアプリ プール identity など) として実行されているシナリオを考えてください。 このような場合、管理者は、サービス アカウント identity でアクセスできるレジストリ キーをプロビジョニングできます。 次に示すように、PersistKeysToRegistry 拡張メソッドを呼び出します。 暗号化キーを格納する必要がある場所を指し示す RegistryKey を指定します。
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Sample\keys", true));
}
重要
Windows DPAPI を使用して保存時にキーを暗号化することをお勧めします。
Entity Framework Core
The Microsoft.AspNetCore.DataProtection.EntityFrameworkCore パッケージでは、Entity Framework Core を使用してデータ保護キーをデータベースに格納するためのメカニズムが提供されます。 プロジェクト ファイルに Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
NuGet パッケージを追加する必要があります。これは Microsoft.AspNetCore.App メタパッケージの一部ではありません。
このパッケージを使用すると、Web アプリの複数のインスタンス間でキーを共有できます。
EF Core プロバイダーを構成するには、次のように PersistKeysToDbContext メソッドを呼び出します。
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
// Add a DbContext to store your Database Keys
services.AddDbContext<MyKeysContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyKeysConnection")));
// using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.PersistKeysToDbContext<MyKeysContext>();
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
コードのコメントを英語以外の言語に翻訳し表示したい場合、こちらの GitHub ディスカッション イシューにてお知らせください。
ジェネリック パラメーター TContext
は、DbContext から継承し、IDataProtectionKeyContext を実装する必要があります。
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;
namespace WebApp1
{
class MyKeysContext : DbContext, IDataProtectionKeyContext
{
// A recommended constructor overload when using EF Core
// with dependency injection.
public MyKeysContext(DbContextOptions<MyKeysContext> options)
: base(options) { }
// This maps to the table that stores keys.
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
}
DataProtectionKeys
テーブルを作成します。
パッケージ マネージャー コンソール (PMC) で以下のコマンドを実行します。
Add-Migration AddDataProtectionKeys -Context MyKeysContext
Update-Database -Context MyKeysContext
MyKeysContext
は、前出のコード サンプルで定義された DbContext
です。 別の名前で DbContext
を使用している場合は、MyKeysContext
の代わりに、お使いの DbContext
の名前を使用します。
DataProtectionKeys
クラス/エンティティには、次の表に示す構造が採用されています。
プロパティ/フィールド | CLR 型 | SQL 型 |
---|---|---|
Id |
int |
int 、PK、IDENTITY(1,1) 、NULL 以外 |
FriendlyName |
string |
nvarchar(MAX) 、NULL |
Xml |
string |
nvarchar(MAX) 、NULL |
カスタム キー リポジトリ
付属のメカニズムが適切でない場合には、カスタムの IXmlRepository を提供することで、開発者が独自のキー永続化メカニズムを指定できます。
ASP.NET Core