Browse Source

Introduce RangeEncrypted since you cannot combine explict and rage anyways

issue/4185-light
Christoph Strobl 10 months ago
parent
commit
32eeee56d3
No known key found for this signature in database
GPG Key ID: E6054036D0C37A4B
  1. 34
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/encryption/MongoEncryptionConverter.java
  2. 18
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ExplicitEncrypted.java
  3. 65
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/RangeEncrypted.java
  4. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/encryption/RangeEncryptionTests.java

34
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/encryption/MongoEncryptionConverter.java

@ -43,6 +43,7 @@ import org.springframework.data.mongodb.core.encryption.EncryptionOptions;
import org.springframework.data.mongodb.core.mapping.Encrypted; import org.springframework.data.mongodb.core.mapping.Encrypted;
import org.springframework.data.mongodb.core.mapping.ExplicitEncrypted; import org.springframework.data.mongodb.core.mapping.ExplicitEncrypted;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.mapping.RangeEncrypted;
import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.mongodb.util.BsonUtils;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@ -180,23 +181,28 @@ public class MongoEncryptionConverter implements EncryptingConverter<Object, Obj
ExplicitEncrypted explicitEncryptedAnnotation = persistentProperty.findAnnotation(ExplicitEncrypted.class); ExplicitEncrypted explicitEncryptedAnnotation = persistentProperty.findAnnotation(ExplicitEncrypted.class);
if (explicitEncryptedAnnotation != null) { if (explicitEncryptedAnnotation != null) {
QueryableEncryptionOptions queryableEncryptionOptions = QueryableEncryptionOptions.none(); encryptionOptions = new EncryptionOptions(algorithm, key, QueryableEncryptionOptions.none());
String rangeOptions = explicitEncryptedAnnotation.rangeOptions(); } else {
if (!rangeOptions.isEmpty()) { RangeEncrypted rangeEncryptedAnnotation = persistentProperty.findAnnotation(RangeEncrypted.class);
queryableEncryptionOptions = queryableEncryptionOptions.rangeOptions(Document.parse(rangeOptions)); if (rangeEncryptedAnnotation != null) {
} QueryableEncryptionOptions queryableEncryptionOptions = QueryableEncryptionOptions.none();
String rangeOptions = rangeEncryptedAnnotation.rangeOptions();
if (!rangeOptions.isEmpty()) {
queryableEncryptionOptions = queryableEncryptionOptions.rangeOptions(Document.parse(rangeOptions));
}
if (explicitEncryptedAnnotation.contentionFactor() >= 0) { if (rangeEncryptedAnnotation.contentionFactor() >= 0) {
queryableEncryptionOptions = queryableEncryptionOptions queryableEncryptionOptions = queryableEncryptionOptions
.contentionFactor(explicitEncryptedAnnotation.contentionFactor()); .contentionFactor(rangeEncryptedAnnotation.contentionFactor());
} }
boolean isPartOfARangeQuery = algorithm.equalsIgnoreCase(RANGE) && fieldNameAndQueryOperator != null; boolean isPartOfARangeQuery = fieldNameAndQueryOperator != null;
if (isPartOfARangeQuery) { if (isPartOfARangeQuery) {
encryptExpression = true; encryptExpression = true;
queryableEncryptionOptions = queryableEncryptionOptions.queryType("range"); queryableEncryptionOptions = queryableEncryptionOptions.queryType("range");
}
encryptionOptions = new EncryptionOptions(algorithm, key, queryableEncryptionOptions);
} }
encryptionOptions = new EncryptionOptions(algorithm, key, queryableEncryptionOptions);
} }
if (encryptExpression) { if (encryptExpression) {

18
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ExplicitEncrypted.java

@ -86,24 +86,6 @@ public @interface ExplicitEncrypted {
*/ */
String keyAltName() default ""; String keyAltName() default "";
/**
* Set the contention factor
* <p>
* Only required when using {@literal range} encryption.
* @return the contention factor
*/
long contentionFactor() default -1;
/**
* Set the {@literal range} options
* <p>
* Should be valid extended json representing the range options and including the following values:
* {@code min}, {@code max}, {@code trimFactor} and {@code sparsity}.
*
* @return the json representation of range options
*/
String rangeOptions() default "";
/** /**
* The {@link EncryptingConverter} type handling the {@literal en-/decryption} of the annotated property. * The {@link EncryptingConverter} type handling the {@literal en-/decryption} of the annotated property.
* *

65
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/RangeEncrypted.java

@ -0,0 +1,65 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.mapping;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.convert.PropertyValueConverter;
import org.springframework.data.convert.ValueConverter;
import org.springframework.data.mongodb.core.convert.encryption.EncryptingConverter;
import org.springframework.data.mongodb.core.convert.encryption.MongoEncryptionConverter;
/**
* @author Christoph Strobl
* @since 2025/03
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Encrypted(algorithm = "Range")
@ValueConverter
public @interface RangeEncrypted {
/**
* Set the contention factor
* <p>
* Only required when using {@literal range} encryption.
* @return the contention factor
*/
long contentionFactor() default -1;
/**
* Set the {@literal range} options
* <p>
* Should be valid extended json representing the range options and including the following values:
* {@code min}, {@code max}, {@code trimFactor} and {@code sparsity}.
*
* @return the json representation of range options
*/
String rangeOptions() default "";
/**
* The {@link EncryptingConverter} type handling the {@literal en-/decryption} of the annotated property.
*
* @return the configured {@link EncryptingConverter}. A {@link MongoEncryptionConverter} by default.
*/
@AliasFor(annotation = ValueConverter.class, value = "value")
Class<? extends PropertyValueConverter> value() default MongoEncryptionConverter.class;
}

6
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/encryption/RangeEncryptionTests.java

@ -76,6 +76,7 @@ import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter;
import org.springframework.data.mongodb.core.convert.encryption.MongoEncryptionConverter; import org.springframework.data.mongodb.core.convert.encryption.MongoEncryptionConverter;
import org.springframework.data.mongodb.core.mapping.ExplicitEncrypted; import org.springframework.data.mongodb.core.mapping.ExplicitEncrypted;
import org.springframework.data.mongodb.core.mapping.RangeEncrypted;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.schema.JsonSchemaProperty; import org.springframework.data.mongodb.core.schema.JsonSchemaProperty;
import org.springframework.data.mongodb.core.schema.QueryCharacteristics; import org.springframework.data.mongodb.core.schema.QueryCharacteristics;
@ -353,12 +354,11 @@ class RangeEncryptionTests {
static class Person { static class Person {
String id; String id;
// @ExplicitEncrypted(algorithm = AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic)
String name; String name;
@ExplicitEncrypted(algorithm = RANGE, contentionFactor = 0L, @RangeEncrypted(contentionFactor = 0L,
rangeOptions = "{\"min\": 0, \"max\": 200, \"trimFactor\": 1, \"sparsity\": 1}") Integer encryptedInt; rangeOptions = "{\"min\": 0, \"max\": 200, \"trimFactor\": 1, \"sparsity\": 1}") Integer encryptedInt;
@ExplicitEncrypted(algorithm = RANGE, contentionFactor = 0L, @RangeEncrypted(contentionFactor = 0L,
rangeOptions = "{\"min\": {\"$numberLong\": \"1000\"}, \"max\": {\"$numberLong\": \"9999\"}, \"trimFactor\": 1, \"sparsity\": 1}") Long encryptedLong; rangeOptions = "{\"min\": {\"$numberLong\": \"1000\"}, \"max\": {\"$numberLong\": \"9999\"}, \"trimFactor\": 1, \"sparsity\": 1}") Long encryptedLong;
public String getId() { public String getId() {

Loading…
Cancel
Save