From d42d5038a7113609b44e638b296aeaffad969e83 Mon Sep 17 00:00:00 2001 From: Erwin Pe Date: Fri, 18 Feb 2022 17:58:50 +0000 Subject: SERVER-63465 Create index limitations with encrypted fields --- src/mongo/db/commands/SConscript | 1 + src/mongo/db/commands/create_indexes.cpp | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) (limited to 'src/mongo') diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript index 60fa18346ac..6e17b42669a 100644 --- a/src/mongo/db/commands/SConscript +++ b/src/mongo/db/commands/SConscript @@ -367,6 +367,7 @@ env.Library( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/crypto/encrypted_field_config', '$BUILD_DIR/mongo/db/api_parameters', '$BUILD_DIR/mongo/db/catalog/catalog_helpers', '$BUILD_DIR/mongo/db/catalog/collection_query_info', diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp index 8496c2fe0ee..92c3efb2bbf 100644 --- a/src/mongo/db/commands/create_indexes.cpp +++ b/src/mongo/db/commands/create_indexes.cpp @@ -35,6 +35,7 @@ #include #include "mongo/base/string_data.h" +#include "mongo/crypto/encryption_fields_gen.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/catalog/clustered_collection_util.h" #include "mongo/db/catalog/collection.h" @@ -195,6 +196,74 @@ void validateTTLOptions(OperationContext* opCtx, } } +void checkEncryptedFieldIndexRestrictions(OperationContext* opCtx, + const NamespaceString& ns, + const CreateIndexesCommand& cmd) { + if (!gFeatureFlagFLE2.isEnabledAndIgnoreFCV()) { + return; + } + + AutoGetCollection collection(opCtx, ns, MODE_IS); + if (!collection) { + return; + } + + const auto& encryptConfig = collection->getCollectionOptions().encryptedFieldConfig; + if (!encryptConfig) { + // this collection is not encrypted + return; + } + + auto& encryptedFields = encryptConfig->getFields(); + std::vector encryptedFieldRefs; + + for (const auto& index : cmd.getIndexes()) { + + // Do not allow TTL indexes on encrypted collections because automatic + // deletion of encrypted documents would require the deletion tokens + // for each encrypted field, which the server does not have. + uassert(6346501, + "TTL indexes are not allowed on encrypted collections", + !index_key_validate::isIndexTTL(index)); + + if (!index.hasField(IndexDescriptor::kUniqueFieldName) || + index.getBoolField(IndexDescriptor::kUniqueFieldName) == false) { + // skip if not attempting to create a unique index + continue; + } + + // Create the FieldRefs for each encrypted field (if not already created) + if (encryptedFieldRefs.empty() && !encryptedFields.empty()) { + std::transform(encryptedFields.begin(), + encryptedFields.end(), + std::back_inserter(encryptedFieldRefs), + [](auto& path) { return FieldRef(path.getPath()); }); + } + + // Do not allow unique indexes on encrypted fields, or prefixes of encrypted fields. + auto keyObject = index[IndexDescriptor::kKeyPatternFieldName].Obj(); + for (const auto& keyElement : keyObject) { + + FieldRef keyFieldRef(keyElement.fieldNameStringData()); + + for (const auto& encryptedFieldRef : encryptedFieldRefs) { + auto common = keyFieldRef.commonPrefixSize(encryptedFieldRef); + uassert( + 6346502, + str::stream() + << "Unique indexes are not allowed on, or a prefix of, the encrypted field " + << encryptedFieldRef.dottedField(), + common != keyFieldRef.numParts()); + uassert(6346503, + str::stream() << "Unique indexes are not allowed on keys whose prefix is " + "the encrypted field " + << encryptedFieldRef.dottedField(), + common != encryptedFieldRef.numParts()); + } + } + } +} + /** * Retrieves the commit quorum from 'cmdObj' if it is present. If it isn't, we provide a default * commit quorum, which consists of all the data-bearing nodes. @@ -423,6 +492,7 @@ CreateIndexesReply runCreateIndexesWithCoordinator(OperationContext* opCtx, } validateTTLOptions(opCtx, ns, cmd); + checkEncryptedFieldIndexRestrictions(opCtx, ns, cmd); // Preliminary checks before handing control over to IndexBuildsCoordinator: // 1) We are in a replication mode that allows for index creation. -- cgit v1.2.1