|
|
|
@ -15,110 +15,16 @@ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
package org.springframework.data.mongodb.core.encryption; |
|
|
|
package org.springframework.data.mongodb.core.encryption; |
|
|
|
|
|
|
|
|
|
|
|
import java.security.SecureRandom; |
|
|
|
|
|
|
|
import java.util.Collections; |
|
|
|
|
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.bson.BsonBinary; |
|
|
|
|
|
|
|
import org.bson.Document; |
|
|
|
|
|
|
|
import org.junit.jupiter.api.extension.ExtendWith; |
|
|
|
import org.junit.jupiter.api.extension.ExtendWith; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
|
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
|
|
|
|
import org.springframework.context.annotation.Bean; |
|
|
|
|
|
|
|
import org.springframework.context.annotation.Configuration; |
|
|
|
|
|
|
|
import org.springframework.data.convert.PropertyValueConverterFactory; |
|
|
|
|
|
|
|
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; |
|
|
|
|
|
|
|
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter; |
|
|
|
|
|
|
|
import org.springframework.data.mongodb.core.convert.encryption.MongoEncryptionConverter; |
|
|
|
|
|
|
|
import org.springframework.data.mongodb.core.encryption.EncryptionTests.Config; |
|
|
|
|
|
|
|
import org.springframework.data.util.Lazy; |
|
|
|
|
|
|
|
import org.springframework.test.context.ContextConfiguration; |
|
|
|
import org.springframework.test.context.ContextConfiguration; |
|
|
|
import org.springframework.test.context.junit.jupiter.SpringExtension; |
|
|
|
import org.springframework.test.context.junit.jupiter.SpringExtension; |
|
|
|
|
|
|
|
|
|
|
|
import com.mongodb.ClientEncryptionSettings; |
|
|
|
|
|
|
|
import com.mongodb.ConnectionString; |
|
|
|
|
|
|
|
import com.mongodb.MongoClientSettings; |
|
|
|
|
|
|
|
import com.mongodb.MongoNamespace; |
|
|
|
|
|
|
|
import com.mongodb.client.MongoClient; |
|
|
|
|
|
|
|
import com.mongodb.client.MongoCollection; |
|
|
|
|
|
|
|
import com.mongodb.client.model.Filters; |
|
|
|
|
|
|
|
import com.mongodb.client.model.IndexOptions; |
|
|
|
|
|
|
|
import com.mongodb.client.model.Indexes; |
|
|
|
|
|
|
|
import com.mongodb.client.model.vault.DataKeyOptions; |
|
|
|
|
|
|
|
import com.mongodb.client.vault.ClientEncryptions; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* @author Christoph Strobl |
|
|
|
* @author Christoph Strobl |
|
|
|
* @author Julia Lee |
|
|
|
* @author Julia Lee |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@ExtendWith(SpringExtension.class) |
|
|
|
@ExtendWith(SpringExtension.class) |
|
|
|
@ContextConfiguration(classes = Config.class) |
|
|
|
@ContextConfiguration(classes = AbstractEncryptionTestBase.EncryptionConfig.class) |
|
|
|
public class EncryptionTests extends AbstractEncryptionTestBase { |
|
|
|
public class EncryptionTests extends AbstractEncryptionTestBase { |
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
|
|
|
static class Config extends AbstractMongoClientConfiguration { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired ApplicationContext applicationContext; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
protected String getDatabaseName() { |
|
|
|
|
|
|
|
return "fle-test"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public MongoClient mongoClient() { |
|
|
|
|
|
|
|
return super.mongoClient(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
protected void configureConverters(MongoConverterConfigurationAdapter converterConfigurationAdapter) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
converterConfigurationAdapter |
|
|
|
|
|
|
|
.registerPropertyValueConverterFactory(PropertyValueConverterFactory.beanFactoryAware(applicationContext)) |
|
|
|
|
|
|
|
.useNativeDriverJavaTimeCodecs(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
|
|
|
MongoEncryptionConverter encryptingConverter(MongoClientEncryption mongoClientEncryption) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Lazy<BsonBinary> dataKey = Lazy.of(() -> mongoClientEncryption.getClientEncryption().createDataKey("local", |
|
|
|
|
|
|
|
new DataKeyOptions().keyAltNames(Collections.singletonList("mySuperSecretKey")))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new MongoEncryptionConverter(mongoClientEncryption, |
|
|
|
|
|
|
|
EncryptionKeyResolver.annotated((ctx) -> EncryptionKey.keyId(dataKey.get()))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
|
|
|
CachingMongoClientEncryption clientEncryption(ClientEncryptionSettings encryptionSettings) { |
|
|
|
|
|
|
|
return new CachingMongoClientEncryption(() -> ClientEncryptions.create(encryptionSettings)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
|
|
|
ClientEncryptionSettings encryptionSettings(MongoClient mongoClient) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault"); |
|
|
|
|
|
|
|
MongoCollection<Document> keyVaultCollection = mongoClient.getDatabase(keyVaultNamespace.getDatabaseName()) |
|
|
|
|
|
|
|
.getCollection(keyVaultNamespace.getCollectionName()); |
|
|
|
|
|
|
|
keyVaultCollection.drop(); |
|
|
|
|
|
|
|
// Ensure that two data keys cannot share the same keyAltName.
|
|
|
|
|
|
|
|
keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), |
|
|
|
|
|
|
|
new IndexOptions().unique(true).partialFilterExpression(Filters.exists("keyAltNames"))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MongoCollection<Document> collection = mongoClient.getDatabase(getDatabaseName()).getCollection("test"); |
|
|
|
|
|
|
|
collection.drop(); // Clear old data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
byte[] localMasterKey = new byte[96]; |
|
|
|
|
|
|
|
new SecureRandom().nextBytes(localMasterKey); |
|
|
|
|
|
|
|
Map<String, Map<String, Object>> kmsProviders = Map.of("local", Map.of("key", localMasterKey)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create the ClientEncryption instance
|
|
|
|
|
|
|
|
return ClientEncryptionSettings.builder() |
|
|
|
|
|
|
|
.keyVaultMongoClientSettings( |
|
|
|
|
|
|
|
MongoClientSettings.builder().applyConnectionString(new ConnectionString("mongodb://localhost")).build()) //
|
|
|
|
|
|
|
|
.keyVaultNamespace(keyVaultNamespace.getFullName()) //
|
|
|
|
|
|
|
|
.kmsProviders(kmsProviders) //
|
|
|
|
|
|
|
|
.build(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|