diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc index 5d8692a26..a4aae2374 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc @@ -119,61 +119,6 @@ By default, the `@ExplicitEncrypted(value=…)` attribute references a `MongoEnc It is possible to change the default implementation and exchange it with any `PropertyValueConverter` implementation by providing the according type reference. To learn more about custom `PropertyValueConverters` and the required configuration, please refer to the xref:mongodb/mapping/property-converters.adoc[Property Converters - Mapping specific fields] section. -[[mongo.encryption.explicit-setup]] -=== MongoEncryptionConverter Setup - -The converter setup for `MongoEncryptionConverter` requires a few steps as several components are involved. -The bean setup consists of the following: - -1. The `ClientEncryption` engine -2. A `MongoEncryptionConverter` instance configured with `ClientEncryption` and a `EncryptionKeyResolver`. -3. A `PropertyValueConverterFactory` that uses the registered `MongoEncryptionConverter` bean. - -A side effect of using annotated key resolution is that the `@ExplicitEncrypted` annotation does not need to specify an alt key name. -The `EncryptionKeyResolver` uses an `EncryptionContext` providing access to the property allowing for dynamic DEK resolution. - -.Sample MongoEncryptionConverter Configuration -==== -[source,java] ----- -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 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> Set up a `Encryption` engine using `com.mongodb.client.vault.ClientEncryption`. -The instance is stateful and must be closed after usage. -Spring takes care of this because `ClientEncryption` is ``Closeable``. -<2> Set up an annotation-based `EncryptionKeyResolver` to determine the `EncryptionKey` from annotations. -<3> Create the `MongoEncryptionConverter`. -<4> Enable for a `PropertyValueConverter` lookup from the `BeanFactory`. -==== - [[mongo.encryption.queryable]] == Queryable Encryption (QE) @@ -183,7 +128,7 @@ Please make sure to consult the https://www.mongodb.com/docs/manual/core/queryab === Collection Setup Queryable Encryption requires upfront declaration of certain aspects allowed within an actual query against an encrypted field. -The information covers the algorithm in use as well as allowed query types along with their attributes and must be provided when creating the collection and will +The information covers the algorithm in use as well as allowed query types along with their attributes and must be provided when creating the collection. `MongoOperations#createCollection(...)` can be used to do the initial setup for collections utilizing QE. The configuration for QE via Spring Data uses the same building blocks (a xref:mongodb/mapping/mapping-schema.adoc#mongo.jsonSchema.encrypted-fields[JSON Schema creation]) as CSFLE, converting the schema/properties into the configuration format required by MongoDB. @@ -196,13 +141,14 @@ Manual Collection Setup:: [source,java,indent=0,subs="verbatim,quotes",role="primary"] ---- CollectionOptions collectionOptions = CollectionOptions.encryptedCollection(options -> options - .queryable(encrypted(string("ssn")), equality().contention(0)) + .queryable(encrypted(string("ssn")).algorithm("Indexed"), equality().contention(0)) .queryable(encrypted(int32("age")).algorithm("Range"), range().contention(8).min(0).max(150)) - .queryable(encrypted(int64("address.sign")), range().contention(2).min(-10L).max(10L)) + .queryable(encrypted(int64("address.sign")).algorithm("Range"), range().contention(2).min(-10L).max(10L)) ); -mongoTemplate.createCollection(Patient.class, collectionOptions); +mongoTemplate.createCollection(Patient.class, collectionOptions); <1> ---- +<1> Using the template to create the collection may prevent capturing generated keyIds. In this case render the `Document` from the options and use the `createEncryptedCollection(...)` method via the encryption library. ==== Derived Collection Setup:: @@ -230,8 +176,13 @@ MongoJsonSchema patientSchema = MongoJsonSchemaCreator.create(mappingContext) CollectionOptions collectionOptions = CollectionOptions.encryptedCollection(patientSchema); -mongoTemplate.createCollection(Patient.class, collectionOptions); +mongoTemplate.createCollection(Patient.class, collectionOptions); <1> ---- +<1> Using the template to create the collection may prevent capturing generated keyIds. In this case render the `Document` from the options and use the `createEncryptedCollection(...)` method via the encryption library. + +The `Queryable` annotation allows to define allowed query types for encrypted fields. +`@RangeEncrypted` is a combination of `@Encrypted` and `@Queryable` for fields allowing `range` queries. +It is possible to create custom annotations out of the provided ones. ==== MongoDB Collection Info:: @@ -273,29 +224,90 @@ MongoDB Collection Info:: ==== ====== -[WARNING] +[NOTE] ==== -It is not possible to use both QE and CSFLE within the same collection. +- It is not possible to use both QE and CSFLE within the same collection. +- It is not possible to query a `range` indexed field with an `equality` operator. +- It is not possible to query an `equality` indexed field with a `range` operator. +- It is not possible to set `bypassAutoEncrytion(true)`. +- It is not possible to use self maintained encryption keys via `@Encrypted` in combination with Queryable Encryption. +- Contention is only optional on the server side, the clients requires you to set the value (Default us `8`). +- Additional options for eg. `min` and `max` need to match the actual field type. Make sure to use `$numberLong` etc. to ensure target types when parsing bson String. +- Queryable Encryption will an extra field `__safeContent__` to each of your documents. +Unless explicitly excluded the field will be loaded into memory when retrieving results. ==== -[WARNING] -==== -//add big warnings in here -- types -- indexes -- queries -==== +[[mongo.encryption.queryable.automatic]] +=== Automatic Encryption (QE) + +MongoDB supports Queryable Encryption out of the box using the MongoDB driver with its Automatic Encryption feature. +Automatic Encryption requires a xref:mongodb/mapping/mapping-schema.adoc[JSON Schema] that allows to perform encrypted read and write operations without the need to provide an explicit en-/decryption step. + +All you need to do is create the collection according to the MongoDB documentation. +You may utilize techniques to create the required configuration outlined in the section above. + +[[mongo.encryption.queryable.manual]] +=== Explicit Encryption (QE) + +Explicit encryption uses the MongoDB driver's encryption library (`org.mongodb:mongodb-crypt`) to perform encryption and decryption tasks based on the meta information provided by annotation within the domain model. [NOTE] ==== -Queryable Encryption will an extra field `__safeContent__` to each of your documents. -Unless explicitly excluded the field will be loaded into memory when retrieving results. +There is no official support for using Explicit Queryable Encryption. +The audacious user may combine `@Encyrpted` and `@Queryable` with `@ValueConverter(MongoEncryptionConverter.class)` at their own risk. ==== +[[mongo.encryption.explicit-setup]] +[[mongo.encryption.converter-setup]] +== MongoEncryptionConverter Setup +The converter setup for `MongoEncryptionConverter` requires a few steps as several components are involved. +The bean setup consists of the following: -[[mongo.encryption.queryable.automatic]] -=== Automatic Encryption (QE) +1. The `ClientEncryption` engine +2. A `MongoEncryptionConverter` instance configured with `ClientEncryption` and a `EncryptionKeyResolver`. +3. A `PropertyValueConverterFactory` that uses the registered `MongoEncryptionConverter` bean. -MongoDB supports Queryable Encryption out of the box using the MongoDB driver with its Automatic Encryption feature. -Automatic Encryption requires a xref:mongodb/mapping/mapping-schema.adoc[JSON Schema] that allows to perform encrypted read and write operations without the need to provide an explicit en-/decryption step. +The `EncryptionKeyResolver` uses an `EncryptionContext` providing access to the property allowing for dynamic DEK resolution. + +.Sample MongoEncryptionConverter Configuration +==== +[source,java] +---- +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 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> Set up a `Encryption` engine using `com.mongodb.client.vault.ClientEncryption`. +The instance is stateful and must be closed after usage. +Spring takes care of this because `ClientEncryption` is ``Closeable``. +<2> Set up an annotation-based `EncryptionKeyResolver` to determine the `EncryptionKey` from annotations. +<3> Create the `MongoEncryptionConverter`. +<4> Enable for a `PropertyValueConverter` lookup from the `BeanFactory`. +====