Skip to content

Commit 8c71285

Browse files
committed
Add a test of failing decryption in Lucene
1 parent 127e8cd commit 8c71285

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/provider/foundationdb/properties/RecordLayerPropertyStorage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ public <T> boolean hasProp(@Nonnull RecordLayerPropertyKey<T> propKey) {
100100
return propertyMap.containsKey(propKey);
101101
}
102102

103+
public <T> void removeProp(@Nonnull RecordLayerPropertyKey<T> propKey) {
104+
propertyMap.remove(propKey);
105+
}
106+
103107
public <T> Builder addProp(@Nonnull RecordLayerPropertyValue<T> propValue) {
104108
if (this.propertyMap.putIfAbsent(propValue.getKey(), propValue) != null) {
105109
throw new RecordCoreException("Duplicate property name is added")

fdb-record-layer-lucene/src/test/java/com/apple/foundationdb/record/lucene/LuceneIndexMaintenanceTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
import com.apple.foundationdb.record.lucene.directory.FDBDirectoryLockFactory;
3636
import com.apple.foundationdb.record.lucene.directory.FDBDirectoryWrapper;
3737
import com.apple.foundationdb.record.metadata.Index;
38+
import com.apple.foundationdb.record.provider.common.FixedZeroKeyManager;
3839
import com.apple.foundationdb.record.provider.common.RollingTestKeyManager;
40+
import com.apple.foundationdb.record.provider.common.SerializationKeyManager;
3941
import com.apple.foundationdb.record.provider.common.StoreTimer;
4042
import com.apple.foundationdb.record.provider.foundationdb.FDBExceptions;
4143
import com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext;
@@ -70,6 +72,8 @@
7072

7173
import javax.annotation.Nonnull;
7274
import javax.annotation.Nullable;
75+
import javax.crypto.KeyGenerator;
76+
import javax.crypto.SecretKey;
7377
import java.io.IOException;
7478
import java.security.GeneralSecurityException;
7579
import java.time.Duration;
@@ -104,6 +108,8 @@
104108
import static com.apple.foundationdb.record.metadata.Key.Expressions.field;
105109
import static com.apple.foundationdb.record.metadata.Key.Expressions.function;
106110
import static org.hamcrest.MatcherAssert.assertThat;
111+
import static org.hamcrest.Matchers.containsString;
112+
import static org.hamcrest.Matchers.instanceOf;
107113
import static org.junit.jupiter.api.Assertions.assertEquals;
108114
import static org.junit.jupiter.api.Assertions.assertFalse;
109115
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -893,6 +899,52 @@ void sampledDelete(boolean isSynthetic, boolean isGrouped, long seed) throws IOE
893899
assertThat(partitionCounts, Matchers.contains(5, 3, 4)));
894900
}
895901

902+
static Stream<Arguments> changingEncryptionKey() {
903+
return Stream.concat(Stream.of(Arguments.of(true, true, 288513),
904+
Arguments.of(false, false, 792025)),
905+
RandomizedTestUtils.randomArguments(random ->
906+
Arguments.of(random.nextBoolean(), random.nextBoolean(), random.nextLong())));
907+
}
908+
909+
@ParameterizedTest
910+
@MethodSource
911+
void changingEncryptionKey(boolean isSynthetic, boolean isGrouped, long seed) throws IOException, GeneralSecurityException {
912+
final LuceneIndexTestDataModel dataModel = new LuceneIndexTestDataModel.Builder(seed, this::getStoreBuilder, pathManager)
913+
.setIsGrouped(isGrouped)
914+
.setIsSynthetic(isSynthetic)
915+
.setPrimaryKeySegmentIndexEnabled(true)
916+
.build();
917+
918+
final RecordLayerPropertyStorage.Builder contextPropsBuilder = RecordLayerPropertyStorage.newBuilder()
919+
.addProp(LuceneRecordContextProperties.LUCENE_INDEX_COMPRESSION_ENABLED, true)
920+
.addProp(LuceneRecordContextProperties.LUCENE_INDEX_ENCRYPTION_ENABLED, true);
921+
final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
922+
keyGen.init(128);
923+
final SecretKey key1 = keyGen.generateKey();
924+
final SerializationKeyManager keyManager1 = new FixedZeroKeyManager(key1, null, null);
925+
contextPropsBuilder.addProp(LuceneRecordContextProperties.LUCENE_INDEX_KEY_MANAGER, keyManager1);
926+
final RecordLayerPropertyStorage contextProps1 = contextPropsBuilder.build();
927+
928+
try (FDBRecordContext context = openContext(contextProps1)) {
929+
dataModel.saveRecordsToAllGroups(20, context);
930+
commit(context);
931+
}
932+
933+
explicitMergeIndex(dataModel.index, contextProps1, dataModel.schemaSetup);
934+
935+
final SecretKey key2 = keyGen.generateKey();
936+
final SerializationKeyManager keyManager2 = new FixedZeroKeyManager(key2, null, null);
937+
contextPropsBuilder.removeProp(LuceneRecordContextProperties.LUCENE_INDEX_KEY_MANAGER);
938+
contextPropsBuilder.addProp(LuceneRecordContextProperties.LUCENE_INDEX_KEY_MANAGER, keyManager2);
939+
final RecordLayerPropertyStorage contextProps2 = contextPropsBuilder.build();
940+
IOException ioException = assertThrows(IOException.class,
941+
() -> dataModel.validate(() -> openContext(contextProps2)));
942+
assertThat(ioException.getCause(), instanceOf(RecordCoreException.class));
943+
assertThat(ioException.getCause().getMessage(), containsString("Lucene data decoding failure"));
944+
assertThat(ioException.getCause().getCause(), instanceOf(GeneralSecurityException.class));
945+
946+
}
947+
896948
private static Stream<Arguments> concurrentParameters() {
897949
// only run the individual tests with synthetic during nightly, the mix runs both
898950
return Stream.concat(Stream.of(false),

0 commit comments

Comments
 (0)