diff options
author | Erwin Pe <erwin.pe@mongodb.com> | 2022-04-21 00:10:22 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-05 15:34:06 +0000 |
commit | b318215fa716860cfc38906fd9aa719234b16cb6 (patch) | |
tree | f55931f74eeadd02b663b1102b05f8ec2c4679e2 | |
parent | 4eb4a309aff8130430c9abc70f1147819e5a151e (diff) | |
download | mongo-b318215fa716860cfc38906fd9aa719234b16cb6.tar.gz |
SERVER-65431 Disallow renaming to/from a collection with encrypted fields
(cherry picked from commit 3904aa02b46c153193bd8110397bb0cd2f882c6b)
-rw-r--r-- | jstests/fle2/rename_encrypted_collection.js | 69 | ||||
-rw-r--r-- | src/mongo/db/catalog/rename_collection.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/s/rename_collection_coordinator.cpp | 8 |
3 files changed, 85 insertions, 1 deletions
diff --git a/jstests/fle2/rename_encrypted_collection.js b/jstests/fle2/rename_encrypted_collection.js new file mode 100644 index 00000000000..74860d54ead --- /dev/null +++ b/jstests/fle2/rename_encrypted_collection.js @@ -0,0 +1,69 @@ +// Verify renaming to/from a collection with encrypted fields is disallowed + +/** + * @tags: [ + * requires_fcv_60 + * ] + */ +load("jstests/fle2/libs/encrypted_client_util.js"); + +(function() { +'use strict'; + +const srcDbName = 'rename_encrypted_collection_src_db'; +const tgtDbName = 'rename_encrypted_collection_tgt_db'; +const dbSrc = db.getSiblingDB(srcDbName); +const dbTgt = db.getSiblingDB(tgtDbName); + +dbSrc.encrypted.drop(); +dbSrc.unencrypted.drop(); +dbSrc.renamed.drop(); +dbTgt.encrypted.drop(); +dbTgt.unencrypted.drop(); + +const sampleEncryptedFields = { + "fields": [ + { + "path": "firstName", + "keyId": UUID("11d58b8a-0c6c-4d69-a0bd-70c6d9befae9"), + "bsonType": "string", + "queries": {"queryType": "equality"} + }, + ] +}; +const srcEncryptedErrmsg = "Cannot rename an encrypted collection"; +const tgtEncryptedErrmsg = "Cannot rename to an existing encrypted collection"; + +assert.commandWorked(dbSrc.createCollection("encrypted", {encryptedFields: sampleEncryptedFields})); +assert.commandWorked(dbSrc.createCollection("unencrypted")); + +assert.commandWorked(dbTgt.createCollection("encrypted", {encryptedFields: sampleEncryptedFields})); + +jsTestLog("Test renaming encrypted collection to another namespace is prohibited"); +let res = assert.commandFailedWithCode( + dbSrc.adminCommand({renameCollection: dbSrc + ".encrypted", to: dbSrc + ".renamed"}), + ErrorCodes.IllegalOperation, + "Renaming an encrypted collection within same DB passed"); +assert.eq(res.errmsg, srcEncryptedErrmsg); + +res = assert.commandFailedWithCode( + dbSrc.adminCommand({renameCollection: dbSrc + ".encrypted", to: dbTgt + ".unencrypted"}), + ErrorCodes.IllegalOperation, + "Renaming an encrypted collection between DBs passed"); +assert.eq(res.errmsg, srcEncryptedErrmsg); + +jsTestLog("Test renaming unencrypted collection to an encrypted namespace is prohibited"); +res = assert.commandFailedWithCode( + dbSrc.adminCommand( + {renameCollection: dbSrc + ".unencrypted", to: dbSrc + ".encrypted", dropTarget: true}), + ErrorCodes.IllegalOperation, + "Renaming to an encrypted collection within same DB passed"); +assert.eq(res.errmsg, tgtEncryptedErrmsg); + +res = assert.commandFailedWithCode( + dbSrc.adminCommand( + {renameCollection: dbSrc + ".unencrypted", to: dbTgt + ".encrypted", dropTarget: true}), + ErrorCodes.IllegalOperation, + "Renaming to an encrypted collection between DBs passed"); +assert.eq(res.errmsg, tgtEncryptedErrmsg); +}()); diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp index d9aab7b34ae..186e4a38330 100644 --- a/src/mongo/db/catalog/rename_collection.cpp +++ b/src/mongo/db/catalog/rename_collection.cpp @@ -116,6 +116,10 @@ Status checkSourceAndTargetNamespaces(OperationContext* opCtx, str::stream() << "Source collection " << source.ns() << " does not exist"); } + if (sourceColl->getCollectionOptions().encryptedFieldConfig) { + return Status(ErrorCodes::IllegalOperation, "Cannot rename an encrypted collection"); + } + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection(sourceColl->uuid()); const auto targetColl = catalog->lookupCollectionByNamespace(opCtx, target); @@ -125,6 +129,11 @@ Status checkSourceAndTargetNamespaces(OperationContext* opCtx, return Status(ErrorCodes::NamespaceExists, str::stream() << "a view already exists with that name: " << target); } else { + if (targetColl->getCollectionOptions().encryptedFieldConfig) { + return Status(ErrorCodes::IllegalOperation, + "Cannot rename to an existing encrypted collection"); + } + if (!targetExistsAllowed && !options.dropTarget) return Status(ErrorCodes::NamespaceExists, "target namespace exists"); } diff --git a/src/mongo/db/s/rename_collection_coordinator.cpp b/src/mongo/db/s/rename_collection_coordinator.cpp index b8c882d4def..47db3dc63d7 100644 --- a/src/mongo/db/s/rename_collection_coordinator.cpp +++ b/src/mongo/db/s/rename_collection_coordinator.cpp @@ -176,8 +176,11 @@ ExecutorFuture<void> RenameCollectionCoordinator::_runImpl( opCtx, fromNss, MODE_IS, AutoGetCollectionViewMode::kViewsPermitted}; checkCollectionUUIDMismatch( opCtx, fromNss, *coll, _doc.getExpectedSourceUUID()); - } + uassert(ErrorCodes::IllegalOperation, + "Cannot rename an encrypted collection", + !coll || !coll->getCollectionOptions().encryptedFieldConfig); + } // Make sure the source collection exists const auto optSourceCollType = getShardedCollection(opCtx, fromNss); @@ -215,6 +218,9 @@ ExecutorFuture<void> RenameCollectionCoordinator::_runImpl( AutoGetCollection coll{opCtx, toNss, MODE_IS}; checkCollectionUUIDMismatch( opCtx, toNss, *coll, _doc.getExpectedTargetUUID()); + uassert(ErrorCodes::IllegalOperation, + "Cannot rename to an existing encrypted collection", + !coll || !coll->getCollectionOptions().encryptedFieldConfig); } } catch (const DBException&) { |