summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/sharding/session_info_in_oplog.js38
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/db/SConscript66
-rw-r--r--src/mongo/db/auth/sasl_commands.cpp4
-rw-r--r--src/mongo/db/auth/user.cpp31
-rw-r--r--src/mongo/db/auth/user.h14
-rw-r--r--src/mongo/db/commands.h9
-rw-r--r--src/mongo/db/commands/SConscript3
-rw-r--r--src/mongo/db/commands/shutdown.h2
-rw-r--r--src/mongo/db/commands/start_session_command.cpp59
-rw-r--r--src/mongo/db/logical_session_cache.cpp42
-rw-r--r--src/mongo/db/logical_session_cache.h25
-rw-r--r--src/mongo/db/logical_session_cache_test.cpp171
-rw-r--r--src/mongo/db/logical_session_id.cpp40
-rw-r--r--src/mongo/db/logical_session_id.h106
-rw-r--r--src/mongo/db/logical_session_id.idl52
-rw-r--r--src/mongo/db/logical_session_id_helpers.cpp155
-rw-r--r--src/mongo/db/logical_session_id_helpers.h55
-rw-r--r--src/mongo/db/logical_session_id_test.cpp237
-rw-r--r--src/mongo/db/logical_session_record.cpp72
-rw-r--r--src/mongo/db/logical_session_record.h99
-rw-r--r--src/mongo/db/logical_session_record.idl48
-rw-r--r--src/mongo/db/logical_session_record_test.cpp65
-rw-r--r--src/mongo/db/operation_context.cpp21
-rw-r--r--src/mongo/db/operation_context.h10
-rw-r--r--src/mongo/db/operation_context_test.cpp64
-rw-r--r--src/mongo/db/repl/oplog.cpp5
-rw-r--r--src/mongo/db/repl/replication_info.cpp2
-rw-r--r--src/mongo/db/repl/rs_rollback_test.cpp6
-rw-r--r--src/mongo/db/service_entry_point_mongod.cpp3
-rw-r--r--src/mongo/db/service_liason.cpp67
-rw-r--r--src/mongo/db/service_liason.h16
-rw-r--r--src/mongo/db/session_catalog.h2
-rw-r--r--src/mongo/db/session_test.cpp24
-rw-r--r--src/mongo/db/session_txn_record.idl8
-rw-r--r--src/mongo/db/sessions_collection.h4
-rw-r--r--src/mongo/db/sessions_collection_mock.cpp12
-rw-r--r--src/mongo/db/sessions_collection_mock.h11
-rw-r--r--src/mongo/db/signed_logical_session_id.cpp73
-rw-r--r--src/mongo/db/signed_logical_session_id.h115
-rw-r--r--src/mongo/db/signed_logical_session_id.idl50
-rw-r--r--src/mongo/db/signed_logical_session_id_test.cpp81
-rw-r--r--src/mongo/dbtests/cursor_manager_test.cpp12
-rw-r--r--src/mongo/s/commands/strategy.cpp5
-rw-r--r--src/mongo/s/query/SConscript1
-rw-r--r--src/mongo/s/query/cluster_client_cursor_impl_test.cpp2
-rw-r--r--src/mongo/s/query/cluster_cursor_manager_test.cpp14
-rw-r--r--src/mongo/shell/shell_utils.cpp28
-rw-r--r--src/mongo/util/uuid.h4
49 files changed, 796 insertions, 1238 deletions
diff --git a/jstests/sharding/session_info_in_oplog.js b/jstests/sharding/session_info_in_oplog.js
index 78e10be8f5b..86b4c463f0a 100644
--- a/jstests/sharding/session_info_in_oplog.js
+++ b/jstests/sharding/session_info_in_oplog.js
@@ -7,6 +7,17 @@
var checkOplog = function(mainConn, priConn) {
var lsid = UUID();
+ var uid = function() {
+ var user = mainConn.getDB("admin")
+ .runCommand({connectionStatus: 1})
+ .authInfo.authenticatedUsers[0];
+
+ if (user) {
+ return computeSHA256Block(user.user + "@" + user.db);
+ } else {
+ return computeSHA256Block("");
+ }
+ }();
////////////////////////////////////////////////////////////////////////
// Test insert command
@@ -15,7 +26,7 @@
insert: 'user',
documents: [{_id: 10}, {_id: 30}],
ordered: false,
- lsid: {id: {uuid: lsid}},
+ lsid: {id: lsid},
txnNumber: NumberLong(34),
};
@@ -26,14 +37,16 @@
var firstDoc = oplog.findOne({ns: 'test.user', 'o._id': 10});
assert(firstDoc != null);
assert(firstDoc.lsid != null);
- assert.eq(lsid, firstDoc.lsid.id.uuid);
+ assert.eq(lsid, firstDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(34), firstDoc.txnNumber);
assert.eq(0, firstDoc.stmtId);
var secondDoc = oplog.findOne({ns: 'test.user', 'o._id': 30});
assert(secondDoc != null);
assert(secondDoc.lsid != null);
- assert.eq(lsid, secondDoc.lsid.id.uuid);
+ assert.eq(lsid, secondDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(34), secondDoc.txnNumber);
assert.eq(1, secondDoc.stmtId);
@@ -48,7 +61,7 @@
{q: {_id: 30}, u: {z: 1}} // replacement
],
ordered: false,
- lsid: {id: {uuid: lsid}},
+ lsid: {id: lsid},
txnNumber: NumberLong(35),
};
@@ -57,21 +70,24 @@
firstDoc = oplog.findOne({ns: 'test.user', op: 'u', 'o2._id': 10});
assert(firstDoc != null);
assert(firstDoc.lsid != null);
- assert.eq(lsid, firstDoc.lsid.id.uuid);
+ assert.eq(lsid, firstDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(35), firstDoc.txnNumber);
assert.eq(0, firstDoc.stmtId);
secondDoc = oplog.findOne({ns: 'test.user', op: 'i', 'o._id': 20});
assert(secondDoc != null);
assert(secondDoc.lsid != null);
- assert.eq(lsid, secondDoc.lsid.id.uuid);
+ assert.eq(lsid, secondDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(35), secondDoc.txnNumber);
assert.eq(1, secondDoc.stmtId);
var thirdDoc = oplog.findOne({ns: 'test.user', op: 'u', 'o2._id': 30});
assert(thirdDoc != null);
assert(thirdDoc.lsid != null);
- assert.eq(lsid, thirdDoc.lsid.id.uuid);
+ assert.eq(lsid, thirdDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(35), thirdDoc.txnNumber);
assert.eq(2, thirdDoc.stmtId);
@@ -82,7 +98,7 @@
delete: 'user',
deletes: [{q: {_id: 10}, limit: 1}, {q: {_id: 20}, limit: 1}],
ordered: false,
- lsid: {id: {uuid: lsid}},
+ lsid: {id: lsid},
txnNumber: NumberLong(36),
};
@@ -91,14 +107,16 @@
firstDoc = oplog.findOne({ns: 'test.user', op: 'd', 'o._id': 10});
assert(firstDoc != null);
assert(firstDoc.lsid != null);
- assert.eq(lsid, firstDoc.lsid.id.uuid);
+ assert.eq(lsid, firstDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(36), firstDoc.txnNumber);
assert.eq(0, firstDoc.stmtId);
secondDoc = oplog.findOne({ns: 'test.user', op: 'd', 'o._id': 20});
assert(secondDoc != null);
assert(secondDoc.lsid != null);
- assert.eq(lsid, secondDoc.lsid.id.uuid);
+ assert.eq(lsid, secondDoc.lsid.id);
+ assert.eq(uid, firstDoc.lsid.uid);
assert.eq(NumberLong(36), secondDoc.txnNumber);
assert.eq(1, secondDoc.stmtId);
};
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index d53612857d7..67283e703b4 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -411,6 +411,7 @@ if not has_option('noshell') and usemozjs:
"shell/shell_utils_launcher.cpp",
],
LIBDEPS=[
+ 'db/logical_session_id_helpers',
'db/catalog/index_key_validate',
'db/index/external_key_generator',
'db/query/command_request_response',
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index dea25aa4e74..7a906a19450 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -206,6 +206,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'logical_session_id',
+ 'logical_session_id_helpers',
'service_context',
'$BUILD_DIR/mongo/db/auth/authorization_manager_mock_init',
'$BUILD_DIR/mongo/db/service_context_noop_init',
@@ -873,73 +874,40 @@ env.Library(
env.Idlc('logical_session_id.idl')[0],
],
LIBDEPS=[
- '$BUILD_DIR/mongo/idl/idl_parser',
- '$BUILD_DIR/mongo/util/uuid',
- '$BUILD_DIR/mongo/base',
- ],
-)
-
-env.CppUnitTest(
- target='logical_session_id_test',
- source=[
- 'logical_session_id_test.cpp',
- ],
- LIBDEPS=[
- '$BUILD_DIR/mongo/base',
- 'logical_session_id'
- ],
-)
-
-env.Library(
- target='signed_logical_session_id',
- source=[
- 'signed_logical_session_id.cpp',
- env.Idlc('signed_logical_session_id.idl')[0],
- ],
- LIBDEPS=[
'$BUILD_DIR/mongo/base',
- '$BUILD_DIR/mongo/crypto/sha1_block',
+ '$BUILD_DIR/mongo/crypto/sha256_block',
+ '$BUILD_DIR/mongo/crypto/sha_block_${MONGO_CRYPTO}',
'$BUILD_DIR/mongo/idl/idl_parser',
'$BUILD_DIR/mongo/util/uuid',
- 'logical_session_id'
- ],
-)
-
-env.CppUnitTest(
- target='signed_logical_session_id_test',
- source=[
- 'signed_logical_session_id_test.cpp',
- ],
- LIBDEPS=[
- '$BUILD_DIR/mongo/base',
- 'signed_logical_session_id',
],
)
env.Library(
- target='logical_session_record',
+ target='logical_session_id_helpers',
source=[
- 'logical_session_record.cpp',
- env.Idlc('logical_session_record.idl')[0],
+ 'logical_session_id_helpers.cpp',
],
LIBDEPS=[
- '$BUILD_DIR/mongo/base',
- '$BUILD_DIR/mongo/db/auth/user_name',
- '$BUILD_DIR/mongo/idl/idl_parser',
'logical_session_id',
- 'signed_logical_session_id',
+ 'logical_session_cache',
+ '$BUILD_DIR/mongo/db/auth/authcore',
],
)
env.CppUnitTest(
- target='logical_session_record_test',
+ target='logical_session_id_test',
source=[
- 'logical_session_record_test.cpp',
+ 'logical_session_id_test.cpp',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/service_context_noop_init',
+ '$BUILD_DIR/mongo/transport/transport_layer_mock',
+ '$BUILD_DIR/mongo/db/auth/authcore',
+ '$BUILD_DIR/mongo/db/auth/authmocks',
+ '$BUILD_DIR/mongo/db/auth/authorization_session_for_test',
'logical_session_id',
- 'logical_session_record',
+ 'logical_session_id_helpers',
],
)
@@ -954,7 +922,6 @@ env.Library(
'keys_collection_manager',
'keys_collection_manager_zero',
'logical_clock',
- 'signed_logical_session_id',
],
)
@@ -1032,7 +999,6 @@ env.Library(
],
LIBDEPS=[
'logical_session_id',
- 'logical_session_record',
'sessions_collection',
'server_parameters',
'service_liason',
@@ -1050,10 +1016,10 @@ envWithAsio.CppUnitTest(
'keys_collection_manager',
'keys_collection_document',
'logical_clock',
+ 'logical_session_id_helpers',
'logical_session_cache',
'service_liason_mock',
'sessions_collection_mock',
- 'signed_logical_session_id',
],
)
diff --git a/src/mongo/db/auth/sasl_commands.cpp b/src/mongo/db/auth/sasl_commands.cpp
index 57ad20647d8..f489e3792c6 100644
--- a/src/mongo/db/auth/sasl_commands.cpp
+++ b/src/mongo/db/auth/sasl_commands.cpp
@@ -85,7 +85,7 @@ public:
virtual bool slaveOk() const {
return true;
}
- virtual bool requiresAuth() {
+ bool requiresAuth() const override {
return false;
}
};
@@ -111,7 +111,7 @@ public:
virtual bool slaveOk() const {
return true;
}
- virtual bool requiresAuth() {
+ bool requiresAuth() const override {
return false;
}
};
diff --git a/src/mongo/db/auth/user.cpp b/src/mongo/db/auth/user.cpp
index f98fa52550c..36039d2ef14 100644
--- a/src/mongo/db/auth/user.cpp
+++ b/src/mongo/db/auth/user.cpp
@@ -41,7 +41,22 @@
namespace mongo {
-User::User(const UserName& name) : _name(name), _id(), _refCount(0), _isValid(1) {}
+namespace {
+
+SHA256Block computeDigest(const UserName& name, const boost::optional<OID>& id) {
+ const auto& fn = name.getFullName();
+
+ if (id) {
+ return SHA256Block::computeHash({id->toCDR(), ConstDataRange(fn.c_str(), fn.size())});
+ } else {
+ return SHA256Block::computeHash({ConstDataRange(fn.c_str(), fn.size())});
+ }
+};
+
+} // namespace
+
+User::User(const UserName& name)
+ : _name(name), _id(), _digest(computeDigest(_name, _id)), _refCount(0), _isValid(1) {}
User::~User() {
dassert(_refCount == 0);
@@ -55,6 +70,10 @@ const boost::optional<OID>& User::getID() const {
return _id;
}
+const SHA256Block& User::getDigest() const {
+ return _digest;
+}
+
RoleNameIterator User::getRoles() const {
return makeRoleNameIteratorForContainer(_roles);
}
@@ -87,17 +106,9 @@ const ActionSet User::getActionsForResource(const ResourcePattern& resource) con
return it->second.getActions();
}
-User* User::clone() const {
- std::unique_ptr<User> result(new User(_name));
- result->_id = _id;
- result->_privileges = _privileges;
- result->_roles = _roles;
- result->_credentials = _credentials;
- return result.release();
-}
-
void User::setID(boost::optional<OID> id) {
_id = std::move(id);
+ _digest = computeDigest(_name, _id);
}
void User::setCredentials(const CredentialData& credentials) {
diff --git a/src/mongo/db/auth/user.h b/src/mongo/db/auth/user.h
index 4d179184323..7807043652d 100644
--- a/src/mongo/db/auth/user.h
+++ b/src/mongo/db/auth/user.h
@@ -32,6 +32,7 @@
#include "mongo/base/disallow_copying.h"
#include "mongo/bson/oid.h"
+#include "mongo/crypto/sha256_block.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/resource_pattern.h"
#include "mongo/db/auth/restriction_set.h"
@@ -93,6 +94,11 @@ public:
const boost::optional<OID>& getID() const;
/**
+ * Returns a digest of the user's identity
+ */
+ const SHA256Block& getDigest() const;
+
+ /**
* Returns an iterator over the names of the user's direct roles
*/
RoleNameIterator getRoles() const;
@@ -137,11 +143,6 @@ public:
*/
uint32_t getRefCount() const;
- /**
- * Clones this user into a new, valid User object with refcount of 0.
- */
- User* clone() const;
-
// Mutators below. Mutation functions should *only* be called by the AuthorizationManager
/**
@@ -237,6 +238,9 @@ private:
// an unset _id field to be a distinct value that will fail to compare to any other id value.
boost::optional<OID> _id;
+ // Digest of the full username
+ SHA256Block _digest;
+
// Maps resource name to privilege on that resource
ResourcePrivilegeMap _privileges;
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 3f2346fe926..86fbec22161 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -148,6 +148,11 @@ public:
virtual bool shouldAffectCommandCounter() const = 0;
/**
+ * Return true if the command requires auth.
+ */
+ virtual bool requiresAuth() const = 0;
+
+ /**
* Generates help text for this command.
*/
virtual void help(std::stringstream& help) const = 0;
@@ -302,6 +307,10 @@ public:
return true;
}
+ bool requiresAuth() const override {
+ return true;
+ }
+
void help(std::stringstream& help) const override;
Status explain(OperationContext* opCtx,
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index 57e5b5683fc..c6197fed134 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -85,7 +85,8 @@ env.Library(
'$BUILD_DIR/mongo/db/lasterror',
'$BUILD_DIR/mongo/db/log_process_details',
'$BUILD_DIR/mongo/db/logical_session_cache',
- '$BUILD_DIR/mongo/db/logical_session_record',
+ '$BUILD_DIR/mongo/db/logical_session_id',
+ '$BUILD_DIR/mongo/db/logical_session_id_helpers',
'$BUILD_DIR/mongo/db/matcher/expressions',
'$BUILD_DIR/mongo/db/repl/isself',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_global',
diff --git a/src/mongo/db/commands/shutdown.h b/src/mongo/db/commands/shutdown.h
index 90db47c3fb3..655d25b367f 100644
--- a/src/mongo/db/commands/shutdown.h
+++ b/src/mongo/db/commands/shutdown.h
@@ -39,7 +39,7 @@ class CmdShutdown : public BasicCommand {
public:
CmdShutdown() : BasicCommand("shutdown") {}
- virtual bool requiresAuth() {
+ bool requiresAuth() const override {
return true;
}
virtual bool adminOnly() const {
diff --git a/src/mongo/db/commands/start_session_command.cpp b/src/mongo/db/commands/start_session_command.cpp
index 529b93b2323..cd241c7a310 100644
--- a/src/mongo/db/commands/start_session_command.cpp
+++ b/src/mongo/db/commands/start_session_command.cpp
@@ -39,7 +39,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/logical_session_cache.h"
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/logical_session_record.h"
+#include "mongo/db/logical_session_id_helpers.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/stats/top.h"
@@ -79,57 +79,30 @@ public:
const BSONObj& cmdObj,
BSONObjBuilder& result) override {
- boost::optional<OID> uid;
auto client = opCtx->getClient();
-
ServiceContext* serviceContext = client->getServiceContext();
- if (AuthorizationManager::get(serviceContext)->isAuthEnabled()) {
-
- UserName userName;
-
- auto authzSession = AuthorizationSession::get(client);
- auto userNameItr = authzSession->getAuthenticatedUserNames();
- if (userNameItr.more()) {
- userName = userNameItr.next();
- if (userNameItr.more()) {
- return appendCommandStatus(
- result,
- Status(ErrorCodes::Unauthorized,
- "must only be authenticated as exactly one user "
- "to create a logical session"));
- }
- } else {
- return appendCommandStatus(result,
- Status(ErrorCodes::Unauthorized,
- "must only be authenticated as exactly one user "
- "to create a logical session"));
- }
-
- User* user = authzSession->lookupUser(userName);
- invariant(user);
- uid = user->getID();
- }
- auto lsCache = LogicalSessionCache::get(serviceContext);
+ boost::optional<LogicalSessionId> lsid;
- auto statusWithSlsid = lsCache->signLsid(opCtx, LogicalSessionId::gen(), uid);
- if (!statusWithSlsid.isOK()) {
- return appendCommandStatus(result, statusWithSlsid.getStatus());
+ try {
+ lsid = makeLogicalSessionId(opCtx);
+ } catch (...) {
+ auto status = exceptionToStatus();
+
+ return appendCommandStatus(result, status);
}
- auto slsid = statusWithSlsid.getValue();
- auto lsRecord = LogicalSessionRecord::makeAuthoritativeRecord(
- slsid, serviceContext->getFastClockSource()->now());
- Status startSessionStatus = lsCache->startSession(std::move(slsid));
- appendCommandStatus(result, startSessionStatus);
+ auto lsCache = LogicalSessionCache::get(serviceContext);
- if (startSessionStatus.isOK()) {
- result.append("id", lsRecord.toBSON());
- result.append("timeoutMinutes", localLogicalSessionTimeoutMinutes);
- return true;
+ Status startSessionStatus = lsCache->startSession(lsid.get());
+
+ if (!startSessionStatus.isOK()) {
+ return appendCommandStatus(result, startSessionStatus);
}
- return false;
+ makeLogicalSessionToClient(lsid.get()).serialize(&result);
+
+ return true;
}
} startSessionCommand;
diff --git a/src/mongo/db/logical_session_cache.cpp b/src/mongo/db/logical_session_cache.cpp
index 0a93fd5addd..36c1625a69c 100644
--- a/src/mongo/db/logical_session_cache.cpp
+++ b/src/mongo/db/logical_session_cache.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/logical_session_cache.h"
+#include "mongo/db/logical_session_id.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/server_parameters.h"
#include "mongo/db/service_context.h"
@@ -99,15 +100,15 @@ LogicalSessionCache::~LogicalSessionCache() {
}
}
-Status LogicalSessionCache::fetchAndPromote(SignedLogicalSessionId slsid) {
+Status LogicalSessionCache::fetchAndPromote(LogicalSessionId lsid) {
// Search our local cache first
- auto promoteRes = promote(slsid);
+ auto promoteRes = promote(lsid);
if (promoteRes.isOK()) {
return promoteRes;
}
// Cache miss, must fetch from the sessions collection.
- auto res = _sessionsColl->fetchRecord(slsid);
+ auto res = _sessionsColl->fetchRecord(lsid);
// If we got a valid record, add it to our cache.
if (res.isOK()) {
@@ -124,9 +125,9 @@ Status LogicalSessionCache::fetchAndPromote(SignedLogicalSessionId slsid) {
return res.getStatus();
}
-Status LogicalSessionCache::promote(SignedLogicalSessionId slsid) {
+Status LogicalSessionCache::promote(LogicalSessionId lsid) {
stdx::unique_lock<stdx::mutex> lk(_cacheMutex);
- auto it = _cache.find(slsid.getLsid());
+ auto it = _cache.find(lsid);
if (it == _cache.end()) {
return {ErrorCodes::NoSuchSession, "no matching session record found in the cache"};
}
@@ -142,14 +143,14 @@ Status LogicalSessionCache::promote(SignedLogicalSessionId slsid) {
return Status::OK();
}
-Status LogicalSessionCache::startSession(SignedLogicalSessionId slsid) {
- // Make sure the timestamp makes sense
- auto authoritativeRecord =
- LogicalSessionRecord::makeAuthoritativeRecord(slsid, _service->now());
+Status LogicalSessionCache::startSession(LogicalSessionId lsid) {
+ LogicalSessionRecord lsr;
+ lsr.setId(lsid);
+ lsr.setLastUse(_service->now());
// Attempt to insert into the sessions collection first. This collection enforces
// unique session ids, so it will act as concurrency control for us.
- auto res = _sessionsColl->insertRecord(authoritativeRecord);
+ auto res = _sessionsColl->insertRecord(lsr);
if (!res.isOK()) {
return res;
}
@@ -158,9 +159,9 @@ Status LogicalSessionCache::startSession(SignedLogicalSessionId slsid) {
// conflicting record is not dead and is not equal to our record, an interloper
// may have ended this session and then created a new one with the same id.
// In this case, return a failure.
- auto oldRecord = _addToCache(authoritativeRecord);
+ auto oldRecord = _addToCache(lsr);
if (oldRecord) {
- if (*oldRecord != authoritativeRecord) {
+ if (*oldRecord != lsr) {
if (!_isDead(*oldRecord, _service->now())) {
return {ErrorCodes::DuplicateSession, "session with this id already exists"};
}
@@ -170,17 +171,6 @@ Status LogicalSessionCache::startSession(SignedLogicalSessionId slsid) {
return Status::OK();
}
-StatusWith<SignedLogicalSessionId> LogicalSessionCache::signLsid(OperationContext* opCtx,
- const LogicalSessionId& id,
- boost::optional<OID> userId) {
- return _service->signLsid(opCtx, id, std::move(userId));
-}
-
-Status LogicalSessionCache::validateLsid(OperationContext* opCtx,
- const SignedLogicalSessionId& slsid) {
- return _service->validateLsid(opCtx, slsid);
-}
-
void LogicalSessionCache::_refresh() {
LogicalSessionIdSet activeSessions;
LogicalSessionIdSet deadSessions;
@@ -201,9 +191,9 @@ void LogicalSessionCache::_refresh() {
for (auto& it : cacheCopy) {
auto record = it.second;
if (!_isDead(record, now)) {
- activeSessions.insert(record.getSignedLsid().getLsid());
+ activeSessions.insert(LogicalSessionId{record.getId()});
} else {
- deadSessions.insert(record.getSignedLsid().getLsid());
+ deadSessions.insert(LogicalSessionId{record.getId()});
}
}
@@ -260,7 +250,7 @@ bool LogicalSessionCache::_isDead(const LogicalSessionRecord& record, Date_t now
boost::optional<LogicalSessionRecord> LogicalSessionCache::_addToCache(
LogicalSessionRecord record) {
stdx::unique_lock<stdx::mutex> lk(_cacheMutex);
- return _cache.add(record.getSignedLsid().getLsid(), std::move(record));
+ return _cache.add(record.getId(), std::move(record));
}
} // namespace mongo
diff --git a/src/mongo/db/logical_session_cache.h b/src/mongo/db/logical_session_cache.h
index da3d521b02e..5d901c191ce 100644
--- a/src/mongo/db/logical_session_cache.h
+++ b/src/mongo/db/logical_session_cache.h
@@ -30,10 +30,8 @@
#include "mongo/base/status_with.h"
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/logical_session_record.h"
#include "mongo/db/service_liason.h"
#include "mongo/db/sessions_collection.h"
-#include "mongo/db/signed_logical_session_id.h"
#include "mongo/db/time_proof_service.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/thread.h"
@@ -120,7 +118,7 @@ public:
*
* This method does not issue networking calls.
*/
- Status promote(SignedLogicalSessionId lsid);
+ Status promote(LogicalSessionId lsid);
/**
* If the cache contains a record for this LogicalSessionId, promotes it.
@@ -129,7 +127,7 @@ public:
*
* This method may issue networking calls.
*/
- Status fetchAndPromote(SignedLogicalSessionId lsid);
+ Status fetchAndPromote(LogicalSessionId lsid);
/**
* Inserts a new authoritative session record into the cache. This method will
@@ -137,22 +135,7 @@ public:
* should only be used when starting new sessions and should not be used to
* insert records for existing sessions.
*/
- Status startSession(SignedLogicalSessionId lsid);
-
- /**
- * Generates and sets a signature for the fields in this LogicalSessionId.
- *
- * If this method is not able to acquire a key to perform the signature
- * this call will return an error.
- */
- StatusWith<SignedLogicalSessionId> signLsid(OperationContext* opCtx,
- const LogicalSessionId& id,
- boost::optional<OID> userId);
-
- /**
- * Validates that this LogicalSessionId was signed with the correct key.
- */
- Status validateLsid(OperationContext* opCtx, const SignedLogicalSessionId& lsid);
+ Status startSession(LogicalSessionId lsid);
/**
* Removes all local records in this cache. Does not remove the corresponding
@@ -184,7 +167,7 @@ private:
std::unique_ptr<SessionsCollection> _sessionsColl;
stdx::mutex _cacheMutex;
- LRUCache<LogicalSessionId, LogicalSessionRecord, LogicalSessionId::Hash> _cache;
+ LRUCache<LogicalSessionId, LogicalSessionRecord, LogicalSessionIdHash> _cache;
};
} // namespace mongo
diff --git a/src/mongo/db/logical_session_cache_test.cpp b/src/mongo/db/logical_session_cache_test.cpp
index baba6814b34..381801cecab 100644
--- a/src/mongo/db/logical_session_cache_test.cpp
+++ b/src/mongo/db/logical_session_cache_test.cpp
@@ -32,7 +32,7 @@
#include "mongo/db/auth/user_name.h"
#include "mongo/db/logical_session_cache.h"
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/logical_session_record.h"
+#include "mongo/db/logical_session_id_helpers.h"
#include "mongo/db/service_liason_mock.h"
#include "mongo/db/sessions_collection_mock.h"
#include "mongo/stdx/future.h"
@@ -97,128 +97,127 @@ private:
// Test that session cache fetches new records from the sessions collection
TEST_F(LogicalSessionCacheTest, CacheFetchesNewRecords) {
- auto signedLsid = SignedLogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
// When the record is not present (and not in the sessions collection) returns an error
- auto res = cache()->fetchAndPromote(signedLsid);
+ auto res = cache()->fetchAndPromote(lsid);
ASSERT(!res.isOK());
// When the record is not present (but is in the sessions collection) returns it
- sessions()->add(LogicalSessionRecord::makeAuthoritativeRecord(signedLsid, service()->now()));
- res = cache()->fetchAndPromote(signedLsid);
+ sessions()->add(makeLogicalSessionRecord(lsid, service()->now()));
+ res = cache()->fetchAndPromote(lsid);
ASSERT(res.isOK());
// When the record is present in the cache, returns it
- sessions()->setFetchHook([](SignedLogicalSessionId id) -> StatusWith<LogicalSessionRecord> {
+ sessions()->setFetchHook([](LogicalSessionId id) -> StatusWith<LogicalSessionRecord> {
// We should not be querying the sessions collection on the next call
ASSERT(false);
return {ErrorCodes::NoSuchSession, "no such session"};
});
- res = cache()->fetchAndPromote(signedLsid);
+ res = cache()->fetchAndPromote(lsid);
ASSERT(res.isOK());
}
// Test that the getFromCache method does not make calls to the sessions collection
TEST_F(LogicalSessionCacheTest, TestCacheHitsOnly) {
- auto signedLsid = SignedLogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
// When the record is not present (and not in the sessions collection), returns an error
- auto res = cache()->promote(signedLsid);
+ auto res = cache()->promote(lsid);
ASSERT(!res.isOK());
// When the record is not present (but is in the sessions collection), returns an error
- sessions()->add(LogicalSessionRecord::makeAuthoritativeRecord(signedLsid, service()->now()));
- res = cache()->promote(signedLsid);
+ sessions()->add(makeLogicalSessionRecord(lsid, service()->now()));
+ res = cache()->promote(lsid);
ASSERT(!res.isOK());
// When the record is present, returns the owner
- cache()->fetchAndPromote(signedLsid).transitional_ignore();
- res = cache()->promote(signedLsid);
+ cache()->fetchAndPromote(lsid).transitional_ignore();
+ res = cache()->promote(lsid);
ASSERT(res.isOK());
}
// Test that fetching from the cache updates the lastUse date of records
TEST_F(LogicalSessionCacheTest, FetchUpdatesLastUse) {
- auto signedLsid = SignedLogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto start = service()->now();
// Insert the record into the sessions collection with 'start'
- sessions()->add(LogicalSessionRecord::makeAuthoritativeRecord(signedLsid, start));
+ sessions()->add(makeLogicalSessionRecord(lsid, start));
// Fast forward time and fetch
service()->fastForward(Milliseconds(500));
ASSERT(start != service()->now());
- auto res = cache()->fetchAndPromote(signedLsid);
+ auto res = cache()->fetchAndPromote(lsid);
ASSERT(res.isOK());
// Now that we fetched, lifetime of session should be extended
service()->fastForward(kSessionTimeout - Milliseconds(500));
- res = cache()->fetchAndPromote(signedLsid);
+ res = cache()->fetchAndPromote(lsid);
ASSERT(res.isOK());
// We fetched again, so lifetime extended again
service()->fastForward(kSessionTimeout - Milliseconds(10));
- res = cache()->fetchAndPromote(signedLsid);
+ res = cache()->fetchAndPromote(lsid);
ASSERT(res.isOK());
// Fast forward and hit-only fetch
service()->fastForward(kSessionTimeout - Milliseconds(10));
- res = cache()->promote(signedLsid);
+ res = cache()->promote(lsid);
ASSERT(res.isOK());
// Lifetime extended again
service()->fastForward(Milliseconds(11));
- res = cache()->promote(signedLsid);
+ res = cache()->promote(lsid);
ASSERT(res.isOK());
// Let record expire, we should not be able to get it from the cache
service()->fastForward(kSessionTimeout + Milliseconds(1));
- res = cache()->promote(signedLsid);
+ res = cache()->promote(lsid);
ASSERT(!res.isOK());
}
// Test the startSession method
TEST_F(LogicalSessionCacheTest, StartSession) {
- auto signedLsid = SignedLogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
// Test starting a new session
- auto res = cache()->startSession(signedLsid);
+ auto res = cache()->startSession(lsid);
ASSERT(res.isOK());
- ASSERT(sessions()->has(signedLsid.getLsid()));
+ ASSERT(sessions()->has(lsid));
// Try to start a session that is already in the sessions collection and our
// local cache, should fail
- res = cache()->startSession(signedLsid);
+ res = cache()->startSession(lsid);
ASSERT(!res.isOK());
// Try to start a session that is already in the sessions collection but
// is not in our local cache, should fail
- auto record2 = LogicalSessionRecord::makeAuthoritativeRecord(SignedLogicalSessionId::gen(),
- service()->now());
- auto signedLsid2 = record2.getSignedLsid();
+ auto record2 = makeLogicalSessionRecord(makeLogicalSessionIdForTest(), service()->now());
+ auto lsid2 = record2.getId();
sessions()->add(std::move(record2));
- res = cache()->startSession(signedLsid2);
+ res = cache()->startSession(lsid2);
ASSERT(!res.isOK());
// Try to start a session that has expired from our cache, and is no
// longer in the sessions collection, should succeed
service()->fastForward(Milliseconds(kSessionTimeout.count() + 5));
- sessions()->remove(signedLsid.getLsid());
- ASSERT(!sessions()->has(signedLsid.getLsid()));
- res = cache()->startSession(signedLsid);
+ sessions()->remove(lsid);
+ ASSERT(!sessions()->has(lsid));
+ res = cache()->startSession(lsid);
ASSERT(res.isOK());
- ASSERT(sessions()->has(signedLsid.getLsid()));
+ ASSERT(sessions()->has(lsid));
}
// Test that records in the cache are properly refreshed until they expire
TEST_F(LogicalSessionCacheTest, CacheRefreshesOwnRecords) {
// Insert two records into the cache
- auto signedLsid1 = SignedLogicalSessionId::gen();
- auto signedLsid2 = SignedLogicalSessionId::gen();
- cache()->startSession(signedLsid1).transitional_ignore();
- cache()->startSession(signedLsid2).transitional_ignore();
+ auto lsid1 = makeLogicalSessionIdForTest();
+ auto lsid2 = makeLogicalSessionIdForTest();
+ cache()->startSession(lsid1).transitional_ignore();
+ cache()->startSession(lsid2).transitional_ignore();
stdx::promise<int> hitRefresh;
auto refreshFuture = hitRefresh.get_future();
@@ -241,7 +240,7 @@ TEST_F(LogicalSessionCacheTest, CacheRefreshesOwnRecords) {
auto refresh2Future = refresh2.get_future();
// Use one of the records
- auto res = cache()->fetchAndPromote(signedLsid1);
+ auto res = cache()->fetchAndPromote(lsid1);
ASSERT(res.isOK());
// Advance time so that one record expires
@@ -258,25 +257,25 @@ TEST_F(LogicalSessionCacheTest, CacheRefreshesOwnRecords) {
service()->fastForward(kSessionTimeout - kForceRefresh + Milliseconds(1));
refresh2Future.wait();
- ASSERT_EQ(refresh2Future.get(), signedLsid1.getLsid());
+ ASSERT_EQ(refresh2Future.get(), lsid1);
}
// Test that cache deletes records that fail to refresh
TEST_F(LogicalSessionCacheTest, CacheDeletesRecordsThatFailToRefresh) {
// Put two sessions into the cache
- auto signedLsid1 = SignedLogicalSessionId::gen();
- auto signedLsid2 = SignedLogicalSessionId::gen();
- cache()->startSession(signedLsid1).transitional_ignore();
- cache()->startSession(signedLsid2).transitional_ignore();
+ auto lsid1 = makeLogicalSessionIdForTest();
+ auto lsid2 = makeLogicalSessionIdForTest();
+ cache()->startSession(lsid1).transitional_ignore();
+ cache()->startSession(lsid2).transitional_ignore();
stdx::promise<void> hitRefresh;
auto refreshFuture = hitRefresh.get_future();
// Record 1 fails to refresh
- sessions()->setRefreshHook([&hitRefresh, &signedLsid1](LogicalSessionIdSet sessions) {
+ sessions()->setRefreshHook([&hitRefresh, &lsid1](LogicalSessionIdSet sessions) {
ASSERT_EQ(sessions.size(), size_t(2));
hitRefresh.set_value();
- return LogicalSessionIdSet{signedLsid1.getLsid()};
+ return LogicalSessionIdSet{lsid1};
});
// Force a refresh
@@ -284,71 +283,71 @@ TEST_F(LogicalSessionCacheTest, CacheDeletesRecordsThatFailToRefresh) {
refreshFuture.wait();
// Ensure that one record is still there and the other is gone
- auto res = cache()->promote(signedLsid1);
+ auto res = cache()->promote(lsid1);
ASSERT(!res.isOK());
- res = cache()->promote(signedLsid2);
+ res = cache()->promote(lsid2);
ASSERT(res.isOK());
}
// Test that we don't remove records that fail to refresh if they are active on the service
TEST_F(LogicalSessionCacheTest, KeepActiveSessionAliveEvenIfRefreshFails) {
// Put two sessions into the cache, one into the service
- auto signedLsid1 = SignedLogicalSessionId::gen();
- auto signedLsid2 = SignedLogicalSessionId::gen();
- cache()->startSession(signedLsid1).transitional_ignore();
- service()->add(signedLsid1.getLsid());
- cache()->startSession(signedLsid2).transitional_ignore();
+ auto lsid1 = makeLogicalSessionIdForTest();
+ auto lsid2 = makeLogicalSessionIdForTest();
+ cache()->startSession(lsid1).transitional_ignore();
+ service()->add(lsid1);
+ cache()->startSession(lsid2).transitional_ignore();
stdx::promise<void> hitRefresh;
auto refreshFuture = hitRefresh.get_future();
// SignedLsid 1 fails to refresh
- sessions()->setRefreshHook([&hitRefresh, &signedLsid1](LogicalSessionIdSet sessions) {
+ sessions()->setRefreshHook([&hitRefresh, &lsid1](LogicalSessionIdSet sessions) {
ASSERT_EQ(sessions.size(), size_t(2));
hitRefresh.set_value();
- return LogicalSessionIdSet{signedLsid1.getLsid()};
+ return LogicalSessionIdSet{lsid1};
});
// Force a refresh
service()->fastForward(kForceRefresh);
refreshFuture.wait();
- // Ensure that both signedLsids are still there
- auto res = cache()->promote(signedLsid1);
+ // Ensure that both lsids are still there
+ auto res = cache()->promote(lsid1);
ASSERT(res.isOK());
- res = cache()->promote(signedLsid2);
+ res = cache()->promote(lsid2);
ASSERT(res.isOK());
}
-// Test that session cache properly expires signedLsids after 30 minutes of no use
+// Test that session cache properly expires lsids after 30 minutes of no use
TEST_F(LogicalSessionCacheTest, BasicSessionExpiration) {
- // Insert a signedLsid
- auto signedLsid = SignedLogicalSessionId::gen();
- cache()->startSession(signedLsid).transitional_ignore();
- auto res = cache()->promote(signedLsid);
+ // Insert a lsid
+ auto lsid = makeLogicalSessionIdForTest();
+ cache()->startSession(lsid).transitional_ignore();
+ auto res = cache()->promote(lsid);
ASSERT(res.isOK());
// Force it to expire
service()->fastForward(Milliseconds(kSessionTimeout.count() + 5));
// Check that it is no longer in the cache
- res = cache()->promote(signedLsid);
+ res = cache()->promote(lsid);
ASSERT(!res.isOK());
}
// Test that we keep refreshing sessions that are active on the service
TEST_F(LogicalSessionCacheTest, LongRunningQueriesAreRefreshed) {
- auto signedLsid = SignedLogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
- // Insert one active signedLsid on the service, none in the cache
- service()->add(signedLsid.getLsid());
+ // Insert one active lsid on the service, none in the cache
+ service()->add(lsid);
stdx::mutex mutex;
stdx::condition_variable cv;
int count = 0;
- sessions()->setRefreshHook([&cv, &mutex, &count, &signedLsid](LogicalSessionIdSet sessions) {
- ASSERT_EQ(*(sessions.begin()), signedLsid.getLsid());
+ sessions()->setRefreshHook([&cv, &mutex, &count, &lsid](LogicalSessionIdSet sessions) {
+ ASSERT_EQ(*(sessions.begin()), lsid);
{
stdx::unique_lock<stdx::mutex> lk(mutex);
count++;
@@ -378,7 +377,7 @@ TEST_F(LogicalSessionCacheTest, LongRunningQueriesAreRefreshed) {
// Wait until the next job has been scheduled
waitUntilRefreshScheduled();
- // Force another refresh, check that it refreshes that active signedLsid again
+ // Force another refresh, check that it refreshes that active lsid again
service()->fastForward(kForceRefresh);
{
stdx::unique_lock<stdx::mutex> lk(mutex);
@@ -386,18 +385,18 @@ TEST_F(LogicalSessionCacheTest, LongRunningQueriesAreRefreshed) {
}
}
-// Test that the set of signedLsids we refresh is a sum of cached + active signedLsids
+// Test that the set of lsids we refresh is a sum of cached + active lsids
TEST_F(LogicalSessionCacheTest, RefreshCachedAndServiceSignedLsidsTogether) {
// Put one session into the cache, one into the service
- auto signedLsid1 = SignedLogicalSessionId::gen();
- service()->add(signedLsid1.getLsid());
- auto signedLsid2 = SignedLogicalSessionId::gen();
- cache()->startSession(signedLsid2).transitional_ignore();
+ auto lsid1 = makeLogicalSessionIdForTest();
+ service()->add(lsid1);
+ auto lsid2 = makeLogicalSessionIdForTest();
+ cache()->startSession(lsid2).transitional_ignore();
stdx::promise<void> hitRefresh;
auto refreshFuture = hitRefresh.get_future();
- // Both signedLsids refresh
+ // Both lsids refresh
sessions()->setRefreshHook([&hitRefresh](LogicalSessionIdSet sessions) {
ASSERT_EQ(sessions.size(), size_t(2));
hitRefresh.set_value();
@@ -409,18 +408,18 @@ TEST_F(LogicalSessionCacheTest, RefreshCachedAndServiceSignedLsidsTogether) {
refreshFuture.wait();
}
-// Test large sets of cache-only session signedLsids
+// Test large sets of cache-only session lsids
TEST_F(LogicalSessionCacheTest, ManySignedLsidsInCacheRefresh) {
int count = LogicalSessionCache::kLogicalSessionCacheDefaultCapacity;
for (int i = 0; i < count; i++) {
- auto signedLsid = SignedLogicalSessionId::gen();
- cache()->startSession(signedLsid).transitional_ignore();
+ auto lsid = makeLogicalSessionIdForTest();
+ cache()->startSession(lsid).transitional_ignore();
}
stdx::promise<void> hitRefresh;
auto refreshFuture = hitRefresh.get_future();
- // Check that all signedLsids refresh
+ // Check that all lsids refresh
sessions()->setRefreshHook([&hitRefresh, &count](LogicalSessionIdSet sessions) {
ASSERT_EQ(sessions.size(), size_t(count));
hitRefresh.set_value();
@@ -432,18 +431,18 @@ TEST_F(LogicalSessionCacheTest, ManySignedLsidsInCacheRefresh) {
refreshFuture.wait();
}
-// Test larger sets of service-only session signedLsids
+// Test larger sets of service-only session lsids
TEST_F(LogicalSessionCacheTest, ManyLongRunningSessionsRefresh) {
int count = LogicalSessionCache::kLogicalSessionCacheDefaultCapacity;
for (int i = 0; i < count; i++) {
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
service()->add(lsid);
}
stdx::promise<void> hitRefresh;
auto refreshFuture = hitRefresh.get_future();
- // Check that all signedLsids refresh
+ // Check that all lsids refresh
sessions()->setRefreshHook([&hitRefresh, &count](LogicalSessionIdSet sessions) {
ASSERT_EQ(sessions.size(), size_t(count));
hitRefresh.set_value();
@@ -459,10 +458,10 @@ TEST_F(LogicalSessionCacheTest, ManyLongRunningSessionsRefresh) {
TEST_F(LogicalSessionCacheTest, ManySessionsRefreshComboDeluxe) {
int count = LogicalSessionCache::kLogicalSessionCacheDefaultCapacity;
for (int i = 0; i < count; i++) {
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
service()->add(lsid);
- auto lsid2 = SignedLogicalSessionId::gen();
+ auto lsid2 = makeLogicalSessionIdForTest();
cache()->startSession(lsid2).transitional_ignore();
}
@@ -471,7 +470,7 @@ TEST_F(LogicalSessionCacheTest, ManySessionsRefreshComboDeluxe) {
int refreshes = 0;
int nRefreshed = 0;
- // Check that all signedLsids refresh successfully
+ // Check that all lsids refresh successfully
sessions()->setRefreshHook(
[&refreshes, &mutex, &cv, &nRefreshed](LogicalSessionIdSet sessions) {
{
@@ -531,7 +530,7 @@ TEST_F(LogicalSessionCacheTest, ManySessionsRefreshComboDeluxe) {
cv.wait(lk, [&refreshes] { return refreshes == 3; });
}
- // Since all but one signedLsid failed to refresh, third set should just have one signedLsid
+ // Since all but one lsid failed to refresh, third set should just have one lsid
ASSERT_EQ(nRefreshed, 1);
}
diff --git a/src/mongo/db/logical_session_id.cpp b/src/mongo/db/logical_session_id.cpp
index 36e4c6faf58..ad1dd8a496d 100644
--- a/src/mongo/db/logical_session_id.cpp
+++ b/src/mongo/db/logical_session_id.cpp
@@ -31,48 +31,18 @@
#include "mongo/db/logical_session_id.h"
#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/logical_session_cache.h"
#include "mongo/util/assert_util.h"
namespace mongo {
-LogicalSessionId::LogicalSessionId() : LogicalSessionId(UUID::gen()) {}
-
-LogicalSessionId::LogicalSessionId(Logical_session_id&& lsid) {
- static_cast<Logical_session_id&>(*this) = lsid;
-}
-
-LogicalSessionId::LogicalSessionId(UUID id) {
- setId(std::move(id));
-}
-
-LogicalSessionId LogicalSessionId::gen() {
- return {UUID::gen()};
-}
-
-StatusWith<LogicalSessionId> LogicalSessionId::parse(const std::string& s) {
- auto res = UUID::parse(s);
- if (!res.isOK()) {
- return res.getStatus();
- }
-
- return LogicalSessionId{std::move(res.getValue())};
-}
-
-LogicalSessionId LogicalSessionId::parse(const BSONObj& doc) {
- IDLParserErrorContext ctx("logical session id");
+LogicalSessionId makeLogicalSessionIdForTest() {
LogicalSessionId lsid;
- lsid.parseProtected(ctx, doc);
- return lsid;
-}
-BSONObj LogicalSessionId::toBSON() const {
- BSONObjBuilder builder;
- serialize(&builder);
- return builder.obj();
-}
+ lsid.setId(UUID::gen());
+ lsid.setUid(SHA256Block::computeHash({}));
-std::string LogicalSessionId::toString() const {
- return getId().toString();
+ return lsid;
}
} // namespace mongo
diff --git a/src/mongo/db/logical_session_id.h b/src/mongo/db/logical_session_id.h
index 230b892d934..4984a57cc30 100644
--- a/src/mongo/db/logical_session_id.h
+++ b/src/mongo/db/logical_session_id.h
@@ -45,84 +45,66 @@ const TxnNumber kUninitializedTxnNumber = -1;
class BSONObjBuilder;
-/**
- * A 128-bit unique identifier for a logical session.
- */
-class LogicalSessionId : public Logical_session_id {
-public:
- LogicalSessionId();
- LogicalSessionId(Logical_session_id&& lsid);
-
- friend class Logical_session_id;
- friend class Logical_session_record;
- friend class SignedLogicalSessionId;
-
- /**
- * Create and return a new LogicalSessionId with a random UUID.
- */
- static LogicalSessionId gen();
-
- /**
- * If the given string represents a valid UUID, constructs and returns
- * a new LogicalSessionId. Otherwise returns an error.
- */
- static StatusWith<LogicalSessionId> parse(const std::string& s);
-
- /**
- * Constructs a new LogicalSessionId out of a BSONObj. For IDL.
- */
- static LogicalSessionId parse(const BSONObj& doc);
-
- /**
- * Returns a string representation of this session id.
- */
- std::string toString() const;
-
- /**
- * Serialize this object to BSON.
- */
- BSONObj toBSON() const;
-
- inline bool operator==(const LogicalSessionId& rhs) const {
- return getId() == rhs.getId();
- }
+class OperationContext;
+
+inline bool operator==(const LogicalSessionId& lhs, const LogicalSessionId& rhs) {
+ auto makeEqualityLens = [](const auto& lsid) { return std::tie(lsid.getId(), lsid.getUid()); };
+
+ return makeEqualityLens(lhs) == makeEqualityLens(rhs);
+}
- inline bool operator!=(const LogicalSessionId& rhs) const {
- return !(*this == rhs);
+inline bool operator!=(const LogicalSessionId& lhs, const LogicalSessionId& rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool operator==(const LogicalSessionRecord& lhs, const LogicalSessionRecord& rhs) {
+ return lhs.getId() == rhs.getId();
+}
+
+inline bool operator!=(const LogicalSessionRecord& lhs, const LogicalSessionRecord& rhs) {
+ return !(lhs == rhs);
+}
+
+LogicalSessionId makeLogicalSessionIdForTest();
+
+struct LogicalSessionIdHash {
+ std::size_t operator()(const LogicalSessionId& lsid) const {
+ return _hasher(lsid.getId());
}
- /**
- * Custom hasher so LogicalSessionIds can be used in unordered data structures.
- *
- * ex: std::unordered_set<LogicalSessionId, LogicalSessionId::Hash> lsidSet;
- */
- struct Hash {
- std::size_t operator()(const LogicalSessionId& lsid) const {
- return _hasher(lsid.getId());
- }
+private:
+ UUID::Hash _hasher;
+};
- private:
- UUID::Hash _hasher;
- };
+struct LogicalSessionRecordHash {
+ std::size_t operator()(const LogicalSessionRecord& lsid) const {
+ return _hasher(lsid.getId().getId());
+ }
private:
- /**
- * Construct a LogicalSessionId from a UUID.
- */
- LogicalSessionId(UUID id);
+ UUID::Hash _hasher;
};
+
inline std::ostream& operator<<(std::ostream& s, const LogicalSessionId& lsid) {
- return (s << lsid.toString());
+ return (s << lsid.getId() << " - " << lsid.getUid());
}
inline StringBuilder& operator<<(StringBuilder& s, const LogicalSessionId& lsid) {
- return (s << lsid.toString());
+ return (s << lsid.getId().toString() << " - " << lsid.getUid().toString());
+}
+
+inline std::ostream& operator<<(std::ostream& s, const LogicalSessionFromClient& lsid) {
+ return (s << lsid.getId() << " - " << (lsid.getUid() ? lsid.getUid()->toString() : ""));
+}
+
+inline StringBuilder& operator<<(StringBuilder& s, const LogicalSessionFromClient& lsid) {
+ return (s << lsid.getId() << " - " << (lsid.getUid() ? lsid.getUid()->toString() : ""));
}
/**
* An alias for sets of session ids.
*/
-using LogicalSessionIdSet = stdx::unordered_set<LogicalSessionId, LogicalSessionId::Hash>;
+using LogicalSessionIdSet = stdx::unordered_set<LogicalSessionId, LogicalSessionIdHash>;
} // namespace mongo
diff --git a/src/mongo/db/logical_session_id.idl b/src/mongo/db/logical_session_id.idl
index b080f6d41e2..e60c57753c3 100644
--- a/src/mongo/db/logical_session_id.idl
+++ b/src/mongo/db/logical_session_id.idl
@@ -24,16 +24,10 @@ global:
imports:
- "mongo/idl/basic_types.idl"
+ - "mongo/crypto/sha256_block.idl"
types:
- UUIDIDL:
- description: "IDL representation of the UUID type"
- bson_serialization_type: object
- cpp_type: "mongo::UUID"
- deserializer: "mongo::UUID::parse"
- serializer: "mongo::UUID::toBSON"
-
TxnNumber:
description: "A strictly-increasing per-session counter, which indicates to which transaction
of a given session does the specified command belong. The combination of
@@ -50,18 +44,56 @@ types:
structs:
- logical_session_id:
+ LogicalSessionId:
description: "A struct representing a LogicalSessionId"
strict: true
fields:
- id: UUIDIDL
+ id: uuid
+ uid: sha256Block
+
+ LogicalSessionToClient:
+ description: "A struct representing a LogicalSessionId to external clients"
+ strict: true
+ fields:
+ id: uuid
+ timeoutMinutes: int
+
+ LogicalSessionRecord:
+ description: "A struct representing a LogicalSessionRecord"
+ strict: true
+ fields:
+ id: LogicalSessionId
+ lastUse: date
+
+ LogicalSessionFromClient:
+ description: "A struct representing a LogicalSessionId from external clients"
+ strict: true
+ fields:
+ id: uuid
+ uid:
+ type: sha256Block
+ optional: true
OperationSessionInfo:
+ description: "Parser for serializing sessionId/txnNumber combination"
+ strict: false
+ fields:
+ lsid:
+ type: LogicalSessionId
+ cpp_name: sessionId
+ optional: true
+ txnNumber:
+ description: "The transaction number relative to the session in which a particular write
+ operation executes."
+ type: TxnNumber
+ optional: true
+
+ OperationSessionInfoFromClient:
description: "Parser for pulling out the sessionId/txnNumber combination from commands"
strict: false
fields:
lsid:
- type: logical_session_id
+ type: LogicalSessionFromClient
cpp_name: sessionId
optional: true
txnNumber:
diff --git a/src/mongo/db/logical_session_id_helpers.cpp b/src/mongo/db/logical_session_id_helpers.cpp
new file mode 100644
index 00000000000..e152e20bafb
--- /dev/null
+++ b/src/mongo/db/logical_session_id_helpers.cpp
@@ -0,0 +1,155 @@
+/**
+ * Copyright (C) 2017 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/logical_session_id.h"
+
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/auth/user.h"
+#include "mongo/db/logical_session_cache.h"
+#include "mongo/db/operation_context.h"
+
+namespace mongo {
+
+namespace {
+
+/**
+ * This is a safe hash that will not collide with a username because all full usernames include an
+ * '@' character.
+ */
+const auto kNoAuthDigest = SHA256Block::computeHash(reinterpret_cast<const uint8_t*>(""), 0);
+
+SHA256Block lookupUserDigest(OperationContext* opCtx) {
+ auto client = opCtx->getClient();
+ ServiceContext* serviceContext = client->getServiceContext();
+
+ if (AuthorizationManager::get(serviceContext)->isAuthEnabled()) {
+ UserName userName;
+
+ auto authzSession = AuthorizationSession::get(client);
+ auto userNameItr = authzSession->getAuthenticatedUserNames();
+ if (userNameItr.more()) {
+ userName = userNameItr.next();
+ if (userNameItr.more()) {
+ uasserted(ErrorCodes::Unauthorized,
+ "must only be authenticated as exactly one user "
+ "to create a logical session");
+ }
+ } else {
+ uasserted(ErrorCodes::Unauthorized,
+ "must only be authenticated as exactly one user "
+ "to create a logical session");
+ }
+
+ User* user = authzSession->lookupUser(userName);
+ invariant(user);
+
+ return user->getDigest();
+ } else {
+ return kNoAuthDigest;
+ }
+}
+
+} // namespace
+
+LogicalSessionId makeLogicalSessionId(const LogicalSessionFromClient& fromClient,
+ OperationContext* opCtx) {
+ LogicalSessionId lsid;
+
+ lsid.setId(fromClient.getId());
+
+ if (fromClient.getUid()) {
+ auto authSession = AuthorizationSession::get(opCtx->getClient());
+
+ uassert(ErrorCodes::Unauthorized,
+ "Unauthorized to set user digest in LogicalSessionId",
+ authSession->isAuthorizedForPrivilege(
+ Privilege(ResourcePattern::forClusterResource(), ActionType::impersonate)));
+
+ lsid.setUid(*fromClient.getUid());
+ } else {
+ lsid.setUid(lookupUserDigest(opCtx));
+ }
+
+ return lsid;
+}
+
+LogicalSessionId makeLogicalSessionId(OperationContext* opCtx) {
+ LogicalSessionId id{};
+
+ id.setId(UUID::gen());
+ id.setUid(lookupUserDigest(opCtx));
+
+ return id;
+}
+
+LogicalSessionRecord makeLogicalSessionRecord(const LogicalSessionId& lsid, Date_t lastUse) {
+ LogicalSessionRecord lsr;
+
+ lsr.setId(lsid);
+ lsr.setLastUse(lastUse);
+
+ return lsr;
+}
+
+LogicalSessionToClient makeLogicalSessionToClient(const LogicalSessionId& lsid) {
+ LogicalSessionToClient id;
+ id.setId(lsid.getId());
+ id.setTimeoutMinutes(localLogicalSessionTimeoutMinutes);
+
+ return id;
+};
+
+void initializeOperationSessionInfo(OperationContext* opCtx,
+ const BSONObj& requestBody,
+ bool requiresAuth) {
+ if (!requiresAuth) {
+ return;
+ }
+
+ auto osi = OperationSessionInfoFromClient::parse(IDLParserErrorContext("OperationSessionInfo"),
+ requestBody);
+
+ if (osi.getSessionId()) {
+ opCtx->setLogicalSessionId(makeLogicalSessionId(*(osi.getSessionId()), opCtx));
+ }
+
+ if (osi.getTxnNumber()) {
+ uassert(ErrorCodes::IllegalOperation,
+ "Transaction number requires a sessionId to be specified",
+ opCtx->getLogicalSessionId());
+ uassert(ErrorCodes::BadValue,
+ "Transaction number cannot be negative",
+ *osi.getTxnNumber() >= 0);
+
+ opCtx->setTxnNumber(*osi.getTxnNumber());
+ }
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/logical_session_id_helpers.h b/src/mongo/db/logical_session_id_helpers.h
new file mode 100644
index 00000000000..5f1ff3c854e
--- /dev/null
+++ b/src/mongo/db/logical_session_id_helpers.h
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2017 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/db/logical_session_id.h"
+
+namespace mongo {
+
+LogicalSessionId makeLogicalSessionId(const LogicalSessionFromClient& lsid,
+ OperationContext* opCtx);
+LogicalSessionId makeLogicalSessionId(OperationContext* opCtx);
+LogicalSessionRecord makeLogicalSessionRecord(const LogicalSessionId& lsid, Date_t lastUse);
+LogicalSessionToClient makeLogicalSessionToClient(const LogicalSessionId& lsid);
+
+/**
+ * Parses the session information from the body of a request and installs it on the current
+ * operation context. Must only be called once per operation and should be done right in the
+ * beginning.
+ *
+ * Throws if the sessionId/txnNumber combination is not properly formatted.
+ *
+ * requiresAuth specifies if the command we're initializing operationSessionInfo for requires
+ * authorization or not. This can be determined by invoking ->requiresAuth() on the parsed command.
+ */
+void initializeOperationSessionInfo(OperationContext* opCtx,
+ const BSONObj& requestBody,
+ bool requiresAuth);
+
+} // namespace mongo
diff --git a/src/mongo/db/logical_session_id_test.cpp b/src/mongo/db/logical_session_id_test.cpp
index c9e86639c4a..410292ef801 100644
--- a/src/mongo/db/logical_session_id_test.cpp
+++ b/src/mongo/db/logical_session_id_test.cpp
@@ -30,56 +30,225 @@
#include <string>
-#include "mongo/bson/bsonmisc.h"
-#include "mongo/bson/bsonobj.h"
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/bson/bsontypes.h"
#include "mongo/db/logical_session_id.h"
+
+#include "mongo/db/auth/action_set.h"
+#include "mongo/db/auth/action_type.h"
+#include "mongo/db/auth/authorization_manager.h"
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/auth/authorization_session_for_test.h"
+#include "mongo/db/auth/authz_manager_external_state_mock.h"
+#include "mongo/db/auth/authz_session_external_state_mock.h"
+#include "mongo/db/auth/user.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/logical_session_id_helpers.h"
+#include "mongo/db/operation_context_noop.h"
+#include "mongo/db/server_options.h"
+#include "mongo/db/service_context_noop.h"
+#include "mongo/transport/session.h"
+#include "mongo/transport/transport_layer_mock.h"
#include "mongo/unittest/unittest.h"
-#include "mongo/util/uuid.h"
namespace mongo {
namespace {
-TEST(LogicalSessionIdTest, ToAndFromStringTest) {
- // Round-trip a UUID string
- auto uuid = UUID::gen();
- auto uuidString = uuid.toString();
+class LogicalSessionIdTest : public ::mongo::unittest::Test {
+public:
+ AuthzManagerExternalStateMock* managerState;
+ transport::TransportLayerMock transportLayer;
+ transport::SessionHandle session;
+ ServiceContextNoop serviceContext;
+ ServiceContext::UniqueClient client;
+ ServiceContext::UniqueOperationContext _opCtx;
+ AuthzSessionExternalStateMock* sessionState;
+ AuthorizationManager* authzManager;
+ AuthorizationSessionForTest* authzSession;
+
+ void setUp() {
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k36);
+ session = transportLayer.createSession();
+ client = serviceContext.makeClient("testClient", session);
+ RestrictionEnvironment::set(
+ session, stdx::make_unique<RestrictionEnvironment>(SockAddr(), SockAddr()));
+ _opCtx = client->makeOperationContext();
+ auto localManagerState = stdx::make_unique<AuthzManagerExternalStateMock>();
+ managerState = localManagerState.get();
+ managerState->setAuthzVersion(AuthorizationManager::schemaVersion26Final);
+ auto uniqueAuthzManager =
+ stdx::make_unique<AuthorizationManager>(std::move(localManagerState));
+ authzManager = uniqueAuthzManager.get();
+ AuthorizationManager::set(&serviceContext, std::move(uniqueAuthzManager));
+ auto localSessionState = stdx::make_unique<AuthzSessionExternalStateMock>(authzManager);
+ sessionState = localSessionState.get();
+
+ auto localauthzSession =
+ stdx::make_unique<AuthorizationSessionForTest>(std::move(localSessionState));
+ authzSession = localauthzSession.get();
+
+ AuthorizationSession::set(client.get(), std::move(localauthzSession));
+ authzManager->setAuthEnabled(true);
+ }
+
+ User* addSimpleUser(UserName un) {
+ ASSERT_OK(managerState->insertPrivilegeDocument(
+ _opCtx.get(),
+ BSON("user" << un.getUser() << "db" << un.getDB() << "credentials" << BSON("MONGODB-CR"
+ << "a")
+ << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWrite"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), un));
+ return authzSession->lookupUser(un);
+ }
+
+ User* addClusterUser(UserName un) {
+ ASSERT_OK(managerState->insertPrivilegeDocument(
+ _opCtx.get(),
+ BSON("user" << un.getUser() << "db" << un.getDB() << "credentials" << BSON("MONGODB-CR"
+ << "a")
+ << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "__system"
+ << "db"
+ << "admin"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), un));
+ return authzSession->lookupUser(un);
+ }
+};
+
+TEST_F(LogicalSessionIdTest, ConstructorFromClientWithoutPassedUid) {
+ auto id = UUID::gen();
+ User* user = addSimpleUser(UserName("simple", "test"));
+
+ LogicalSessionFromClient req;
+ req.setId(id);
+
+ LogicalSessionId lsid = makeLogicalSessionId(req, _opCtx.get());
+ ASSERT_EQ(lsid.getId(), id);
+ ASSERT_EQ(lsid.getUid(), user->getDigest());
+}
+
+TEST_F(LogicalSessionIdTest, ConstructorFromClientWithoutPassedUidAndWithoutAuthedUser) {
+ auto id = UUID::gen();
+
+ LogicalSessionFromClient req;
+ req.setId(id);
+
+ ASSERT_THROWS(makeLogicalSessionId(req, _opCtx.get()), UserException);
+}
+
+TEST_F(LogicalSessionIdTest, ConstructorFromClientWithPassedUidWithPermissions) {
+ auto id = UUID::gen();
+ auto uid = SHA256Block{};
+ addClusterUser(UserName("cluster", "test"));
- auto res = LogicalSessionId::parse(uuidString);
- ASSERT(res.isOK());
+ LogicalSessionFromClient req;
+ req.setId(id);
+ req.setUid(uid);
- auto lsidString = res.getValue().toString();
- ASSERT_EQUALS(uuidString, lsidString);
+ LogicalSessionId lsid = makeLogicalSessionId(req, _opCtx.get());
- // Test with a bad string
- res = LogicalSessionId::parse("not a session id!");
- ASSERT(!res.isOK());
+ ASSERT_EQ(lsid.getId(), id);
+ ASSERT_EQ(lsid.getUid(), uid);
}
-TEST(LogicalSessionIdTest, FromBSONTest) {
- auto uuid = UUID::gen();
+TEST_F(LogicalSessionIdTest, ConstructorFromClientWithPassedUidWithoutAuthedUser) {
+ auto id = UUID::gen();
+ auto uid = SHA256Block{};
+
+ LogicalSessionFromClient req;
+ req.setId(id);
+ req.setUid(uid);
+
+ ASSERT_THROWS(makeLogicalSessionId(req, _opCtx.get()), UserException);
+}
+
+TEST_F(LogicalSessionIdTest, ConstructorFromClientWithPassedUidWithoutPermissions) {
+ auto id = UUID::gen();
+ auto uid = SHA256Block{};
+ addSimpleUser(UserName("simple", "test"));
+
+ LogicalSessionFromClient req;
+ req.setId(id);
+ req.setUid(uid);
- BSONObjBuilder b;
- b.append("id", uuid.toBSON());
- auto bson = b.done();
+ ASSERT_THROWS(makeLogicalSessionId(req, _opCtx.get()), UserException);
+}
+
+TEST_F(LogicalSessionIdTest, GenWithUser) {
+ User* user = addSimpleUser(UserName("simple", "test"));
+ auto lsid = makeLogicalSessionId(_opCtx.get());
+
+ ASSERT_EQ(lsid.getUid(), user->getDigest());
+}
+
+TEST_F(LogicalSessionIdTest, GenWithMultipleAuthedUsers) {
+ addSimpleUser(UserName("simple", "test"));
+ addSimpleUser(UserName("simple", "test2"));
+
+ ASSERT_THROWS(makeLogicalSessionId(_opCtx.get()), UserException);
+}
+
+TEST_F(LogicalSessionIdTest, GenWithoutAuthedUser) {
+ ASSERT_THROWS(makeLogicalSessionId(_opCtx.get()), UserException);
+}
+
+TEST_F(LogicalSessionIdTest, InitializeOperationSessionInfo_NoSessionIdNoTransactionNumber) {
+ addSimpleUser(UserName("simple", "test"));
+ initializeOperationSessionInfo(_opCtx.get(), BSON("TestCmd" << 1), true);
+
+ ASSERT(!_opCtx->getLogicalSessionId());
+ ASSERT(!_opCtx->getTxnNumber());
+}
+
+TEST_F(LogicalSessionIdTest, InitializeOperationSessionInfo_SessionIdNoTransactionNumber) {
+ addSimpleUser(UserName("simple", "test"));
+ LogicalSessionFromClient lsid{};
+ lsid.setId(UUID::gen());
+
+ initializeOperationSessionInfo(_opCtx.get(),
+ BSON("TestCmd" << 1 << "lsid" << lsid.toBSON() << "OtherField"
+ << "TestField"),
+ true);
+
+ ASSERT(_opCtx->getLogicalSessionId());
+ ASSERT_EQ(lsid.getId(), _opCtx->getLogicalSessionId()->getId());
+
+ ASSERT(!_opCtx->getTxnNumber());
+}
+
+TEST_F(LogicalSessionIdTest, InitializeOperationSessionInfo_MissingSessionIdWithTransactionNumber) {
+ addSimpleUser(UserName("simple", "test"));
+ ASSERT_THROWS_CODE(
+ initializeOperationSessionInfo(_opCtx.get(),
+ BSON("TestCmd" << 1 << "txnNumber" << 100LL << "OtherField"
+ << "TestField"),
+ true),
+ UserException,
+ ErrorCodes::IllegalOperation);
+}
- auto lsid = LogicalSessionId::parse(bson);
- ASSERT_EQUALS(lsid.toString(), uuid.toString());
+TEST_F(LogicalSessionIdTest, InitializeOperationSessionInfo_SessionIdAndTransactionNumber) {
+ addSimpleUser(UserName("simple", "test"));
+ LogicalSessionFromClient lsid;
+ lsid.setId(UUID::gen());
- // Dump back to BSON, make sure we get the same thing
- auto bsonDump = lsid.toBSON();
- ASSERT_EQ(bsonDump.woCompare(bson), 0);
+ initializeOperationSessionInfo(
+ _opCtx.get(),
+ BSON("TestCmd" << 1 << "lsid" << lsid.toBSON() << "txnNumber" << 100LL << "OtherField"
+ << "TestField"),
+ true);
- // Try parsing mal-formatted bson objs
- ASSERT_THROWS(LogicalSessionId::parse(BSON("hi"
- << "there")),
- UserException);
+ ASSERT(_opCtx->getLogicalSessionId());
+ ASSERT_EQ(lsid.getId(), _opCtx->getLogicalSessionId()->getId());
- ASSERT_THROWS(LogicalSessionId::parse(BSON("id"
- << "not a session id!")),
- UserException);
- ASSERT_THROWS(LogicalSessionId::parse(BSON("id" << 14)), UserException);
+ ASSERT(_opCtx->getTxnNumber());
+ ASSERT_EQ(100, *_opCtx->getTxnNumber());
}
} // namespace
diff --git a/src/mongo/db/logical_session_record.cpp b/src/mongo/db/logical_session_record.cpp
deleted file mode 100644
index 51ca629962b..00000000000
--- a/src/mongo/db/logical_session_record.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (C) 2017 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include <utility>
-
-#include "mongo/db/logical_session_record.h"
-
-#include "mongo/bson/bsonobjbuilder.h"
-
-namespace mongo {
-
-StatusWith<LogicalSessionRecord> LogicalSessionRecord::parse(const BSONObj& bson) {
- try {
- IDLParserErrorContext ctxt("logical session record");
- LogicalSessionRecord record;
- record.parseProtected(ctxt, bson);
- return record;
- } catch (std::exception e) {
- return exceptionToStatus();
- }
-}
-
-LogicalSessionRecord LogicalSessionRecord::makeAuthoritativeRecord(SignedLogicalSessionId id,
- Date_t now) {
- return LogicalSessionRecord(std::move(id), std::move(now));
-}
-
-BSONObj LogicalSessionRecord::toBSON() const {
- BSONObjBuilder builder;
- serialize(&builder);
- return builder.obj();
-}
-
-std::string LogicalSessionRecord::toString() const {
- return str::stream() << "LogicalSessionRecord"
- << " Id: '" << getSignedLsid() << "'"
- << " Last-use: " << getLastUse().toString();
-}
-
-LogicalSessionRecord::LogicalSessionRecord(SignedLogicalSessionId id, Date_t now) {
- setSignedLsid(std::move(id));
- setLastUse(now);
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/logical_session_record.h b/src/mongo/db/logical_session_record.h
deleted file mode 100644
index 6d8662327ab..00000000000
--- a/src/mongo/db/logical_session_record.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Copyright (C) 2017 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include <boost/optional.hpp>
-#include <utility>
-
-#include "mongo/bson/bsonobj.h"
-#include "mongo/db/logical_session_record_gen.h"
-#include "mongo/db/signed_logical_session_id.h"
-#include "mongo/util/time_support.h"
-
-namespace mongo {
-
-/**
- * This class is the in-memory representation of a logical session record.
- *
- * The BSON representation of a session record follows this form:
- *
- * {
- * lsid : SignedLogicalSessionId,
- * lastUse : Date_t
- * }
- */
-class LogicalSessionRecord : public Logical_session_record {
-public:
- /**
- * Constructs and returns a LogicalSessionRecord from a BSON representation,
- * or throws an error. For IDL.
- */
- static StatusWith<LogicalSessionRecord> parse(const BSONObj& bson);
-
- /**
- * Construct a new record, for a new session that does not yet have an
- * authoritative record in the sessions collection. This method should
- * only be used when the caller is intending to make a new authoritative
- * record and subsequently insert that record into the sessions collection.
- */
- static LogicalSessionRecord makeAuthoritativeRecord(SignedLogicalSessionId id, Date_t now);
-
- /**
- * Return a BSON representation of this session record.
- */
- BSONObj toBSON() const;
-
- /**
- * Return a string represenation of this session record.
- */
- std::string toString() const;
-
- inline bool operator==(const LogicalSessionRecord& rhs) const {
- return getSignedLsid() == rhs.getSignedLsid();
- }
-
- inline bool operator!=(const LogicalSessionRecord& rhs) const {
- return !(*this == rhs);
- }
-
-private:
- LogicalSessionRecord() = default;
-
- LogicalSessionRecord(SignedLogicalSessionId id, Date_t now);
-};
-
-inline std::ostream& operator<<(std::ostream& s, const LogicalSessionRecord& record) {
- return (s << record.toString());
-}
-
-inline StringBuilder& operator<<(StringBuilder& s, const LogicalSessionRecord& record) {
- return (s << record.toString());
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/logical_session_record.idl b/src/mongo/db/logical_session_record.idl
deleted file mode 100644
index 25e2ac65b76..00000000000
--- a/src/mongo/db/logical_session_record.idl
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (C) 2017 MongoDB Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License, version 3,
-# as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-# This IDL file describes the BSON format for a LogicalSessionRecord, and
-# handles the serialization to and deserialization from its BSON representation
-# for that class.
-
-global:
- cpp_namespace: "mongo"
- cpp_includes:
- - "mongo/db/logical_session_id.h"
- - "mongo/db/signed_logical_session_id.h"
-
-imports:
- - "mongo/idl/basic_types.idl"
- - "mongo/db/signed_logical_session_id.idl"
-
-types:
- SignedLogicalSessionIdIDL:
- description: "IDL representation of the SignedLogicalSessionId cpp type"
- bson_serialization_type: object
- cpp_type: "mongo::SignedLogicalSessionId"
- deserializer: "mongo::SignedLogicalSessionId::parse"
- serializer: "mongo::SignedLogicalSessionId::toBSON"
-
-structs:
-
- logical_session_record:
- description: "A struct representing a LogicalSessionRecord"
- fields:
- signedLsid:
- description: "The id for this session record"
- type: SignedLogicalSessionIdIDL
- lastUse:
- description: "The time at which this record was last used. Note: the date expressed in this in-memory record object may not match the date on the authoritative record for this session, which is stored in the sessions collection."
- type: date
diff --git a/src/mongo/db/logical_session_record_test.cpp b/src/mongo/db/logical_session_record_test.cpp
deleted file mode 100644
index 659d23efa5b..00000000000
--- a/src/mongo/db/logical_session_record_test.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright (C) 2017 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-
-#include "mongo/bson/bsonmisc.h"
-#include "mongo/bson/bsonobj.h"
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/bson/bsontypes.h"
-#include "mongo/db/logical_session_id.h"
-#include "mongo/db/logical_session_record.h"
-#include "mongo/db/logical_session_record_gen.h"
-#include "mongo/unittest/unittest.h"
-
-namespace mongo {
-namespace {
-
-TEST(LogicalSessionRecordTest, ToAndFromBSONTest) {
- // Round-trip a BSON obj
- auto lsid = LogicalSessionId::gen();
- SignedLogicalSessionId slsid{lsid, boost::none, 1, SHA1Block{}};
- auto lastUse = Date_t::now();
- auto bson = BSON("signedLsid" << slsid.toBSON() << "lastUse" << lastUse);
-
- // Make a session record out of this
- auto res = LogicalSessionRecord::parse(bson);
- ASSERT(res.isOK());
- auto record = res.getValue();
-
- ASSERT_EQ(record.getSignedLsid(), slsid);
- ASSERT_EQ(record.getLastUse(), lastUse);
-
- // Dump back to bson, make sure we get the same thing
- auto bsonDump = record.toBSON();
- ASSERT_EQ(bsonDump.woCompare(bson), 0);
-}
-
-} // namespace
-} // namespace mongo
diff --git a/src/mongo/db/operation_context.cpp b/src/mongo/db/operation_context.cpp
index d04760cd69d..848f1319ef0 100644
--- a/src/mongo/db/operation_context.cpp
+++ b/src/mongo/db/operation_context.cpp
@@ -393,25 +393,4 @@ Date_t OperationContext::getExpirationDateForWaitForValue(Milliseconds waitFor)
return getServiceContext()->getPreciseClockSource()->now() + waitFor;
}
-void initializeOperationSessionInfo(OperationContext* opCtx, const BSONObj& requestBody) {
- auto osi =
- OperationSessionInfo::parse(IDLParserErrorContext("OperationSessionInfo"), requestBody);
-
- if (osi.getSessionId()) {
- auto lsid = *osi.getSessionId();
- opCtx->setLogicalSessionId(LogicalSessionId(std::move(lsid)));
- }
-
- if (osi.getTxnNumber()) {
- uassert(ErrorCodes::IllegalOperation,
- "Transaction number requires a sessionId to be specified",
- opCtx->getLogicalSessionId());
- uassert(ErrorCodes::BadValue,
- "Transaction number cannot be negative",
- *osi.getTxnNumber() >= 0);
-
- opCtx->setTxnNumber(*osi.getTxnNumber());
- }
-}
-
} // namespace mongo
diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h
index 9bacdde641c..68641488d48 100644
--- a/src/mongo/db/operation_context.h
+++ b/src/mongo/db/operation_context.h
@@ -547,14 +547,4 @@ private:
const bool _shouldReplicateWrites;
};
} // namespace repl
-
-/**
- * Parses the session information from the body of a request and installs it on the current
- * operation context. Must only be called once per operation and should be done right in the
- * beginning.
- *
- * Throws if the sessionId/txnNumber combination is not properly formatted.
- */
-void initializeOperationSessionInfo(OperationContext* opCtx, const BSONObj& requestBody);
-
} // namespace mongo
diff --git a/src/mongo/db/operation_context_test.cpp b/src/mongo/db/operation_context_test.cpp
index 5174e599748..b5c8fe2c91d 100644
--- a/src/mongo/db/operation_context_test.cpp
+++ b/src/mongo/db/operation_context_test.cpp
@@ -89,7 +89,7 @@ TEST(OperationContextTest, SessionIdNoTransactionNumber) {
auto client = serviceCtx->makeClient("OperationContextTest");
auto opCtx = client->makeOperationContext();
- const auto lsid = assertGet(LogicalSessionId::parse("00000000-abab-4000-8000-000000000000"));
+ const auto lsid = makeLogicalSessionIdForTest();
opCtx->setLogicalSessionId(lsid);
ASSERT(opCtx->getLogicalSessionId());
@@ -103,7 +103,7 @@ TEST(OperationContextTest, SessionIdAndTransactionNumber) {
auto client = serviceCtx->makeClient("OperationContextTest");
auto opCtx = client->makeOperationContext();
- const auto lsid = assertGet(LogicalSessionId::parse("00000000-abab-4000-8000-000000000000"));
+ const auto lsid = makeLogicalSessionIdForTest();
opCtx->setLogicalSessionId(lsid);
opCtx->setTxnNumber(5);
@@ -111,66 +111,6 @@ TEST(OperationContextTest, SessionIdAndTransactionNumber) {
ASSERT_EQUALS(5, *opCtx->getTxnNumber());
}
-TEST(OperationContextTest, InitializeOperationSessionInfo_NoSessionIdNoTransactionNumber) {
- auto serviceCtx = stdx::make_unique<ServiceContextNoop>();
- auto client = serviceCtx->makeClient("OperationContextTest");
- auto opCtx = client->makeOperationContext();
-
- initializeOperationSessionInfo(opCtx.get(), BSON("TestCmd" << 1));
-
- ASSERT(!opCtx->getLogicalSessionId());
- ASSERT(!opCtx->getTxnNumber());
-}
-
-TEST(OperationContextTest, InitializeOperationSessionInfo_SessionIdNoTransactionNumber) {
- auto serviceCtx = stdx::make_unique<ServiceContextNoop>();
- auto client = serviceCtx->makeClient("OperationContextTest");
- auto opCtx = client->makeOperationContext();
-
- LogicalSessionId lsid;
-
- initializeOperationSessionInfo(opCtx.get(),
- BSON("TestCmd" << 1 << "lsid" << lsid.toBSON() << "OtherField"
- << "TestField"));
-
- ASSERT(opCtx->getLogicalSessionId());
- ASSERT_EQ(lsid, *opCtx->getLogicalSessionId());
-
- ASSERT(!opCtx->getTxnNumber());
-}
-
-TEST(OperationContextTest, InitializeOperationSessionInfo_MissingSessionIdWithTransactionNumber) {
- auto serviceCtx = stdx::make_unique<ServiceContextNoop>();
- auto client = serviceCtx->makeClient("OperationContextTest");
- auto opCtx = client->makeOperationContext();
-
- ASSERT_THROWS_CODE(
- initializeOperationSessionInfo(opCtx.get(),
- BSON("TestCmd" << 1 << "txnNumber" << 100LL << "OtherField"
- << "TestField")),
- UserException,
- ErrorCodes::IllegalOperation);
-}
-
-TEST(OperationContextTest, InitializeOperationSessionInfo_SessionIdAndTransactionNumber) {
- auto serviceCtx = stdx::make_unique<ServiceContextNoop>();
- auto client = serviceCtx->makeClient("OperationContextTest");
- auto opCtx = client->makeOperationContext();
-
- LogicalSessionId lsid;
-
- initializeOperationSessionInfo(
- opCtx.get(),
- BSON("TestCmd" << 1 << "lsid" << lsid.toBSON() << "txnNumber" << 100LL << "OtherField"
- << "TestField"));
-
- ASSERT(opCtx->getLogicalSessionId());
- ASSERT_EQ(lsid, *opCtx->getLogicalSessionId());
-
- ASSERT(opCtx->getTxnNumber());
- ASSERT_EQ(100, *opCtx->getTxnNumber());
-}
-
TEST(OperationContextTest, OpCtxGroup) {
OperationContextGroup group1;
ASSERT_TRUE(group1.isEmpty());
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 951cf713c66..a3888344f9d 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -306,11 +306,8 @@ void appendSessionInfo(OperationContext* opCtx, BSONObjBuilder* builder, StmtId
return;
}
- Logical_session_id lsid;
- lsid.setId(logicalSessionId->getId());
-
OperationSessionInfo sessionInfo;
- sessionInfo.setSessionId(lsid);
+ sessionInfo.setSessionId(*logicalSessionId);
sessionInfo.setTxnNumber(txnNum);
sessionInfo.serialize(builder);
diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp
index af7db98cf92..b8d5e9969e3 100644
--- a/src/mongo/db/repl/replication_info.cpp
+++ b/src/mongo/db/repl/replication_info.cpp
@@ -213,7 +213,7 @@ public:
class CmdIsMaster : public BasicCommand {
public:
- virtual bool requiresAuth() {
+ bool requiresAuth() const override {
return false;
}
virtual bool slaveOk() const {
diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp
index 8d28647a343..0e750b4b958 100644
--- a/src/mongo/db/repl/rs_rollback_test.cpp
+++ b/src/mongo/db/repl/rs_rollback_test.cpp
@@ -1405,8 +1405,8 @@ DEATH_TEST_F(RSRollbackTest, LocalEntryWithTxnNumberWithoutStmtIdIsFatal, "invar
const auto txnNumber = BSON("txnNumber" << 1LL);
const auto noSessionIdOrStmtId = validOplogEntry.addField(txnNumber.firstElement());
- const auto uuid = UUID::gen();
- const auto sessionId = BSON("lsid" << BSON("id" << uuid.toBSON()));
+ const auto lsid = makeLogicalSessionIdForTest();
+ const auto sessionId = BSON("lsid" << lsid.toBSON());
const auto noStmtId = noSessionIdOrStmtId.addField(sessionId.firstElement());
ASSERT_THROWS(updateFixUpInfoFromLocalOplogEntry(fui, noStmtId).transitional_ignore(),
RSFatalException);
@@ -1442,7 +1442,7 @@ TEST(RSRollbackTest, LocalEntryWithTxnNumberAddsTransactionTableDocToBeRefetched
<< "stmtId"
<< 1
<< "lsid"
- << BSON("id" << UUID::gen().toBSON()));
+ << makeLogicalSessionIdForTest().toBSON());
ASSERT_OK(updateFixUpInfoFromLocalOplogEntry(fui, entryWithTxnNumber));
// If txnNumber is present, the session transactions table document corresponding to the oplog
diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp
index 89fd940be08..0802fcedc45 100644
--- a/src/mongo/db/service_entry_point_mongod.cpp
+++ b/src/mongo/db/service_entry_point_mongod.cpp
@@ -49,6 +49,7 @@
#include "mongo/db/lasterror.h"
#include "mongo/db/logical_clock.h"
#include "mongo/db/logical_session_id.h"
+#include "mongo/db/logical_session_id_helpers.h"
#include "mongo/db/logical_time_validator.h"
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/ops/write_ops_exec.h"
@@ -539,7 +540,7 @@ void execCommandDatabase(OperationContext* opCtx,
rpc::readRequestMetadata(opCtx, request.body);
rpc::TrackingMetadata::get(opCtx).initWithOperName(command->getName());
- initializeOperationSessionInfo(opCtx, request.body);
+ initializeOperationSessionInfo(opCtx, request.body, command->requiresAuth());
std::string dbname = request.getDatabase().toString();
uassert(
diff --git a/src/mongo/db/service_liason.cpp b/src/mongo/db/service_liason.cpp
index 96bb92d2b00..22edb98b5c2 100644
--- a/src/mongo/db/service_liason.cpp
+++ b/src/mongo/db/service_liason.cpp
@@ -36,73 +36,6 @@
namespace mongo {
-namespace {
-
-const int kSignatureSize = sizeof(UUID) + sizeof(OID);
-
-SHA1Block computeSignature(const SignedLogicalSessionId* id, TimeProofService::Key key) {
- // Write the uuid and user id to a block for signing.
- char signatureBlock[kSignatureSize] = {0};
- DataRangeCursor cursor(signatureBlock, signatureBlock + kSignatureSize);
- auto res = cursor.writeAndAdvance<ConstDataRange>(id->getLsid().getId().toCDR());
- invariant(res.isOK());
- if (auto userId = id->getUserId()) {
- res = cursor.writeAndAdvance<ConstDataRange>(userId->toCDR());
- invariant(res.isOK());
- }
-
- // Compute the signature.
- return SHA1Block::computeHmac(
- key.data(), key.size(), reinterpret_cast<uint8_t*>(signatureBlock), kSignatureSize);
-}
-
-KeysCollectionManagerZero kKeysCollectionManagerZero{"HMAC"};
-
-} // namespace
-
ServiceLiason::~ServiceLiason() = default;
-StatusWith<SignedLogicalSessionId> ServiceLiason::signLsid(OperationContext* opCtx,
- const LogicalSessionId& lsid,
- boost::optional<OID> userId) {
- auto& keyManager = kKeysCollectionManagerZero;
-
- auto logicalTime = LogicalClock::get(_context())->getClusterTime();
- auto res = keyManager.getKeyForSigning(opCtx, logicalTime);
- if (!res.isOK()) {
- return res.getStatus();
- }
-
- SignedLogicalSessionId signedLsid;
- signedLsid.setUserId(std::move(userId));
- signedLsid.setLsid(lsid);
-
- auto keyDoc = res.getValue();
- signedLsid.setKeyId(keyDoc.getKeyId());
-
- auto signature = computeSignature(&signedLsid, keyDoc.getKey());
- signedLsid.setSignature(std::move(signature));
-
- return signedLsid;
-}
-
-Status ServiceLiason::validateLsid(OperationContext* opCtx, const SignedLogicalSessionId& id) {
- auto& keyManager = kKeysCollectionManagerZero;
-
- // Attempt to get the correct key.
- auto logicalTime = LogicalClock::get(_context())->getClusterTime();
- auto res = keyManager.getKeyForValidation(opCtx, id.getKeyId(), logicalTime);
- if (!res.isOK()) {
- return res.getStatus();
- }
-
- // Re-compute the signature, and see that it matches.
- auto signature = computeSignature(&id, res.getValue().getKey());
- if (signature != id.getSignature()) {
- return {ErrorCodes::NoSuchSession, "Signature validation failed."};
- }
-
- return Status::OK();
-}
-
} // namespace mongo
diff --git a/src/mongo/db/service_liason.h b/src/mongo/db/service_liason.h
index b74b9c0f8d4..ed7bcf0df86 100644
--- a/src/mongo/db/service_liason.h
+++ b/src/mongo/db/service_liason.h
@@ -29,7 +29,6 @@
#pragma once
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/signed_logical_session_id.h"
#include "mongo/stdx/functional.h"
#include "mongo/util/periodic_runner.h"
#include "mongo/util/time_support.h"
@@ -77,21 +76,6 @@ public:
*/
virtual Date_t now() const = 0;
- /**
- * Generates and sets a signature for the fields in this LogicalSessionId.
- *
- * If this method is not able to acquire a key to perform the signature
- * this call will return an error.
- */
- StatusWith<SignedLogicalSessionId> signLsid(OperationContext* opCtx,
- const LogicalSessionId& lsid,
- boost::optional<OID> userId);
-
- /**
- * Validates that this LogicalSessionId was signed with the correct key.
- */
- Status validateLsid(OperationContext* opCtx, const SignedLogicalSessionId& id);
-
protected:
/**
* Returns the service context.
diff --git a/src/mongo/db/session_catalog.h b/src/mongo/db/session_catalog.h
index c6a67f6c44c..5d2ab0c17e1 100644
--- a/src/mongo/db/session_catalog.h
+++ b/src/mongo/db/session_catalog.h
@@ -129,7 +129,7 @@ private:
using SessionRuntimeInfoMap = stdx::unordered_map<LogicalSessionId,
std::shared_ptr<SessionRuntimeInfo>,
- LogicalSessionId::Hash>;
+ LogicalSessionIdHash>;
/**
* Returns a session, previously clecked out through 'checkoutSession', available again.
diff --git a/src/mongo/db/session_test.cpp b/src/mongo/db/session_test.cpp
index b52068b7fb4..902a632a1ee 100644
--- a/src/mongo/db/session_test.cpp
+++ b/src/mongo/db/session_test.cpp
@@ -111,7 +111,7 @@ private:
};
TEST_F(SessionTest, CanCreateNewSessionEntry) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
Session txnState(sessionId);
@@ -141,7 +141,7 @@ TEST_F(SessionTest, CanCreateNewSessionEntry) {
}
TEST_F(SessionTest, StartingOldTxnShouldAssert) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
Session txnState(sessionId);
@@ -154,7 +154,7 @@ TEST_F(SessionTest, StartingOldTxnShouldAssert) {
}
TEST_F(SessionTest, StartingNewSessionWithCompatibleEntryInStorage) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
const Timestamp origTs(985, 15);
@@ -193,7 +193,7 @@ TEST_F(SessionTest, StartingNewSessionWithCompatibleEntryInStorage) {
}
TEST_F(SessionTest, StartingNewSessionWithOlderEntryInStorageShouldUpdateEntry) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
TxnNumber txnNum = 20;
const Timestamp origTs(985, 15);
@@ -232,7 +232,7 @@ TEST_F(SessionTest, StartingNewSessionWithOlderEntryInStorageShouldUpdateEntry)
}
TEST_F(SessionTest, StartingNewSessionWithNewerEntryInStorageShouldAssert) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
TxnNumber txnNum = 20;
const Timestamp origTs(985, 15);
@@ -271,7 +271,7 @@ TEST_F(SessionTest, StartingNewSessionWithNewerEntryInStorageShouldAssert) {
}
TEST_F(SessionTest, StoreOpTime) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
const Timestamp ts1(100, 42);
@@ -337,7 +337,7 @@ TEST_F(SessionTest, StoreOpTime) {
}
TEST_F(SessionTest, CanBumpTransactionIdIfNewer) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
TxnNumber txnNum = 20;
const Timestamp ts1(100, 42);
@@ -397,7 +397,7 @@ TEST_F(SessionTest, CanBumpTransactionIdIfNewer) {
}
TEST_F(SessionTest, StartingNewSessionWithDroppedTableShouldAssert) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
const auto& ns = NamespaceString::kSessionTransactionsTableNamespace;
@@ -413,7 +413,7 @@ TEST_F(SessionTest, StartingNewSessionWithDroppedTableShouldAssert) {
}
TEST_F(SessionTest, SaveTxnProgressShouldAssertIfTableIsDropped) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
const Timestamp ts1(100, 42);
@@ -433,14 +433,14 @@ TEST_F(SessionTest, SaveTxnProgressShouldAssertIfTableIsDropped) {
}
TEST_F(SessionTest, TwoSessionsShouldBeIndependent) {
- const auto sessionId1 = LogicalSessionId::gen();
+ const auto sessionId1 = makeLogicalSessionIdForTest();
const TxnNumber txnNum1 = 20;
const Timestamp ts1(1903, 42);
Session txnState1(sessionId1);
txnState1.begin(opCtx(), txnNum1);
- const auto sessionId2 = LogicalSessionId::gen();
+ const auto sessionId2 = makeLogicalSessionIdForTest();
const TxnNumber txnNum2 = 300;
const Timestamp ts2(671, 5);
@@ -498,7 +498,7 @@ TEST_F(SessionTest, TwoSessionsShouldBeIndependent) {
}
TEST_F(SessionTest, CheckStatementExecuted) {
- const auto sessionId = LogicalSessionId::gen();
+ const auto sessionId = makeLogicalSessionIdForTest();
const TxnNumber txnNum = 20;
const StmtId stmtId = 5;
diff --git a/src/mongo/db/session_txn_record.idl b/src/mongo/db/session_txn_record.idl
index 42c6a107805..3a9dc02328d 100644
--- a/src/mongo/db/session_txn_record.idl
+++ b/src/mongo/db/session_txn_record.idl
@@ -35,14 +35,6 @@ imports:
- "mongo/idl/basic_types.idl"
- "mongo/db/logical_session_id.idl"
-types:
- LogicalSessionId:
- description: "Logical_session_id"
- bson_serialization_type: object
- cpp_type: "mongo::LogicalSessionId"
- deserializer: "mongo::LogicalSessionId::parse"
- serializer: "mongo::LogicalSessionId::toBSON"
-
structs:
sessionTxnRecord:
description: "A document used for storing session transaction states."
diff --git a/src/mongo/db/sessions_collection.h b/src/mongo/db/sessions_collection.h
index 7692e634275..4a7503a293e 100644
--- a/src/mongo/db/sessions_collection.h
+++ b/src/mongo/db/sessions_collection.h
@@ -29,8 +29,6 @@
#pragma once
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/logical_session_record.h"
-#include "mongo/db/signed_logical_session_id.h"
namespace mongo {
@@ -48,7 +46,7 @@ public:
* Returns a LogicalSessionRecord for the given session id. This method
* may run networking operations on the calling thread.
*/
- virtual StatusWith<LogicalSessionRecord> fetchRecord(SignedLogicalSessionId id) = 0;
+ virtual StatusWith<LogicalSessionRecord> fetchRecord(LogicalSessionId id) = 0;
/**
* Inserts the given record into the sessions collection. This method may run
diff --git a/src/mongo/db/sessions_collection_mock.cpp b/src/mongo/db/sessions_collection_mock.cpp
index 1079605badd..832213e1223 100644
--- a/src/mongo/db/sessions_collection_mock.cpp
+++ b/src/mongo/db/sessions_collection_mock.cpp
@@ -65,8 +65,7 @@ void MockSessionsCollectionImpl::clearHooks() {
_remove = stdx::bind(&MockSessionsCollectionImpl::_removeRecords, this, stdx::placeholders::_1);
}
-StatusWith<LogicalSessionRecord> MockSessionsCollectionImpl::fetchRecord(
- SignedLogicalSessionId id) {
+StatusWith<LogicalSessionRecord> MockSessionsCollectionImpl::fetchRecord(LogicalSessionId id) {
return _fetch(std::move(id));
}
@@ -84,7 +83,7 @@ void MockSessionsCollectionImpl::removeRecords(LogicalSessionIdSet sessions) {
void MockSessionsCollectionImpl::add(LogicalSessionRecord record) {
stdx::unique_lock<stdx::mutex> lk(_mutex);
- _sessions.insert({record.getSignedLsid().getLsid(), std::move(record)});
+ _sessions.insert({record.getId(), std::move(record)});
}
void MockSessionsCollectionImpl::remove(LogicalSessionId lsid) {
@@ -106,12 +105,11 @@ const MockSessionsCollectionImpl::SessionMap& MockSessionsCollectionImpl::sessio
return _sessions;
}
-StatusWith<LogicalSessionRecord> MockSessionsCollectionImpl::_fetchRecord(
- SignedLogicalSessionId id) {
+StatusWith<LogicalSessionRecord> MockSessionsCollectionImpl::_fetchRecord(LogicalSessionId id) {
stdx::unique_lock<stdx::mutex> lk(_mutex);
// If we do not have this record, return an error
- auto it = _sessions.find(id.getLsid());
+ auto it = _sessions.find(id);
if (it == _sessions.end()) {
return {ErrorCodes::NoSuchSession, "No matching record in the sessions collection"};
}
@@ -121,7 +119,7 @@ StatusWith<LogicalSessionRecord> MockSessionsCollectionImpl::_fetchRecord(
Status MockSessionsCollectionImpl::_insertRecord(LogicalSessionRecord record) {
stdx::unique_lock<stdx::mutex> lk(_mutex);
- auto res = _sessions.insert({record.getSignedLsid().getLsid(), std::move(record)});
+ auto res = _sessions.insert({record.getId(), std::move(record)});
// We should never try to insert the same record twice. In theory this could
// happen because of a UUID conflict.
diff --git a/src/mongo/db/sessions_collection_mock.h b/src/mongo/db/sessions_collection_mock.h
index afa04bfd9db..870d0434991 100644
--- a/src/mongo/db/sessions_collection_mock.h
+++ b/src/mongo/db/sessions_collection_mock.h
@@ -29,7 +29,6 @@
#pragma once
#include "mongo/db/logical_session_id.h"
-#include "mongo/db/logical_session_record.h"
#include "mongo/db/sessions_collection.h"
#include "mongo/stdx/functional.h"
#include "mongo/stdx/mutex.h"
@@ -55,11 +54,11 @@ namespace mongo {
class MockSessionsCollectionImpl {
public:
using SessionMap =
- stdx::unordered_map<LogicalSessionId, LogicalSessionRecord, LogicalSessionId::Hash>;
+ stdx::unordered_map<LogicalSessionId, LogicalSessionRecord, LogicalSessionIdHash>;
MockSessionsCollectionImpl();
- using FetchHook = stdx::function<StatusWith<LogicalSessionRecord>(SignedLogicalSessionId)>;
+ using FetchHook = stdx::function<StatusWith<LogicalSessionRecord>(LogicalSessionId)>;
using InsertHook = stdx::function<Status(LogicalSessionRecord)>;
using RefreshHook = stdx::function<LogicalSessionIdSet(LogicalSessionIdSet)>;
using RemoveHook = stdx::function<void(LogicalSessionIdSet)>;
@@ -74,7 +73,7 @@ public:
void clearHooks();
// Forwarding methods from the MockSessionsCollection
- StatusWith<LogicalSessionRecord> fetchRecord(SignedLogicalSessionId id);
+ StatusWith<LogicalSessionRecord> fetchRecord(LogicalSessionId id);
Status insertRecord(LogicalSessionRecord record);
LogicalSessionIdSet refreshSessions(LogicalSessionIdSet sessions);
void removeRecords(LogicalSessionIdSet sessions);
@@ -88,7 +87,7 @@ public:
private:
// Default implementations, may be overridden with custom hooks.
- StatusWith<LogicalSessionRecord> _fetchRecord(SignedLogicalSessionId id);
+ StatusWith<LogicalSessionRecord> _fetchRecord(LogicalSessionId id);
Status _insertRecord(LogicalSessionRecord record);
LogicalSessionIdSet _refreshSessions(LogicalSessionIdSet sessions);
void _removeRecords(LogicalSessionIdSet sessions);
@@ -112,7 +111,7 @@ public:
explicit MockSessionsCollection(std::shared_ptr<MockSessionsCollectionImpl> impl)
: _impl(std::move(impl)) {}
- StatusWith<LogicalSessionRecord> fetchRecord(SignedLogicalSessionId id) override {
+ StatusWith<LogicalSessionRecord> fetchRecord(LogicalSessionId id) override {
return _impl->fetchRecord(std::move(id));
}
diff --git a/src/mongo/db/signed_logical_session_id.cpp b/src/mongo/db/signed_logical_session_id.cpp
deleted file mode 100644
index a284fb6344b..00000000000
--- a/src/mongo/db/signed_logical_session_id.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Copyright (C) 2017 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/signed_logical_session_id.h"
-
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/util/assert_util.h"
-
-namespace mongo {
-
-SignedLogicalSessionId SignedLogicalSessionId::gen() {
- return SignedLogicalSessionId();
-}
-
-SignedLogicalSessionId::SignedLogicalSessionId() {
- setLsid(LogicalSessionId::gen());
-}
-
-SignedLogicalSessionId::SignedLogicalSessionId(LogicalSessionId lsid,
- boost::optional<OID> userId,
- long long keyId,
- SHA1Block signature) {
- setLsid(std::move(lsid));
- setUserId(std::move(userId));
- setKeyId(std::move(keyId));
- setSignature(std::move(signature));
-}
-
-SignedLogicalSessionId SignedLogicalSessionId::parse(const BSONObj& doc) {
- IDLParserErrorContext ctx("signed logical session id");
- SignedLogicalSessionId lsid;
- lsid.parseProtected(ctx, doc);
- return lsid;
-}
-
-BSONObj SignedLogicalSessionId::toBSON() const {
- BSONObjBuilder builder;
- serialize(&builder);
- return builder.obj();
-}
-
-std::string SignedLogicalSessionId::toString() const {
- return getLsid().toString();
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/signed_logical_session_id.h b/src/mongo/db/signed_logical_session_id.h
deleted file mode 100644
index 632f645c623..00000000000
--- a/src/mongo/db/signed_logical_session_id.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * Copyright (C) 2017 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include <string>
-
-#include "mongo/base/status_with.h"
-#include "mongo/bson/oid.h"
-#include "mongo/db/logical_session_id.h"
-#include "mongo/db/signed_logical_session_id_gen.h"
-#include "mongo/stdx/unordered_set.h"
-#include "mongo/util/uuid.h"
-
-namespace mongo {
-
-class BSONObjBuilder;
-class OperationContext;
-
-/**
- * An identifier for a logical session. A LogicalSessionId has the following components:
- *
- * - A 128-bit unique identifier (UUID)
- * - An optional user id (ObjectId)
- * - A key id (long long)
- * - An HMAC signature (SHA1Block)
- */
-class SignedLogicalSessionId : public Signed_logical_session_id {
-public:
- using Owner = boost::optional<OID>;
-
- friend class Logical_session_id;
- friend class Logical_session_record;
-
- using keyIdType = long long;
-
- /**
- * Create and return a new LogicalSessionId with a random UUID. This method
- * should be used for testing only. The generated SignedLogicalSessionId will
- * not be signed, and will have no owner.
- */
- static SignedLogicalSessionId gen();
-
- /**
- * Creates a new SignedLogicalSessionId.
- */
- SignedLogicalSessionId(LogicalSessionId lsid,
- boost::optional<OID> userId,
- long long keyId,
- SHA1Block signature);
-
- /**
- * Constructs a new LogicalSessionId out of a BSONObj. For IDL.
- */
- static SignedLogicalSessionId parse(const BSONObj& doc);
-
- /**
- * Returns a string representation of this session id.
- */
- std::string toString() const;
-
- /**
- * Serialize this object to BSON.
- */
- BSONObj toBSON() const;
-
- inline bool operator==(const SignedLogicalSessionId& rhs) const {
- return getLsid() == rhs.getLsid() && getUserId() == rhs.getUserId() &&
- getKeyId() == rhs.getKeyId() && getSignature() == rhs.getSignature();
- }
-
- inline bool operator!=(const SignedLogicalSessionId& rhs) const {
- return !(*this == rhs);
- }
-
- /**
- * This constructor exists for IDL only.
- */
- SignedLogicalSessionId();
-};
-
-inline std::ostream& operator<<(std::ostream& s, const SignedLogicalSessionId& lsid) {
- return (s << lsid.toString());
-}
-
-inline StringBuilder& operator<<(StringBuilder& s, const SignedLogicalSessionId& lsid) {
- return (s << lsid.toString());
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/signed_logical_session_id.idl b/src/mongo/db/signed_logical_session_id.idl
deleted file mode 100644
index 634d4731a52..00000000000
--- a/src/mongo/db/signed_logical_session_id.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (C) 2017 MongoDB Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License, version 3,
-# as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-# This IDL file describes the BSON format for a LogicalSessionId, and
-# handles the serialization to and deserialization from its BSON representation
-# for that class.
-
-global:
- cpp_namespace: "mongo"
- cpp_includes:
- - "mongo/util/uuid.h"
- - "mongo/db/logical_session_id.h"
-
-imports:
- - "mongo/crypto/sha1_block.idl"
- - "mongo/db/logical_session_id.idl"
- - "mongo/idl/basic_types.idl"
-
-types:
- LogicalSessionIdIdl:
- description: "IDL representation of the LogicalSessionId cpp type"
- bson_serialization_type: object
- cpp_type: "mongo::LogicalSessionId"
- deserializer: "mongo::LogicalSessionId::parse"
- serializer: "mongo::LogicalSessionId::toBSON"
-
-structs:
-
- signed_logical_session_id:
- description: "A struct representing a SignedLogicalSessionId"
- strict: true
- fields:
- lsid: LogicalSessionIdIdl
- userId:
- optional: true
- type: objectid
- keyId: long
- signature: sha1Block
diff --git a/src/mongo/db/signed_logical_session_id_test.cpp b/src/mongo/db/signed_logical_session_id_test.cpp
deleted file mode 100644
index 2622d65f2f8..00000000000
--- a/src/mongo/db/signed_logical_session_id_test.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Copyright (C) 2017 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include <string>
-
-#include "mongo/bson/bsonmisc.h"
-#include "mongo/bson/bsonobj.h"
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/bson/bsontypes.h"
-#include "mongo/crypto/sha1_block.h"
-#include "mongo/db/logical_session_id.h"
-#include "mongo/db/signed_logical_session_id.h"
-#include "mongo/unittest/unittest.h"
-#include "mongo/util/uuid.h"
-
-namespace mongo {
-namespace {
-
-TEST(SignedLogicalSessionIdTest, ConstructWithLsid) {
- auto lsid = LogicalSessionId::gen();
- SignedLogicalSessionId slsid(lsid, boost::none, 1, SHA1Block{});
- ASSERT_EQ(slsid.getLsid(), lsid);
-}
-
-TEST(SignedLogicalSessionIdTest, FromBSONTest) {
- auto lsid = LogicalSessionId::gen();
-
- BSONObjBuilder b;
- b.append("lsid", lsid.toBSON());
- b.append("keyId", 4ll);
- char buffer[SHA1Block::kHashLength] = {0};
- b.appendBinData("signature", SHA1Block::kHashLength, BinDataGeneral, buffer);
- auto bson = b.done();
-
- auto slsid = SignedLogicalSessionId::parse(bson);
- ASSERT_EQ(slsid.getLsid(), lsid);
-
- // Dump back to BSON, make sure we get the same thing
- auto bsonDump = slsid.toBSON();
- ASSERT_EQ(bsonDump.woCompare(bson), 0);
-
- // Try parsing mal-formatted bson objs
- ASSERT_THROWS(SignedLogicalSessionId::parse(BSON("hi"
- << "there")),
- UserException);
-
- ASSERT_THROWS(SignedLogicalSessionId::parse(BSON("lsid"
- << "not a session id!")),
- UserException);
- ASSERT_THROWS(SignedLogicalSessionId::parse(BSON("lsid" << 14)), UserException);
-}
-
-} // namespace
-} // namespace mongo
diff --git a/src/mongo/dbtests/cursor_manager_test.cpp b/src/mongo/dbtests/cursor_manager_test.cpp
index 6abd9844de7..6505a64bea0 100644
--- a/src/mongo/dbtests/cursor_manager_test.cpp
+++ b/src/mongo/dbtests/cursor_manager_test.cpp
@@ -441,7 +441,7 @@ TEST_F(CursorManagerTestCustomOpCtx, LogicalSessionIdOnOperationCtxTest) {
// Cursors created on an op ctx with a session id have a session id.
{
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto opCtx2 = _queryServiceContext->makeOperationContext(lsid);
auto pinned2 = makeCursor(opCtx2.get());
@@ -469,7 +469,7 @@ TEST_F(CursorManagerTestCustomOpCtx, CursorsWithoutSessions) {
*/
TEST_F(CursorManagerTestCustomOpCtx, OneCursorWithASession) {
// Add a cursor with a session to the cursor manager.
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto opCtx = _queryServiceContext->makeOperationContext(lsid);
auto pinned = makeCursor(opCtx.get());
@@ -501,7 +501,7 @@ TEST_F(CursorManagerTestCustomOpCtx, OneCursorWithASession) {
*/
TEST_F(CursorManagerTestCustomOpCtx, MultipleCursorsWithSameSession) {
// Add two cursors on the same session to the cursor manager.
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto opCtx = _queryServiceContext->makeOperationContext(lsid);
auto pinned = makeCursor(opCtx.get());
auto pinned2 = makeCursor(opCtx.get());
@@ -510,7 +510,7 @@ TEST_F(CursorManagerTestCustomOpCtx, MultipleCursorsWithSameSession) {
auto cursorId2 = pinned2.getCursor()->cursorid();
// Retrieve all sessions - set should contain just lsid.
- stdx::unordered_set<LogicalSessionId, LogicalSessionId::Hash> lsids;
+ stdx::unordered_set<LogicalSessionId, LogicalSessionIdHash> lsids;
useCursorManager()->appendActiveSessions(&lsids);
ASSERT_EQ(lsids.size(), size_t(1));
ASSERT(lsids.find(lsid) != lsids.end());
@@ -541,8 +541,8 @@ TEST_F(CursorManagerTestCustomOpCtx, MultipleCursorsWithSameSession) {
* Test a manager with multiple cursors running inside of different sessions.
*/
TEST_F(CursorManagerTestCustomOpCtx, MultipleCursorsMultipleSessions) {
- auto lsid1 = LogicalSessionId::gen();
- auto lsid2 = LogicalSessionId::gen();
+ auto lsid1 = makeLogicalSessionIdForTest();
+ auto lsid2 = makeLogicalSessionIdForTest();
CursorId cursor1;
CursorId cursor2;
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index 90b9748732b..b6037760773 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -42,6 +42,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
#include "mongo/db/logical_clock.h"
+#include "mongo/db/logical_session_id_helpers.h"
#include "mongo/db/logical_time_validator.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/namespace_string.h"
@@ -256,12 +257,12 @@ void runAgainstRegistered(OperationContext* opCtx,
return;
}
+ initializeOperationSessionInfo(opCtx, request.body, c->requiresAuth());
+
execCommandClient(opCtx, c, request, anObjBuilder);
}
void runCommand(OperationContext* opCtx, const OpMsgRequest& request, BSONObjBuilder&& builder) {
- initializeOperationSessionInfo(opCtx, request.body);
-
// Handle command option maxTimeMS.
uassert(ErrorCodes::InvalidOptions,
"no such command option $maxTimeMs; use maxTimeMS instead",
diff --git a/src/mongo/s/query/SConscript b/src/mongo/s/query/SConscript
index 39bc9dcf017..f2a7b25cb28 100644
--- a/src/mongo/s/query/SConscript
+++ b/src/mongo/s/query/SConscript
@@ -131,6 +131,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/logical_session_id',
],
)
diff --git a/src/mongo/s/query/cluster_client_cursor_impl_test.cpp b/src/mongo/s/query/cluster_client_cursor_impl_test.cpp
index 6c10cf18530..549a692d720 100644
--- a/src/mongo/s/query/cluster_client_cursor_impl_test.cpp
+++ b/src/mongo/s/query/cluster_client_cursor_impl_test.cpp
@@ -164,7 +164,7 @@ TEST(ClusterClientCursorImpl, LogicalSessionIdsOnCursors) {
// Make a cursor with an lsid
auto mockStage2 = stdx::make_unique<RouterStageMock>();
ClusterClientCursorParams params2(NamespaceString("test"), {});
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
ClusterClientCursorImpl cursor2{std::move(mockStage2), std::move(params2), lsid};
ASSERT(*(cursor2.getLsid()) == lsid);
}
diff --git a/src/mongo/s/query/cluster_cursor_manager_test.cpp b/src/mongo/s/query/cluster_cursor_manager_test.cpp
index 35bbf4ad847..46377d2f483 100644
--- a/src/mongo/s/query/cluster_cursor_manager_test.cpp
+++ b/src/mongo/s/query/cluster_cursor_manager_test.cpp
@@ -969,7 +969,7 @@ TEST_F(ClusterCursorManagerTest, CursorsWithoutSessions) {
*/
TEST_F(ClusterCursorManagerTest, OneCursorWithASession) {
// Add a cursor with a session to the cursor manager.
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto cursorId = assertGet(
getManager()->registerCursor(nullptr,
allocateMockCursor(lsid),
@@ -1003,7 +1003,7 @@ TEST_F(ClusterCursorManagerTest, OneCursorWithASession) {
*/
TEST_F(ClusterCursorManagerTest, GetSessionIdsWhileCheckedOut) {
// Add a cursor with a session to the cursor manager.
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto cursorId = assertGet(
getManager()->registerCursor(nullptr,
allocateMockCursor(lsid),
@@ -1024,7 +1024,7 @@ TEST_F(ClusterCursorManagerTest, GetSessionIdsWhileCheckedOut) {
*/
TEST_F(ClusterCursorManagerTest, MultipleCursorsWithSameSession) {
// Add two cursors on the same session to the cursor manager.
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
auto cursorId1 = assertGet(
getManager()->registerCursor(nullptr,
allocateMockCursor(lsid),
@@ -1039,7 +1039,7 @@ TEST_F(ClusterCursorManagerTest, MultipleCursorsWithSameSession) {
ClusterCursorManager::CursorLifetime::Mortal));
// Retrieve all sessions - set should contain just lsid.
- stdx::unordered_set<LogicalSessionId, LogicalSessionId::Hash> lsids;
+ stdx::unordered_set<LogicalSessionId, LogicalSessionIdHash> lsids;
getManager()->appendActiveSessions(&lsids);
ASSERT_EQ(lsids.size(), size_t(1));
ASSERT(lsids.find(lsid) != lsids.end());
@@ -1069,8 +1069,8 @@ TEST_F(ClusterCursorManagerTest, MultipleCursorsWithSameSession) {
* Test a manager with multiple cursors running inside of different sessions.
*/
TEST_F(ClusterCursorManagerTest, MultipleCursorsMultipleSessions) {
- auto lsid1 = LogicalSessionId::gen();
- auto lsid2 = LogicalSessionId::gen();
+ auto lsid1 = makeLogicalSessionIdForTest();
+ auto lsid2 = makeLogicalSessionIdForTest();
// Register two cursors with different lsids, and one without.
CursorId cursor1 = assertGet(
@@ -1116,7 +1116,7 @@ TEST_F(ClusterCursorManagerTest, MultipleCursorsMultipleSessions) {
TEST_F(ClusterCursorManagerTest, ManyCursorsManySessions) {
const int count = 10000;
for (int i = 0; i < count; i++) {
- auto lsid = LogicalSessionId::gen();
+ auto lsid = makeLogicalSessionIdForTest();
ASSERT_OK(
getManager()->registerCursor(nullptr,
allocateMockCursor(lsid),
diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp
index 4c1d70f6f03..d0189a75432 100644
--- a/src/mongo/shell/shell_utils.cpp
+++ b/src/mongo/shell/shell_utils.cpp
@@ -183,6 +183,33 @@ BSONObj validateIndexKey(const BSONObj& a, void* data) {
return BSON("" << BSON("ok" << true));
}
+BSONObj computeSHA256Block(const BSONObj& a, void* data) {
+ std::vector<ConstDataRange> blocks;
+
+ auto ele = a[0];
+
+ BSONObjBuilder bob;
+ switch (ele.type()) {
+ case BinData: {
+ int len;
+ const char* ptr = ele.binData(len);
+ SHA256Block::computeHash({ConstDataRange(ptr, len)}).appendAsBinData(bob, ""_sd);
+
+ break;
+ }
+ case String: {
+ auto str = ele.valueStringData();
+ SHA256Block::computeHash({ConstDataRange(str.rawData(), str.size())})
+ .appendAsBinData(bob, ""_sd);
+ break;
+ }
+ default:
+ uasserted(ErrorCodes::BadValue, "Can only computeSHA256Block of strings and bindata");
+ }
+
+ return bob.obj();
+}
+
BSONObj replMonitorStats(const BSONObj& a, void* data) {
uassert(17134,
"replMonitorStats requires a single string argument (the ReplSet name)",
@@ -226,6 +253,7 @@ void installShellUtils(Scope& scope) {
scope.injectNative("getBuildInfo", getBuildInfo);
scope.injectNative("isKeyTooLarge", isKeyTooLarge);
scope.injectNative("validateIndexKey", validateIndexKey);
+ scope.injectNative("computeSHA256Block", computeSHA256Block);
#ifndef MONGO_SAFE_SHELL
// can't launch programs
diff --git a/src/mongo/util/uuid.h b/src/mongo/util/uuid.h
index 74139dcdbbf..09a6751fc1f 100644
--- a/src/mongo/util/uuid.h
+++ b/src/mongo/util/uuid.h
@@ -54,7 +54,9 @@ class UUID {
// Make the IDL generated parser a friend
friend class One_UUID;
- friend class Logical_session_id;
+ friend class LogicalSessionId;
+ friend class LogicalSessionToClient;
+ friend class LogicalSessionFromClient;
friend class repl::OplogEntryBase;
public: