最新の安定バージョンについては、Spring Data MongoDB 5.0.0 を使用してください! |
暗号化
クライアント側暗号化は、アプリケーション内のデータを MongoDB に送信する前に暗号化する機能です。Spring Data による暗号化の適用を続行する前に、理想的には MongoDB ドキュメント (英語) から概念を理解し、その機能と制限について詳しく学ぶことをお勧めします。
クライアント側の暗号化を使用するようにドライバー |
クライアント側フィールドレベルの暗号化 (CSFLE)
CSFLE を選択すると、完全な柔軟性が得られ、単一のフィールドに異なるキーを使用できるようになります (たとえば、テナントごとに 1 つのキーのシナリオなど)。
読み進める前に必ず MongoDB CSFLE ドキュメント (英語) を参照してください。
自動暗号化 (CSFLE)
MongoDB は、自動暗号化機能を備えた MongoDB ドライバーを使用して、すぐに使えるクライアント側のフィールドレベル暗号化 (英語) をサポートします。自動暗号化には、明示的な暗号化 / 復号化の手順を行わなくても、暗号化された読み取りおよび書き込み操作を実行できる JSON スキーマが必要です。
暗号化情報を保持する JSON スキーマの定義の詳細については、JSON スキーマセクションを参照してください。
MongoJsonSchema を利用するには、AutoEncryptionSettings と組み合わせる必要があります。MongoClientSettingsBuilderCustomizer 経由。
@Bean
MongoClientSettingsBuilderCustomizer customizer(MappingContext mappingContext) {
return (builder) -> {
// ... keyVaultCollection, kmsProvider, ...
MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext);
MongoJsonSchema patientSchema = schemaCreator
.filter(MongoJsonSchemaCreator.encryptedOnly())
.createSchemaFor(Patient.class);
AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultCollection)
.kmsProviders(kmsProviders)
.extraOptions(extraOpts)
.schemaMap(Collections.singletonMap("db.patient", patientSchema.schemaDocument().toBsonDocument()))
.build();
builder.autoEncryptionSettings(autoEncryptionSettings);
};
}明示的な暗号化 (CSFLE)
明示的な暗号化では、MongoDB ドライバーの暗号化ライブラリ (org.mongodb:mongodb-crypt) を使用して暗号化タスクと復号化タスクを実行します。@ExplicitEncrypted アノテーションは、JSON スキーマの作成とプロパティコンバーターに使用される @Encrypted アノテーションを組み合わせたものです。言い換えれば、@ExplicitEncrypted は既存のビルドブロックを使用して結合し、簡略化された明示的な暗号化サポートを実現します。
|
クライアント側のフィールドレベル暗号化を使用すると、決定的アルゴリズムとランダム化アルゴリズムのどちらかを選択できます。選択したアルゴリズム (英語) に応じて、異なる操作 (英語) がサポートされる場合があります。特定のアルゴリズムを選択するには、@ExplicitEncrypted(algorithm) を使用します。アルゴリズム定数については、EncryptionAlgorithms を参照してください。アルゴリズムとその使用箇所の詳細については、暗号化の種類 (英語) マニュアルを参照してください。
実際の暗号化を実行するには、データ暗号化キー (DEK) が必要です。キー管理の設定方法とデータ暗号化キーの作成方法の詳細については、MongoDB ドキュメント (英語) を参照してください。DEK は、id または定義された別名を介して直接参照できます。@EncryptedField アノテーションでは、代替名による DEK の参照のみが許可されます。後述する EncryptionKeyResolver を任意の DEK に提供することが可能です。
@EncryptedField(algorithm=…, altKeyName = "secret-key") (1)
String ssn;@EncryptedField(algorithm=…, altKeyName = "/name") (2)
String ssn;| 1 | 代替名 secret-key で保存された DEK を使用します。 |
| 2 | 実際のフィールド値を読み取り、それをキー検索に使用するフィールド参照を使用します。保存操作には常に完全なドキュメントが存在する必要があります。フィールドはクエリ / 集計では使用できません。 |
デフォルトでは、@ExplicitEncrypted(value= …) 属性は MongoEncryptionConverter を参照します。対応する型参照を提供することで、デフォルトの実装を変更し、任意の PropertyValueConverter 実装と交換することができます。カスタム PropertyValueConverters と必要な構成の詳細については、"プロパティコンバーター - 特定のフィールドのマッピング" セクションを参照してください。
クエリ可能な暗号化 (QE)
QE を選択すると、暗号化されたフィールドに対して、範囲や等価性などのさまざまな型のクエリを実行できるようになります。
QE の機能と制限事項について詳しく知るには、読み進める前に必ず MongoDB QE ドキュメント (英語) を参照してください。
コレクションの設定
クエリ可能な暗号化では、暗号化されたフィールドに対する実際のクエリで許可される特定の側面を事前に宣言する必要があります。この情報には、使用されるアルゴリズム、許可されるクエリの種類、その属性が含まれており、コレクションの作成時に提供する必要があります。
MongoOperations#createCollection(…) は、QE を利用したコレクションの初期設定に使用できます。Spring Data を介した QE の設定では、CSFLE と同じ構成要素(JSON スキーマの作成)を使用し、スキーマとプロパティを MongoDB に必要な設定形式に変換します。
クエリ可能な暗号化は、手動でも派生的な方法でも設定できます。
手動設定
手動設定では、暗号化フィールドの宣言方法とコレクションの作成方法を完全に制御できます。データキー、暗号化アルゴリズム、フィールドマッピングを明示的に管理する必要がある場合に便利です。
✅ 暗号化設定を完全に制御
✅ データキーとアルゴリズムを明示的に管理する
✅ 複雑な暗号化シナリオに対応
✅ 明示的な設定により予期せぬ事態のリスクを回避 (例: 不適切なアノテーションやクラスパススキャンによる構成の欠落)
⚠️ 明示的なフィールド構成はドメインモデルから逸脱する可能性があるため、ドメインモデルと同期させる必要があります。
派生セットアップ
派生セットアップは、ドメインモデル内のアノテーションに基づいて、必要な暗号化フィールド設定を自動生成します。これはよりシンプルで、データモデルにすでにアノテーションが付与されている一般的な Spring アプリケーションに推奨されます。
✅ ドメインモデル駆動型構成
✅ セットアップとメンテナンスが簡単
⚠️ 複雑なシナリオをすべて網羅しているわけではない
⚠️ 予期せぬ事態が発生するリスク (例: 不適切なアノテーションやクラスパススキャンにより、サブ型に基づくドキュメントの構成が欠落している)
手動収集設定
派生コレクションの設定
MongoDB コレクション情報
BsonBinary pinDK = clientEncryption.createDataKey("local", new com.mongodb.client.model.vault.DataKeyOptions());
BsonBinary ssnDK = clientEncryption.createDataKey("local", new com.mongodb.client.model.vault.DataKeyOptions());
BsonBinary ageDK = clientEncryption.createDataKey("local", new com.mongodb.client.model.vault.DataKeyOptions());
BsonBinary signDK = clientEncryption.createDataKey("local", new com.mongodb.client.model.vault.DataKeyOptions());
CollectionOptions collectionOptions = CollectionOptions.encryptedCollection(options -> options
.encrypted(string("pin"), pinDK)
.queryable(encrypted(string("ssn")).algorithm("Indexed").keyId(ssnDK.asUuid()), equality().contention(0))
.queryable(encrypted(int32("age")).algorithm("Range").keyId(ageDK.asUuid()), range().contention(8).min(0).max(150))
.queryable(encrypted(int64("address.sign")).algorithm("Range").keyId(signDK.asUuid()), range().contention(2).min(-10L).max(10L))
);
mongoTemplate.createCollection(Patient.class, collectionOptions); (1)
| 1 | テンプレートを使用してコレクションを作成すると、生成された keyIds をキャプチャーできない場合があります。その場合は、オプションから Document をレンダリングし、暗号化ライブラリを介して createEncryptedCollection(…) 方式を使用してください。 |
class Patient {
@Id String id; (1)
Address address; (1)
@Encrypted(algorithm = "Unindexed")
String pin; (2)
@Encrypted(algorithm = "Indexed")
@Queryable(queryType = "equality", contentionFactor = 0)
String ssn; (3)
@RangeEncrypted(contentionFactor = 8, rangeOptions = "{ 'min' : 0, 'max' : 150 }")
Integer age; (4)
@RangeEncrypted(contentionFactor = 0L,
rangeOptions = "{\"min\": {\"$numberDouble\": \"0.3\"}, \"max\": {\"$numberDouble\": \"2.5\"}, \"precision\": 2 }")
double height; (5)
}
MongoJsonSchema patientSchema = MongoJsonSchemaCreator.create(mappingContext)
.filter(MongoJsonSchemaCreator.encryptedOnly())
.createSchemaFor(Patient.class);
Document encryptedFields = CollectionOptions.encryptedCollection(patientSchema)
.getEncryptedFieldsOptions()
.map(CollectionOptions.EncryptedFieldsOptions::toDocument)
.orElseThrow();
template.execute(db -> clientEncryption.createEncryptedCollection(db, template.getCollectionName(Patient.class), new CreateCollectionOptions()
.encryptedFields(encryptedFields), new CreateEncryptedCollectionParams("local"))); (1)
| 1 | id と address は暗号化されていません。これらのフィールドは通常通りクエリ可能です。 |
| 2 | pin は暗号化されていますが、クエリをサポートしていません。 |
| 3 | ssn は暗号化されており、等価クエリを許可します。 |
| 4 | age は暗号化されており、0 と 150 間の範囲クエリを可能にします。 |
| 5 | height は暗号化されており、0.3 と 2.5 間の範囲クエリを可能にします。 |
Queryable アノテーションは、暗号化されたフィールドに対して許可されるクエリ型を定義できます。@RangeEncrypted は、range クエリを許可するフィールド向けの @Encrypted と @Queryable を組み合わせたものです。提供されているアノテーションからカスタムアノテーションを作成することもできます。
{
name: 'patient',
type: 'collection',
options: {
encryptedFields: {
escCollection: 'enxcol_.test.esc',
ecocCollection: 'enxcol_.test.ecoc',
fields: [
{
keyId: ...,
path: 'ssn',
bsonType: 'string',
queries: [ { queryType: 'equality', contention: Long('0') } ]
},
{
keyId: ...,
path: 'age',
bsonType: 'int',
queries: [ { queryType: 'range', contention: Long('8'), min: 0, max: 150 } ]
},
{
keyId: ...,
path: 'pin',
bsonType: 'string'
},
{
keyId: ...,
path: 'address.sign',
bsonType: 'long',
queries: [ { queryType: 'range', contention: Long('2'), min: Long('-10'), max: Long('10') } ]
}
]
}
}
}
|
自動暗号化 (QE)
MongoDB は、MongoDB ドライバーの自動暗号化機能を使用することで、クエリ可能な暗号化を標準でサポートしています。自動暗号化には、明示的な暗号化 / 復号化手順を必要とせずに暗号化された読み取り / 書き込み操作を実行できる JSON スキーマが必要です。
MongoDB のドキュメントに従ってコレクションを作成するだけです。上記のセクションで概説した必要な設定を作成するためのテクニックを活用できます。
MongoEncryptionConverter セットアップ
MongoEncryptionConverter のコンバーターのセットアップには、いくつかのコンポーネントが関係するため、いくつかの手順が必要です。Bean セットアップは以下で構成されます。
ClientEncryptionエンジンClientEncryptionおよびEncryptionKeyResolverで構成されたMongoEncryptionConverterインスタンス。登録された
MongoEncryptionConverterBean を使用するPropertyValueConverterFactory。
EncryptionKeyResolver は、動的な DEK 解決を可能にするプロパティへのアクセスを提供する EncryptionContext を使用します。
class Config extends AbstractMongoClientConfiguration {
@Autowired ApplicationContext appContext;
@Bean
ClientEncryption clientEncryption() { (1)
ClientEncryptionSettings encryptionSettings = ClientEncryptionSettings.builder();
// …
return ClientEncryptions.create(encryptionSettings);
}
@Bean
MongoEncryptionConverter encryptingConverter(ClientEncryption clientEncryption) {
Encryption<BsonValue, BsonBinary> encryption = MongoClientEncryption.just(clientEncryption);
EncryptionKeyResolver keyResolver = EncryptionKeyResolver.annotated((ctx) -> …); (2)
return new MongoEncryptionConverter(encryption, keyResolver); (3)
}
@Override
protected void configureConverters(MongoConverterConfigurationAdapter adapter) {
adapter
.registerPropertyValueConverterFactory(PropertyValueConverterFactory.beanFactoryAware(appContext)); (4)
}
}| 1 | com.mongodb.client.vault.ClientEncryption を使用して Encryption エンジンをセットアップします。インスタンスはステートフルであるため、使用後は閉じる必要があります。ClientEncryption は Closeable であるため、Spring がこれを処理します。 |
| 2 | アノテーションから EncryptionKey を決定するには、アノテーションベースの EncryptionKeyResolver をセットアップします。 |
| 3 | MongoEncryptionConverter を作成します。 |
| 4 | BeanFactory からの PropertyValueConverter ルックアップを有効にします。 |