このガイドでは、EF Core プロバイダー を使用して、Queryable Encryption (QE) を使用して特定のドキュメント フィールドを暗号化する方法を学ぶことができます。
Overview
Queryable Encryption は、データを MongoDB に書き込む前に、機密なドキュメント フィールドをアプリケーション レイヤーで暗号化しますが、アプリケーションではこれらのフィールドをクエリできます。暗号化のキーにアクセスできるアプリケーションのみが、平文データを読み取ることができます。攻撃者がデータベースにアクセスした場合、暗号化のキーにアクセスできないため、暗号文のみを表示できます。
例えば、Queryable Encryption を使用して、次のようなフィールドを暗号化できます。
社会保障番号
クレジット カード番号
ヘルスまたは医療情報
金融情報
その他の機密情報または個人を特定できる情報
EF Core プロバイダーは、フルーエント モデル API を介して Queryable Encryption をサポートします。OnModelCreating() メソッドを使用して暗号化するエンティティ プロパティを設定します。プロバイダーは、データの読み書き時に自動的に暗号化を取り扱います。
前提条件
EF Core Provider を使用して Queryable Encryption を構成する前に、次のものがあることを確認してください。
MongoDB 7.0 以降を実行している MongoDB Enterprise または MongoDB Atlas クラスター。
Key Management Service (KMS) へのアクセス。サポートされている KMS プロバイダーには、Amazon Web Services、Azure、Google Cloud Platform、Key Management Interoperability Protocol (KMIP)、およびローカル キー プロバイダーがあります。
自動暗号化共有ライブラリ(
CRYPT_SHARED)または、環境にインストールされているmongocryptd。共有ライブラリのインストール方法については、MongoDB Server ドキュメントの「クエリ分析コンポーネントのインストール」を参照してください。
Queryable Encryption の有効化
次のセクションでは、コンテキストで暗号化オプションを構成し、モデルで暗号化するエンティティプロパティをマークする方法を説明します。
暗号化オプションの構成
Queryable Encryption を使用するコンテキストを構成する前に、次のコードを実行して、アプリケーションの自動暗号化プロバイダーを 1 度登録する必要があります。
MongoClientSettings.Extensions.AddAutoEncryption();
次に、MongoOptionsExtension インスタンスを作成し、インスタンスを UseMongoDB() メソッドに渡す前に次のメソッドをチェーンします。
WithKmsProviders()— KMS プロバイダーと認証情報を指定します。WithKeyVaultNamespace()— データ暗号化キーの保存に使用されるコレクションを指定します。WithCryptProvider()— 使用する暗号化ライブラリとそのパスを指定します。
次の例は、開発用のローカル KMS プロバイダーを構成します。
var kmsProviders = new Dictionary< string, IReadOnlyDictionary<string, object>> { { "local", new Dictionary<string, object> { { "key", localMasterKey } } } }; var keyVaultNamespace = CollectionNamespace.FromFullName( "encryption.__keyVault"); var mongoOptions = new MongoOptionsExtension() .WithConnectionString(connectionString) .WithDatabaseName("myDatabase") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")); var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoOptions);
共有ライブラリの代わりに mongocryptd を使用するには、CryptProvider.Mongocryptd と mongocryptd バイナリへのパスを WithCryptProvider() メソッドに渡します。
警告
本番環境ではローカル KMS プロバイダーを使用しないでください。リモート KMS がない場合、マスター キーへの不正なアクセス、またはデータの復号化に必要なキーの永久的な損失のリスクがあります。
暗号化するフィールドをマークする
OnModelCreating() メソッドでは、暗号化する各プロパティで暗号化メソッドを呼び出します。選択したメソッドにより、そのフィールドで使用できるクエリの種類が制御されます。
方式 | クエリ サポート | ノート |
|---|---|---|
| なし | クエリサポートなしでフィールドを暗号化します。保存しているが、直接フィルターしないフィールドに使用します。 |
| 等式 ( |
|
| 範囲 ( |
|
スカラープロパティではなく、所有するエンティティを暗号化するには、OwnsOne()またはOwnsMany()から返されるOwnedNavigationBuilderまたはOwnershipBuilderでIsEncrypted(dataKeyId)を呼び出します。
前述のメソッドを使用する完全な例については、「例: 患者データの暗号化」セクションを参照してください。
例: 患者データの暗号化
次の Patient エンティティは、SSN フィールドと DateOfBirth フィールドを暗号化する document model を定義します。
public class Patient { public ObjectId Id { get; set; } public string Name { get; set; } = null!; public string SSN { get; set; } = null!; public DateTime DateOfBirth { get; set; } }
次の HospitalContext は、OnModelCreating() メソッドで暗号化するフィールドをマークします。SSN はクエリサポートなしで暗号化され、DateOfBirth は範囲クエリサポートで暗号化されます。コンテキストを初期化する前にキーボルトで作成した 2 つのデータ暗号化キーの ID をコンストラクタで受け取ります。
public class HospitalContext : DbContext { public DbSet<Patient> Patients { get; set; } = null!; private readonly Guid _ssnDataKeyId; private readonly Guid _dobDataKeyId; public HospitalContext( DbContextOptions options, Guid ssnDataKeyId, Guid dobDataKeyId) : base(options) { _ssnDataKeyId = ssnDataKeyId; _dobDataKeyId = dobDataKeyId; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Patient>(entity => { entity.ToCollection("patients"); entity.Property(p => p.SSN) .IsEncrypted(_ssnDataKeyId); entity.Property(p => p.DateOfBirth) .IsEncryptedForRange( new DateTime(1900, 1, 1), new DateTime(2100, 12, 31), _dobDataKeyId); }); } }
次のコードは、暗号化オプションを構成し、データキー ID を持つ HospitalContext をインスタンス化し、Patient ドキュメントを挿入してクエリを実行します。
var mongoOptions = new MongoOptionsExtension() .WithConnectionString("<connection string URI>") .WithDatabaseName("hospitalDb") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")); using var context = new HospitalContext( new DbContextOptionsBuilder<HospitalContext>() .UseMongoDB(mongoOptions) .Options, ssnDataKeyId, dobDataKeyId); context.Database.EnsureCreated(); context.Patients.Add(new Patient { Name = "John Doe", SSN = "123-45-6789", DateOfBirth = new DateTime(1985, 6, 15) }); context.SaveChanges(); var results = context.Patients .Where(p => p.DateOfBirth > new DateTime(1980, 1, 1)) .ToList();
サーバーサイド スキーマ サポート
デフォルトで、EF Core Provider はフィールド暗号化構成をクライアントにのみ適用します。クライアントのみの暗号化は、暗号化スキーマがまだ進化している可能性がある開発中に適しています。
本番環境に配置する場合は、コレクションを作成する際にサーバーに暗号化スキーマを登録します。サーバーがスキーマを保持すると、クライアントの構成に関わらずに暗号化が強制され、構成の誤ったクライアントからの意図せずの平文書き込みが防止されます。サーバーにスキーマを登録した後は、コレクションを再作成せずには暗号化されるフィールドを変更できません。
サーバー側スキーマを使用してコレクションを作成するには、コンテキストの Model を QueryableEncryptionSchemaGenerator.GenerateSchemas() に渡します。次に、次の例に示すように、結果を CreateCollection() メソッドに渡します。
var encryptedSchemas = QueryableEncryptionSchemaGenerator.GenerateSchemas( context.Model); using var client = new MongoClient( "<connection string URI>"); var database = client.GetDatabase("hospitalDb"); foreach (var entityType in context.Model .GetEntityTypes() .Where(e => e.IsDocumentRoot())) { var collectionName = entityType.GetCollectionName(); if (encryptedSchemas.TryGetValue( collectionName, out var schema)) { database.CreateCollection( collectionName, new CreateCollectionOptions { EncryptedFields = schema }); } } context.Database.EnsureCreated();
暗号化されたコレクションがサーバー上に存在すると、新しいコンテキストインスタンスをサーバースキーマのみを使用するように構成できます。次の例に示すように、MongoOptionsExtensionに QueryableEncryptionSchemaMode.Ignore を設定します。
var mongoOptions = new MongoOptionsExtension() .WithConnectionString("<connection string URI>") .WithDatabaseName("hospitalDb") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")) .WithQueryableEncryptionSchemaMode( QueryableEncryptionSchemaMode.Ignore);
Ignore モードでは、OnModelCreating() メソッドの IsEncrypted 構成は暗号化に影響しません。サーバー スキーマは、暗号化されるフィールドを制御します。
詳細情報
Queryable Encryptionの詳細については、MongoDB Server マニュアルの「Queryable Encryption」および「Queryable Encryption ユースケース」の項を参照してください。
実装の詳細については、EF Core Provider API ドキュメント を参照してください。