summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2022-06-28 17:20:38 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-07-29 03:16:01 +0000
commitf5aec2516bed2833b510065b96d6ab35b3467528 (patch)
tree1cdd546ce11a04eb9b411d6acfdc4193ac94bb57
parent7b9299a77fe5fa76b4e019575f38c21ff990c86b (diff)
downloadmongo-f5aec2516bed2833b510065b96d6ab35b3467528.tar.gz
SERVER-66651 restore builtin role needs applyOps permissions
(cherry picked from commit 0ba2a32577ed1d8b2bcf33ca195dce5516a484be)
-rw-r--r--jstests/auth/lib/commands_lib.js16
-rw-r--r--jstests/auth/restore_role_create_collection_via_apply_ops.js61
-rw-r--r--src/mongo/db/auth/role_graph_builtin_roles.cpp8
3 files changed, 77 insertions, 8 deletions
diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js
index 4169036623f..a04e3cc033d 100644
--- a/jstests/auth/lib/commands_lib.js
+++ b/jstests/auth/lib/commands_lib.js
@@ -324,7 +324,8 @@ var authCommandsLib = {
roles: {
dbAdminAnyDatabase: 1,
root: 1,
- __system: 1
+ __system: 1,
+ restore: 1,
},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["createCollection"]},
@@ -354,7 +355,7 @@ var authCommandsLib = {
testcases: [
{
runOnDb: adminDbName,
- roles: {__system: 1, root: 1},
+ roles: {__system: 1, root: 1, restore: 1},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["createCollection"]},
{resource: {cluster: true}, actions: ["useUUID", "forceUUID", "applyOps"]},
@@ -413,7 +414,8 @@ var authCommandsLib = {
roles: {
dbAdminAnyDatabase: 1,
root: 1,
- __system: 1
+ __system: 1,
+ restore: 1,
},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["dropCollection"]},
@@ -452,7 +454,7 @@ var authCommandsLib = {
testcases: [
{
runOnDb: adminDbName,
- roles: {__system: 1, root: 1},
+ roles: {__system: 1, root: 1, restore: 1},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["dropCollection"]},
{resource: {cluster: true}, actions: ["useUUID", "applyOps"]},
@@ -580,7 +582,7 @@ var authCommandsLib = {
testcases: [
{
runOnDb: adminDbName,
- roles: {__system: 1, root: 1},
+ roles: {__system: 1, root: 1, restore: 1},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["insert"]},
{resource: {cluster: true}, actions: ["applyOps"]},
@@ -616,7 +618,7 @@ var authCommandsLib = {
testcases: [
{
runOnDb: adminDbName,
- roles: {__system: 1, root: 1},
+ roles: {__system: 1, root: 1, restore: 1},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["insert"]},
{resource: {cluster: true}, actions: ["useUUID", "applyOps"]},
@@ -656,7 +658,7 @@ var authCommandsLib = {
// failure.
expectFail: true,
runOnDb: adminDbName,
- roles: {__system: 1, root: 1},
+ roles: {__system: 1, root: 1, restore: 1},
privileges: [
{resource: {db: firstDbName, collection: "x"}, actions: ["insert"]},
{resource: {cluster: true}, actions: ["useUUID", "applyOps"]},
diff --git a/jstests/auth/restore_role_create_collection_via_apply_ops.js b/jstests/auth/restore_role_create_collection_via_apply_ops.js
new file mode 100644
index 00000000000..be30be7db47
--- /dev/null
+++ b/jstests/auth/restore_role_create_collection_via_apply_ops.js
@@ -0,0 +1,61 @@
+// Verify that mongorestore can create a collection via applyOps
+
+(function() {
+'use strict';
+
+function makeCreateOp(collName, uuid = undefined) {
+ const op = {
+ op: 'c',
+ ns: 'test.$cmd',
+ o: {
+ create: collName,
+ idIndex: {
+ key: {_id: 1},
+ v: 2,
+ name: "_id_",
+ ns: "test." + collName,
+ },
+ },
+ };
+ if (uuid) {
+ op.ui = uuid;
+ }
+ return op;
+}
+
+function assertHasCollection(db, collName, expectUUID = undefined) {
+ const colls = db.getCollectionInfos({name: collName});
+ assert.eq(colls.length, 1, colls);
+ if (expectUUID !== undefined) {
+ assert.eq(colls[0].info.uuid, expectUUID, colls);
+ }
+}
+
+function runTest(conn) {
+ const admin = conn.getDB('admin');
+ const test = conn.getDB('test');
+ assert.commandWorked(admin.runCommand({createUser: 'admin', pwd: 'admin', roles: ['root']}));
+ assert(admin.auth('admin', 'admin'));
+
+ assert.commandWorked(
+ admin.runCommand({createUser: 'restore1', pwd: 'pwd', roles: ['restore']}));
+ admin.logout();
+
+ assert(admin.auth('restore1', 'pwd'));
+
+ // Simple create collection op.
+ assert.commandWorked(admin.runCommand({applyOps: [makeCreateOp('test1')]}));
+ assertHasCollection(test, 'test1');
+
+ // Create collection with UUID.
+ const kSpecificUUID = UUID();
+ assert.commandWorked(admin.runCommand({applyOps: [makeCreateOp('test2', kSpecificUUID)]}));
+ assertHasCollection(test, 'test2', kSpecificUUID);
+
+ admin.logout();
+}
+
+const standalone = MongoRunner.runMongod({auth: ''});
+runTest(standalone);
+MongoRunner.stopMongod(standalone);
+})(); \ No newline at end of file
diff --git a/src/mongo/db/auth/role_graph_builtin_roles.cpp b/src/mongo/db/auth/role_graph_builtin_roles.cpp
index b001cb2dc70..042c5efc9ed 100644
--- a/src/mongo/db/auth/role_graph_builtin_roles.cpp
+++ b/src/mongo/db/auth/role_graph_builtin_roles.cpp
@@ -672,7 +672,13 @@ void addRestorePrivileges(PrivilegeVector* privileges) {
Privilege::addPrivilegeToPrivilegeVector(
privileges,
Privilege(ResourcePattern::forClusterResource(),
- {ActionType::forceUUID, ActionType::useUUID}));
+ {
+ // Need to be able to force UUID consistency in sharded restores
+ ActionType::forceUUID,
+ ActionType::useUUID,
+ // Needed for `mongorestore --preserveUUID`
+ ActionType::applyOps,
+ }));
}
void addRootRolePrivileges(PrivilegeVector* privileges) {