summaryrefslogtreecommitdiff
path: root/src/mongo/db/logical_session_cache.cpp
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/mongo/db/logical_session_cache.cpp
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/mongo/db/logical_session_cache.cpp')
-rw-r--r--src/mongo/db/logical_session_cache.cpp42
1 files changed, 16 insertions, 26 deletions
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