diff options
author | Tess Avitabile <tess.avitabile@mongodb.com> | 2020-09-02 20:25:08 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-10-21 18:26:47 +0000 |
commit | 6fe78a092be6b3a87ec9a91693c7dc77bd45fe5e (patch) | |
tree | f3d4b918610223d1b47550cc20a30728fe82ee44 | |
parent | 78a269596edf46413b8533132d10da995953d5ee (diff) | |
download | mongo-6fe78a092be6b3a87ec9a91693c7dc77bd45fe5e.tar.gz |
SERVER-50116 Forbid oplog writes when replication is enabled
(cherry picked from commit 7b2913a64bc8812a9ab71ce27fe14bb2f517376f)
(cherry picked from commit 73dd69d37bc64c58a800c8d1225e35d3ca6241cb)
-rw-r--r-- | jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js | 52 | ||||
-rw-r--r-- | src/mongo/db/ops/insert.cpp | 4 |
2 files changed, 56 insertions, 0 deletions
diff --git a/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js b/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js new file mode 100644 index 00000000000..1e77d01c561 --- /dev/null +++ b/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js @@ -0,0 +1,52 @@ +/** + * Tests that oplog writes are forbidden on replica set members. In standalone mode, it is permitted + * to insert oplog entries, which will be applied during replication recovery. This behavior is + * needed for point-in-time restores, which are supported on 4.2+. + * @tags: [ + * requires_persistence, + * requires_replication, + * ] + */ +(function() { +"use strict"; + +const rst = new ReplSetTest({nodes: 1}); +rst.startSet(); +rst.initiateWithHighElectionTimeout(); + +let conn = rst.getPrimary(); +assert.commandWorked(conn.getDB("test").coll.insert({_id: 0, a: 0})); + +let oplog = conn.getDB("local").oplog.rs; + +// Construct a valid oplog entry. +const lastOplogEntry = oplog.find().sort({ts: -1}).limit(1).toArray()[0]; +const highestTS = lastOplogEntry.ts; +const toInsert = Object.extend(lastOplogEntry, { + op: "u", + ns: "test.coll", + o: {$set: {a: 1}}, + o2: {_id: 0}, + ts: Timestamp(highestTS.getTime(), highestTS.getInc() + 1) +}); + +jsTestLog("Test that oplog writes are banned when replication is enabled."); +assert.commandFailedWithCode(oplog.insert(toInsert), ErrorCodes.InvalidNamespace); + +jsTestLog("Restart the node in standalone mode."); +rst.stop(0, undefined /*signal*/, undefined /*opts*/, {forRestart: true}); +conn = rst.start(0, {noReplSet: true, noCleanData: true}); + +jsTestLog("Test that oplog writes are permitted in standalone mode."); +assert.commandWorked(conn.getDB("local").oplog.rs.insert(toInsert)); + +jsTestLog("Restart the node with replication enabled."); +rst.stop(0, undefined /*signal*/, undefined /*opts*/, {forRestart: true}); +rst.start(0, {noCleanData: true}); +conn = rst.getPrimary(); + +jsTestLog("The added oplog entry is applied as part of replication recovery."); +assert.eq({_id: 0, a: 1}, conn.getDB("test").coll.findOne()); + +rst.stopSet(); +}()); diff --git a/src/mongo/db/ops/insert.cpp b/src/mongo/db/ops/insert.cpp index dfc841588dc..4267cffe015 100644 --- a/src/mongo/db/ops/insert.cpp +++ b/src/mongo/db/ops/insert.cpp @@ -35,6 +35,7 @@ #include "mongo/bson/bson_depth.h" #include "mongo/db/logical_clock.h" #include "mongo/db/logical_time.h" +#include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/views/durable_view_catalog.h" #include "mongo/util/str.h" @@ -183,6 +184,9 @@ Status userAllowedWriteNS(StringData db, StringData coll) { if (coll == "system.profile") { return Status(ErrorCodes::InvalidNamespace, str::stream() << "cannot write to '" << db << ".system.profile'"); + } else if (db == "local" && coll == "oplog.rs" && + repl::ReplicationCoordinator::get(getGlobalServiceContext())->isReplEnabled()) { + return Status(ErrorCodes::InvalidNamespace, "cannot write to 'local.oplog.rs'"); } return userAllowedCreateNS(db, coll); } |