summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2017-07-21 11:54:18 -0400
committerJason Carey <jcarey@argv.me>2017-07-26 15:53:42 -0400
commitedfe3f3b1276ef3598b1af673d088e6b5c4b3ad5 (patch)
tree08f0efcdb6100dc315cf5e9ac98c0c6261be928d /src
parentcb36a96d7c96cf1b24c7ef3b8b086cfc04c77642 (diff)
downloadmongo-edfe3f3b1276ef3598b1af673d088e6b5c4b3ad5.tar.gz
SERVER-30298 Add UserDigest LogicalSessionID
Inclusion of a sha256 digest of the full username to the logical session id (in addition to the current guid) is necessary to fully disambiguate logical sessions in degraded clusters (when the authoritative record for a session is unreachable). Semantics for the uid are as follows: session creation via startSession() * Sessions can only be created with one, and only one, user authenticated * The composite key is created from a guid created on the spot, as well as the digest of the currently auth'd username * Only the session guid is returned to the user * This prevents outside users from attempting to send back a value we'd have to check. It's preferable to decorate the guid with the user digest per command, rather than having to check a value the user might send. session use for a command * Sessions are passed via the lsid top level field in any command * Sessions are only meaningful for commands which requireAuth. For sessions which don't require auth, we strip session information from the command at parse time * Session ids are passed as an object, which can optionally include the username digest * It is illegal to pass the username digest unless the currently auth'd user has the impersonate privilege (the __system user does). This enables sessions on shard servers via mongos
Diffstat (limited to 'src')
-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
48 files changed, 768 insertions, 1228 deletions
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: