summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwin Pe <erwin.pe@mongodb.com>2022-04-21 00:10:22 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-05 15:34:06 +0000
commitb318215fa716860cfc38906fd9aa719234b16cb6 (patch)
treef55931f74eeadd02b663b1102b05f8ec2c4679e2
parent4eb4a309aff8130430c9abc70f1147819e5a151e (diff)
downloadmongo-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.js69
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp9
-rw-r--r--src/mongo/db/s/rename_collection_coordinator.cpp8
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&) {