BAEL-6046 - MongoDB - Field Level Encryption (#13494)
This commit is contained in:
parent
ba8a44b0ca
commit
749a077478
@ -14,9 +14,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
|
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
|
||||||
|
|
||||||
import com.baeldung.boot.csfle.config.converter.BinaryConverter;
|
|
||||||
import com.mongodb.AutoEncryptionSettings;
|
import com.mongodb.AutoEncryptionSettings;
|
||||||
import com.mongodb.ClientEncryptionSettings;
|
import com.mongodb.ClientEncryptionSettings;
|
||||||
import com.mongodb.ConnectionString;
|
import com.mongodb.ConnectionString;
|
||||||
@ -50,11 +48,6 @@ public class MongoClientConfig extends AbstractMongoClientConfiguration {
|
|||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MongoCustomConversions customConversions() {
|
|
||||||
return new MongoCustomConversions(Arrays.asList(new BinaryConverter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
@Override
|
||||||
public MongoClient mongoClient() {
|
public MongoClient mongoClient() {
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package com.baeldung.boot.csfle.config.converter;
|
|
||||||
|
|
||||||
import org.bson.BsonBinary;
|
|
||||||
import org.bson.types.Binary;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
|
|
||||||
public class BinaryConverter implements Converter<Binary, BsonBinary> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonBinary convert(Binary source) {
|
|
||||||
return new BsonBinary(source.getType(), source.getData());
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,8 +13,10 @@ public class Citizen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Citizen(EncryptedCitizen encryptedCitizen) {
|
public Citizen(EncryptedCitizen encryptedCitizen) {
|
||||||
|
if (encryptedCitizen != null) {
|
||||||
this.name = encryptedCitizen.getName();
|
this.name = encryptedCitizen.getName();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package com.baeldung.boot.csfle.data;
|
package com.baeldung.boot.csfle.data;
|
||||||
|
|
||||||
import org.bson.BsonBinary;
|
import org.bson.types.Binary;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
@Document("citizens")
|
@Document("citizens")
|
||||||
public class EncryptedCitizen {
|
public class EncryptedCitizen {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private BsonBinary email;
|
private Binary email;
|
||||||
private BsonBinary birthYear;
|
private Binary birthYear;
|
||||||
|
|
||||||
public EncryptedCitizen() {
|
public EncryptedCitizen() {
|
||||||
}
|
}
|
||||||
@ -25,19 +25,19 @@ public class EncryptedCitizen {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BsonBinary getEmail() {
|
public Binary getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmail(BsonBinary email) {
|
public void setEmail(Binary email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BsonBinary getBirthYear() {
|
public Binary getBirthYear() {
|
||||||
return birthYear;
|
return birthYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBirthYear(BsonBinary birthYear) {
|
public void setBirthYear(Binary birthYear) {
|
||||||
this.birthYear = birthYear;
|
this.birthYear = birthYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import org.bson.BsonBinary;
|
|||||||
import org.bson.BsonInt32;
|
import org.bson.BsonInt32;
|
||||||
import org.bson.BsonString;
|
import org.bson.BsonString;
|
||||||
import org.bson.BsonValue;
|
import org.bson.BsonValue;
|
||||||
|
import org.bson.types.Binary;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
@ -65,7 +66,7 @@ public class CitizenService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BsonBinary encrypt(Object value, String algorithm) {
|
public Binary encrypt(Object value, String algorithm) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -80,17 +81,22 @@ public class CitizenService {
|
|||||||
|
|
||||||
EncryptOptions options = new EncryptOptions(algorithm);
|
EncryptOptions options = new EncryptOptions(algorithm);
|
||||||
options.keyId(encryptionConfig.getDataKeyId());
|
options.keyId(encryptionConfig.getDataKeyId());
|
||||||
return clientEncryption.encrypt(bsonValue, options);
|
|
||||||
|
BsonBinary encryptedValue = clientEncryption.encrypt(bsonValue, options);
|
||||||
|
return new Binary(encryptedValue.getType(), encryptedValue.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BsonValue decryptProperty(BsonBinary value) {
|
public BsonValue decryptProperty(Binary value) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return clientEncryption.decrypt(value);
|
return clientEncryption.decrypt(new BsonBinary(value.getType(), value.getData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Citizen decrypt(EncryptedCitizen encrypted) {
|
private Citizen decrypt(EncryptedCitizen encrypted) {
|
||||||
|
if (encrypted == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
Citizen citizen = new Citizen(encrypted);
|
Citizen citizen = new Citizen(encrypted);
|
||||||
|
|
||||||
BsonValue decryptedBirthYear = decryptProperty(encrypted.getBirthYear());
|
BsonValue decryptedBirthYear = decryptProperty(encrypted.getBirthYear());
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package com.baeldung.boot.csfle;
|
package com.baeldung.boot.csfle;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
import org.bson.BsonBinary;
|
import org.bson.types.Binary;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -36,7 +38,7 @@ public class CitizenServiceLiveTest {
|
|||||||
citizen.setName("Foo");
|
citizen.setName("Foo");
|
||||||
citizen.setEmail("foo@citizen.com");
|
citizen.setEmail("foo@citizen.com");
|
||||||
|
|
||||||
BsonBinary encryptedEmail = service.encrypt(citizen.getEmail(), CitizenService.DETERMINISTIC_ALGORITHM);
|
Binary encryptedEmail = service.encrypt(citizen.getEmail(), CitizenService.DETERMINISTIC_ALGORITHM);
|
||||||
|
|
||||||
EncryptedCitizen saved = service.save(citizen);
|
EncryptedCitizen saved = service.save(citizen);
|
||||||
assertEquals(encryptedEmail, saved.getEmail());
|
assertEquals(encryptedEmail, saved.getEmail());
|
||||||
|
@ -4,3 +4,8 @@ spring.datasource.password=sa
|
|||||||
|
|
||||||
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
|
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
|
||||||
logging.level.com.baeldung.spring.data.persistence.search=debug
|
logging.level.com.baeldung.spring.data.persistence.search=debug
|
||||||
|
|
||||||
|
spring.jpa.show-sql=true
|
||||||
|
logging.level.org.hibernate.SQL=DEBUG
|
||||||
|
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||||
|
spring.jpa.properties.hibernate.format_sql=true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user