diff options
-rw-r--r-- | src/mongo/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/SConscript | 47 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager.cpp | 315 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager.h | 142 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_direct.cpp | 137 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_direct.h | 73 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_sharding.cpp | 350 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_sharding.h | 197 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_sharding_test.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_zero.cpp | 57 | ||||
-rw-r--r-- | src/mongo/db/keys_collection_manager_zero.h | 69 | ||||
-rw-r--r-- | src/mongo/db/logical_time_validator.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/logical_time_validator.h | 8 | ||||
-rw-r--r-- | src/mongo/db/logical_time_validator_test.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/service_context.h | 1 | ||||
-rw-r--r-- | src/mongo/db/service_liason.cpp | 1 | ||||
-rw-r--r-- | src/mongo/s/sharding_initialization.cpp | 9 |
18 files changed, 472 insertions, 960 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 0517e674d6d..a447823443b 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -289,7 +289,6 @@ env.Library( 'db/ftdc/ftdc_mongod', 'db/index_d', 'db/initialize_snmp', - 'db/keys_collection_manager_direct', 'db/kill_sessions_local', 'db/logical_session_cache_factory_mongod', 'db/mongod_options', diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index b4b4d5e0efb..428ea17e5de 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -902,8 +902,6 @@ env.Library( LIBDEPS=[ '$BUILD_DIR/mongo/crypto/sha1_block', 'keys_collection_document', - 'keys_collection_manager', - 'keys_collection_manager_zero', 'logical_clock', ], ) @@ -1240,40 +1238,6 @@ env.Library( ) env.Library( - target='keys_collection_manager', - source=[ - 'keys_collection_manager.cpp', - ], - LIBDEPS=[ - 'server_parameters', - ], -) - -env.Library( - target='keys_collection_manager_direct', - source=[ - 'keys_collection_manager_direct.cpp', - ], - LIBDEPS=[ - 'dbdirectclient', - 'keys_collection_manager', - 'logical_clock', - 'logical_time', - ], -) - -env.Library( - target='keys_collection_manager_zero', - source=[ - 'keys_collection_manager_zero.cpp', - ], - LIBDEPS=[ - 'keys_collection_manager', - 'logical_time', - ], -) - -env.Library( target='keys_collection_client_direct', source=[ 'keys_collection_client_direct.cpp', @@ -1302,16 +1266,15 @@ env.Library( ) env.Library( - target='keys_collection_manager_sharding', + target='keys_collection_manager', source=[ - 'keys_collection_manager_sharding.cpp', + 'keys_collection_manager.cpp', 'keys_collection_cache_reader.cpp', 'keys_collection_cache_reader_and_updater.cpp', ], LIBDEPS=[ 'logical_clock', 'keys_collection_document', - 'keys_collection_manager', 'logical_time', 'server_options', 'keys_collection_client_sharded', @@ -1336,7 +1299,7 @@ env.Library( 'logical_time_validator.cpp', ], LIBDEPS=[ - 'keys_collection_manager_sharding', + 'keys_collection_manager', 'service_context', 'signed_logical_time', 'time_proof_service', @@ -1394,7 +1357,7 @@ env.CppUnitTest( 'logical_time_validator_test.cpp', ], LIBDEPS=[ - 'keys_collection_manager_sharding', + 'keys_collection_manager', 'logical_time_validator', '$BUILD_DIR/mongo/s/config_server_test_fixture', '$BUILD_DIR/mongo/s/coreshard', @@ -1466,7 +1429,7 @@ env.CppUnitTest( 'keys_collection_manager_sharding_test.cpp', ], LIBDEPS=[ - 'keys_collection_manager_sharding', + 'keys_collection_manager', '$BUILD_DIR/mongo/s/config_server_test_fixture', ], ) diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index fe0402f15e3..b6ad9f7bdd2 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -78,7 +78,6 @@ #include "mongo/db/keys_collection_client_direct.h" #include "mongo/db/keys_collection_client_sharded.h" #include "mongo/db/keys_collection_manager.h" -#include "mongo/db/keys_collection_manager_sharding.h" #include "mongo/db/kill_sessions.h" #include "mongo/db/kill_sessions_local.h" #include "mongo/db/log_process_details.h" @@ -946,7 +945,7 @@ ExitCode _initAndListen(int listenPort) { makeShardingTaskExecutor(executor::makeNetworkInterface("AddShard-TaskExecutor"))); } else if (replSettings.usingReplSets()) { // standalone replica set auto keysCollectionClient = stdx::make_unique<KeysCollectionClientDirect>(); - auto keyManager = std::make_shared<KeysCollectionManagerSharding>( + auto keyManager = std::make_shared<KeysCollectionManager>( KeysCollectionManager::kKeyManagerPurposeString, std::move(keysCollectionClient), Seconds(KeysRotationIntervalSec)); diff --git a/src/mongo/db/keys_collection_manager.cpp b/src/mongo/db/keys_collection_manager.cpp index 1ef6a8bb673..24fb4a8b6da 100644 --- a/src/mongo/db/keys_collection_manager.cpp +++ b/src/mongo/db/keys_collection_manager.cpp @@ -25,12 +25,27 @@ * exception statement from all source files in the program, then also delete * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault #include "mongo/platform/basic.h" #include "mongo/db/keys_collection_manager.h" +#include "mongo/db/keys_collection_cache_reader.h" +#include "mongo/db/keys_collection_cache_reader_and_updater.h" +#include "mongo/db/keys_collection_client.h" +#include "mongo/db/logical_clock.h" +#include "mongo/db/logical_time.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/server_options.h" #include "mongo/db/server_parameters.h" +#include "mongo/db/service_context.h" +#include "mongo/stdx/memory.h" +#include "mongo/util/concurrency/idle_thread_block.h" +#include "mongo/util/fail_point_service.h" +#include "mongo/util/log.h" +#include "mongo/util/mongoutils/str.h" +#include "mongo/util/time_support.h" namespace mongo { @@ -41,6 +56,304 @@ MONGO_EXPORT_STARTUP_SERVER_PARAMETER(KeysRotationIntervalSec, int, KeysCollectionManager::kKeyValidInterval.count()); -KeysCollectionManager::~KeysCollectionManager() = default; +namespace { + +Milliseconds kDefaultRefreshWaitTime(30 * 1000); +Milliseconds kRefreshIntervalIfErrored(200); +Milliseconds kMaxRefreshWaitTime(10 * 60 * 1000); + +// Prevents the refresher thread from waiting longer than the given number of milliseconds, even on +// a successful refresh. +MONGO_FP_DECLARE(maxKeyRefreshWaitTimeOverrideMS); + +/** + * Returns the amount of time to wait until the monitoring thread should attempt to refresh again. + */ +Milliseconds howMuchSleepNeedFor(const LogicalTime& currentTime, + const LogicalTime& latestExpiredAt, + const Milliseconds& interval) { + auto currentSecs = currentTime.asTimestamp().getSecs(); + auto expiredSecs = latestExpiredAt.asTimestamp().getSecs(); + + if (currentSecs >= expiredSecs) { + // This means that the last round didn't generate a usable key for the current time. + // However, we don't want to poll too hard as well, so use a low interval. + return kRefreshIntervalIfErrored; + } + + auto millisBeforeExpire = 1000 * (expiredSecs - currentSecs); + + if (interval.count() <= millisBeforeExpire) { + return interval; + } + + return Milliseconds(millisBeforeExpire); +} + +} // unnamed namespace + +KeysCollectionManager::KeysCollectionManager(std::string purpose, + std::unique_ptr<KeysCollectionClient> client, + Seconds keyValidForInterval) + : _client(std::move(client)), + _purpose(std::move(purpose)), + _keyValidForInterval(keyValidForInterval), + _keysCache(_purpose, _client.get()) {} + + +StatusWith<KeysCollectionDocument> KeysCollectionManager::getKeyForValidation( + OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) { + auto keyStatus = _getKeyWithKeyIdCheck(keyId, forThisTime); + + if (keyStatus != ErrorCodes::KeyNotFound) { + return keyStatus; + } + + _refresher.refreshNow(opCtx); + + return _getKeyWithKeyIdCheck(keyId, forThisTime); +} + +StatusWith<KeysCollectionDocument> KeysCollectionManager::getKeyForSigning( + OperationContext* opCtx, const LogicalTime& forThisTime) { + return _getKey(forThisTime); +} + +StatusWith<KeysCollectionDocument> KeysCollectionManager::_getKeyWithKeyIdCheck( + long long keyId, const LogicalTime& forThisTime) { + auto keyStatus = _keysCache.getKeyById(keyId, forThisTime); + + if (!keyStatus.isOK()) { + return keyStatus; + } + + return keyStatus.getValue(); +} + +StatusWith<KeysCollectionDocument> KeysCollectionManager::_getKey(const LogicalTime& forThisTime) { + auto keyStatus = _keysCache.getKey(forThisTime); + + if (!keyStatus.isOK()) { + return keyStatus; + } + + const auto& key = keyStatus.getValue(); + + if (key.getExpiresAt() < forThisTime) { + return {ErrorCodes::KeyNotFound, + str::stream() << "No keys found for " << _purpose << " that is valid for " + << forThisTime.toString()}; + } + + return key; +} + +void KeysCollectionManager::refreshNow(OperationContext* opCtx) { + _refresher.refreshNow(opCtx); +} + +void KeysCollectionManager::startMonitoring(ServiceContext* service) { + _keysCache.resetCache(); + _refresher.setFunc([this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); }); + _refresher.start( + service, str::stream() << "monitoring keys for " << _purpose, _keyValidForInterval); +} + +void KeysCollectionManager::stopMonitoring() { + _refresher.stop(); +} + +void KeysCollectionManager::enableKeyGenerator(OperationContext* opCtx, bool doEnable) { + if (doEnable) { + _refresher.switchFunc(opCtx, [this](OperationContext* opCtx) { + KeysCollectionCacheReaderAndUpdater keyGenerator( + _purpose, _client.get(), _keyValidForInterval); + auto keyGenerationStatus = keyGenerator.refresh(opCtx); + + if (ErrorCodes::isShutdownError(keyGenerationStatus.getStatus().code())) { + return keyGenerationStatus; + } + + // An error encountered by the keyGenerator should not prevent refreshing the cache + auto cacheRefreshStatus = _keysCache.refresh(opCtx); + + if (!keyGenerationStatus.isOK()) { + return keyGenerationStatus; + } + + return cacheRefreshStatus; + }); + } else { + _refresher.switchFunc( + opCtx, [this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); }); + } +} + +bool KeysCollectionManager::hasSeenKeys() { + return _refresher.hasSeenKeys(); +} + +void KeysCollectionManager::PeriodicRunner::refreshNow(OperationContext* opCtx) { + auto refreshRequest = [this]() { + stdx::lock_guard<stdx::mutex> lk(_mutex); + + if (_inShutdown) { + uasserted(ErrorCodes::ShutdownInProgress, + "aborting keys cache refresh because node is shutting down"); + } + + if (_refreshRequest) { + return _refreshRequest; + } + + _refreshNeededCV.notify_all(); + _refreshRequest = std::make_shared<Notification<void>>(); + return _refreshRequest; + }(); + + // note: waitFor waits min(maxTimeMS, kDefaultRefreshWaitTime). + // waitFor also throws if timeout, so also throw when notification was not satisfied after + // waiting. + if (!refreshRequest->waitFor(opCtx, kDefaultRefreshWaitTime)) { + uasserted(ErrorCodes::ExceededTimeLimit, "timed out waiting for refresh"); + } +} + +void KeysCollectionManager::PeriodicRunner::_doPeriodicRefresh(ServiceContext* service, + std::string threadName, + Milliseconds refreshInterval) { + Client::initThreadIfNotAlready(threadName); + + while (true) { + bool hasRefreshRequestInitially = false; + unsigned errorCount = 0; + std::shared_ptr<RefreshFunc> doRefresh; + { + stdx::lock_guard<stdx::mutex> lock(_mutex); + + if (_inShutdown) { + break; + } + + invariant(_doRefresh.get() != nullptr); + doRefresh = _doRefresh; + hasRefreshRequestInitially = _refreshRequest.get() != nullptr; + } + + Milliseconds nextWakeup = kRefreshIntervalIfErrored; + + // No need to refresh keys in FCV 3.4, since key generation will be disabled. + if (serverGlobalParams.featureCompatibility.getVersion() == + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo36) { + auto opCtx = cc().makeOperationContext(); + + auto latestKeyStatusWith = (*doRefresh)(opCtx.get()); + if (latestKeyStatusWith.getStatus().isOK()) { + errorCount = 0; + const auto& latestKey = latestKeyStatusWith.getValue(); + auto currentTime = LogicalClock::get(service)->getClusterTime(); + + { + stdx::unique_lock<stdx::mutex> lock(_mutex); + _hasSeenKeys = true; + } + + nextWakeup = + howMuchSleepNeedFor(currentTime, latestKey.getExpiresAt(), refreshInterval); + } else { + errorCount += 1; + nextWakeup = Milliseconds(kRefreshIntervalIfErrored.count() * errorCount); + if (nextWakeup > kMaxRefreshWaitTime) { + nextWakeup = kMaxRefreshWaitTime; + } + } + } else { + nextWakeup = kDefaultRefreshWaitTime; + } + + MONGO_FAIL_POINT_BLOCK(maxKeyRefreshWaitTimeOverrideMS, data) { + const BSONObj& dataObj = data.getData(); + auto overrideMS = Milliseconds(dataObj["overrideMS"].numberInt()); + if (nextWakeup > overrideMS) { + nextWakeup = overrideMS; + } + } + + stdx::unique_lock<stdx::mutex> lock(_mutex); + + if (_refreshRequest) { + if (!hasRefreshRequestInitially) { + // A fresh request came in, fulfill the request before going to sleep. + continue; + } + + _refreshRequest->set(); + _refreshRequest.reset(); + } + + if (_inShutdown) { + break; + } + + // Use a new opCtx so we won't be holding any RecoveryUnit while this thread goes to sleep. + auto opCtx = cc().makeOperationContext(); + + MONGO_IDLE_THREAD_BLOCK; + auto sleepStatus = opCtx->waitForConditionOrInterruptNoAssertUntil( + _refreshNeededCV, lock, Date_t::now() + nextWakeup); + + if (ErrorCodes::isShutdownError(sleepStatus.getStatus().code())) { + break; + } + } + + stdx::unique_lock<stdx::mutex> lock(_mutex); + if (_refreshRequest) { + _refreshRequest->set(); + _refreshRequest.reset(); + } +} + +void KeysCollectionManager::PeriodicRunner::setFunc(RefreshFunc newRefreshStrategy) { + stdx::lock_guard<stdx::mutex> lock(_mutex); + _doRefresh = std::make_shared<RefreshFunc>(std::move(newRefreshStrategy)); + _refreshNeededCV.notify_all(); +} + +void KeysCollectionManager::PeriodicRunner::switchFunc(OperationContext* opCtx, + RefreshFunc newRefreshStrategy) { + setFunc(newRefreshStrategy); +} + +void KeysCollectionManager::PeriodicRunner::start(ServiceContext* service, + const std::string& threadName, + Milliseconds refreshInterval) { + stdx::lock_guard<stdx::mutex> lock(_mutex); + invariant(!_backgroundThread.joinable()); + invariant(!_inShutdown); + + _backgroundThread = stdx::thread([this, service, threadName, refreshInterval] { + _doPeriodicRefresh(service, threadName, refreshInterval); + }); +} + +void KeysCollectionManager::PeriodicRunner::stop() { + { + stdx::lock_guard<stdx::mutex> lock(_mutex); + if (!_backgroundThread.joinable()) { + return; + } + + _inShutdown = true; + _refreshNeededCV.notify_all(); + } + + _backgroundThread.join(); +} + +bool KeysCollectionManager::PeriodicRunner::hasSeenKeys() { + stdx::lock_guard<stdx::mutex> lock(_mutex); + return _hasSeenKeys; +} } // namespace mongo diff --git a/src/mongo/db/keys_collection_manager.h b/src/mongo/db/keys_collection_manager.h index 4d6771be838..3cdac7b9bf2 100644 --- a/src/mongo/db/keys_collection_manager.h +++ b/src/mongo/db/keys_collection_manager.h @@ -31,34 +31,47 @@ #include <memory> #include "mongo/base/status_with.h" +#include "mongo/db/keys_collection_cache_reader.h" +#include "mongo/db/keys_collection_cache_reader_and_updater.h" #include "mongo/db/keys_collection_document.h" +#include "mongo/stdx/functional.h" +#include "mongo/stdx/mutex.h" +#include "mongo/stdx/thread.h" +#include "mongo/util/concurrency/notification.h" +#include "mongo/util/duration.h" namespace mongo { class OperationContext; class LogicalTime; class ServiceContext; +class KeysCollectionClient; extern int KeysRotationIntervalSec; + /** - * This is responsible for providing keys that can be used for HMAC computation. This also supports - * automatic key rotation that happens on a configurable interval. + * The KeysCollectionManager queries the config servers for keys that can be used for + * HMAC computation. It maintains an internal background thread that is used to periodically + * refresh the local key cache against the keys collection stored on the config servers. */ class KeysCollectionManager { public: static const Seconds kKeyValidInterval; static const std::string kKeyManagerPurposeString; - virtual ~KeysCollectionManager(); + KeysCollectionManager(std::string purpose, + std::unique_ptr<KeysCollectionClient> client, + Seconds keyValidForInterval); /** * Return a key that is valid for the given time and also matches the keyId. Note that this call - * can block if it will need to do a refresh and we are on a sharded cluster. + * can block if it will need to do a refresh. * * Throws ErrorCode::ExceededTimeLimit if it times out. */ - virtual StatusWith<KeysCollectionDocument> getKeyForValidation( - OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) = 0; + StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx, + long long keyId, + const LogicalTime& forThisTime); /** * Returns a key that is valid for the given time. Note that unlike getKeyForValidation, this @@ -66,8 +79,121 @@ public: * * Throws ErrorCode::ExceededTimeLimit if it times out. */ - virtual StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx, - const LogicalTime& forThisTime) = 0; + StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx, + const LogicalTime& forThisTime); + + /** + * Request this manager to perform a refresh. + */ + void refreshNow(OperationContext* opCtx); + + /** + * Starts a background thread that will constantly update the internal cache of keys. + * + * Cannot call this after stopMonitoring was called at least once. + */ + void startMonitoring(ServiceContext* service); + + /** + * Stops the background thread updating the cache. + */ + void stopMonitoring(); + + /** + * Enable writing new keys to the config server primary. Should only be called if current node + * is the config primary. + */ + void enableKeyGenerator(OperationContext* opCtx, bool doEnable); + + /** + * Returns true if the refresher has ever successfully returned keys from the config server. + */ + bool hasSeenKeys(); + +private: + /** + * This is responsible for periodically performing refresh in the background. + */ + class PeriodicRunner { + public: + using RefreshFunc = stdx::function<StatusWith<KeysCollectionDocument>(OperationContext*)>; + + /** + * Preemptively inform the monitoring thread it needs to perform a refresh. Returns an + * object + * that gets notified after the current round of refresh is over. Note that being notified + * can + * mean either of these things: + * + * 1. An error occurred and refresh was not performed. + * 2. No error occurred but no new key was found. + * 3. No error occurred and new keys were found. + */ + void refreshNow(OperationContext* opCtx); + + /** + * Sets the refresh function to use. + * Should only be used to bootstrap this refresher with initial strategy. + */ + void setFunc(RefreshFunc newRefreshStrategy); + + /** + * Switches the current strategy with a new one. This also waits to make sure that the old + * strategy is not being used and will no longer be used after this call. + */ + void switchFunc(OperationContext* opCtx, RefreshFunc newRefreshStrategy); + + /** + * Starts the refresh thread. + */ + void start(ServiceContext* service, + const std::string& threadName, + Milliseconds refreshInterval); + + /** + * Stops the refresh thread. + */ + void stop(); + + /** + * Returns true if keys have ever successfully been returned from the config server. + */ + bool hasSeenKeys(); + + private: + void _doPeriodicRefresh(ServiceContext* service, + std::string threadName, + Milliseconds refreshInterval); + + stdx::mutex _mutex; // protects all the member variables below. + std::shared_ptr<Notification<void>> _refreshRequest; + stdx::condition_variable _refreshNeededCV; + + stdx::thread _backgroundThread; + std::shared_ptr<RefreshFunc> _doRefresh; + + bool _hasSeenKeys = false; + bool _inShutdown = false; + }; + + /** + * Return a key that is valid for the given time and also matches the keyId. + */ + StatusWith<KeysCollectionDocument> _getKeyWithKeyIdCheck(long long keyId, + const LogicalTime& forThisTime); + + /** + * Return a key that is valid for the given time. + */ + StatusWith<KeysCollectionDocument> _getKey(const LogicalTime& forThisTime); + + std::unique_ptr<KeysCollectionClient> _client; + const std::string _purpose; + const Seconds _keyValidForInterval; + + // No mutex needed since the members below have their own mutexes. + KeysCollectionCacheReader _keysCache; + PeriodicRunner _refresher; }; } // namespace mongo diff --git a/src/mongo/db/keys_collection_manager_direct.cpp b/src/mongo/db/keys_collection_manager_direct.cpp deleted file mode 100644 index 60cf5672e6e..00000000000 --- a/src/mongo/db/keys_collection_manager_direct.cpp +++ /dev/null @@ -1,137 +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/keys_collection_manager_direct.h" - -#include "mongo/db/dbdirectclient.h" -#include "mongo/db/logical_clock.h" -#include "mongo/db/logical_time.h" -#include "mongo/db/operation_context.h" -#include "mongo/db/server_options.h" -#include "mongo/db/service_context.h" - -namespace mongo { - -namespace { -const char kLogicalTimeKeysCollection[] = "admin.system.keys"; -const int kMaxCachedKeys = 20; -} // namespace - -KeysCollectionManagerDirect::KeysCollectionManagerDirect(std::string purpose, - Seconds keyValidForInterval) - : _purpose(std::move(purpose)), - _keyValidForInterval(keyValidForInterval), - _cache(kMaxCachedKeys) {} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerDirect::getKeyForValidation( - OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) { - // First, attempt to find the key in our cache. - { - stdx::lock_guard<stdx::mutex> lk(_mutex); - auto it = _cache.find(keyId); - if (it != _cache.end()) { - return it->second; - } - } - - // Query admin.system.keys for an active key with this id. - DBDirectClient client(opCtx); - - BSONObjBuilder queryBuilder; - queryBuilder.append("purpose", _purpose); - queryBuilder.append("_id", keyId); - queryBuilder.append("expiresAt", BSON("$gt" << forThisTime.asTimestamp())); - - auto cursor = client.query(KeysCollectionDocument::ConfigNS, queryBuilder.obj()); - - if (!cursor->more()) { - return {ErrorCodes::KeyNotFound, "Could not find matching key"}; - } - - // Parse the key. - auto res = KeysCollectionDocument::fromBSON(cursor->next()); - if (!res.isOK()) { - return res.getStatus(); - } - - // Add to our cache. - { - stdx::lock_guard<stdx::mutex> lk(_mutex); - _cache.add(keyId, res.getValue()); - } - - return res.getValue(); -} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerDirect::getKeyForSigning( - OperationContext* opCtx, const LogicalTime& forThisTime) { - // Search through the cache for active keys. - { - stdx::lock_guard<stdx::mutex> lk(_mutex); - for (auto& it : _cache) { - auto keyDoc = it.second; - auto expiration = keyDoc.getExpiresAt(); - if (expiration > forThisTime) { - return keyDoc; - } - } - } - - // Query admin.system.keys for active keys. - DBDirectClient client(opCtx); - - BSONObjBuilder queryBuilder; - queryBuilder.append("purpose", _purpose); - queryBuilder.append("expiresAt", BSON("$gt" << forThisTime.asTimestamp())); - - auto cursor = client.query(KeysCollectionDocument::ConfigNS, queryBuilder.obj()); - - if (!cursor->more()) { - return {ErrorCodes::KeyNotFound, "Could not find an active key for signing"}; - } - - // Parse and return the key. - auto res = KeysCollectionDocument::fromBSON(cursor->next()); - if (!res.isOK()) { - return res.getStatus(); - } - - auto keyDoc = res.getValue(); - - // Add to our cache. - { - stdx::lock_guard<stdx::mutex> lk(_mutex); - _cache.add(keyDoc.getKeyId(), keyDoc); - } - - return keyDoc; -} - -} // namespace mongo diff --git a/src/mongo/db/keys_collection_manager_direct.h b/src/mongo/db/keys_collection_manager_direct.h deleted file mode 100644 index 2f1228ff056..00000000000 --- a/src/mongo/db/keys_collection_manager_direct.h +++ /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. - */ - -#pragma once - -#include <memory> - -#include "mongo/db/keys_collection_document.h" -#include "mongo/db/keys_collection_manager.h" -#include "mongo/stdx/mutex.h" -#include "mongo/util/lru_cache.h" - -namespace mongo { - -class OperationContext; -class LogicalTime; -class ServiceContext; - -/** - * This implementation of the KeysCollectionManager uses DBDirectclient to query the - * keys collection local to this server. - */ -class KeysCollectionManagerDirect : public KeysCollectionManager { -public: - KeysCollectionManagerDirect(std::string purpose, Seconds keyValidForInterval); - - /** - * Return a key that is valid for the given time and also matches the keyId. - */ - StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx, - long long keyId, - const LogicalTime& forThisTime) override; - - /** - * Returns a key that is valid for the given time. - */ - StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx, - const LogicalTime& forThisTime) override; - -private: - const std::string _purpose; - const Seconds _keyValidForInterval; - - stdx::mutex _mutex; - LRUCache<long long, KeysCollectionDocument> _cache; -}; - -} // namespace mongo diff --git a/src/mongo/db/keys_collection_manager_sharding.cpp b/src/mongo/db/keys_collection_manager_sharding.cpp deleted file mode 100644 index 8baf74d073c..00000000000 --- a/src/mongo/db/keys_collection_manager_sharding.cpp +++ /dev/null @@ -1,350 +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. - */ -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - -#include "mongo/platform/basic.h" - -#include "mongo/db/keys_collection_manager_sharding.h" - -#include "mongo/db/keys_collection_cache_reader.h" -#include "mongo/db/keys_collection_cache_reader_and_updater.h" -#include "mongo/db/keys_collection_client.h" -#include "mongo/db/logical_clock.h" -#include "mongo/db/logical_time.h" -#include "mongo/db/operation_context.h" -#include "mongo/db/server_options.h" -#include "mongo/db/service_context.h" -#include "mongo/stdx/memory.h" -#include "mongo/util/concurrency/idle_thread_block.h" -#include "mongo/util/fail_point_service.h" -#include "mongo/util/log.h" -#include "mongo/util/mongoutils/str.h" -#include "mongo/util/time_support.h" - -namespace mongo { - -namespace { - -Milliseconds kDefaultRefreshWaitTime(30 * 1000); -Milliseconds kRefreshIntervalIfErrored(200); -Milliseconds kMaxRefreshWaitTime(10 * 60 * 1000); - -// Prevents the refresher thread from waiting longer than the given number of milliseconds, even on -// a successful refresh. -MONGO_FP_DECLARE(maxKeyRefreshWaitTimeOverrideMS); - -/** - * Returns the amount of time to wait until the monitoring thread should attempt to refresh again. - */ -Milliseconds howMuchSleepNeedFor(const LogicalTime& currentTime, - const LogicalTime& latestExpiredAt, - const Milliseconds& interval) { - auto currentSecs = currentTime.asTimestamp().getSecs(); - auto expiredSecs = latestExpiredAt.asTimestamp().getSecs(); - - if (currentSecs >= expiredSecs) { - // This means that the last round didn't generate a usable key for the current time. - // However, we don't want to poll too hard as well, so use a low interval. - return kRefreshIntervalIfErrored; - } - - auto millisBeforeExpire = 1000 * (expiredSecs - currentSecs); - - if (interval.count() <= millisBeforeExpire) { - return interval; - } - - return Milliseconds(millisBeforeExpire); -} - -} // unnamed namespace - -KeysCollectionManagerSharding::KeysCollectionManagerSharding( - std::string purpose, std::unique_ptr<KeysCollectionClient> client, Seconds keyValidForInterval) - : _client(std::move(client)), - _purpose(std::move(purpose)), - _keyValidForInterval(keyValidForInterval), - _keysCache(_purpose, _client.get()) {} - - -StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::getKeyForValidation( - OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) { - auto keyStatus = _getKeyWithKeyIdCheck(keyId, forThisTime); - - if (keyStatus != ErrorCodes::KeyNotFound) { - return keyStatus; - } - - _refresher.refreshNow(opCtx); - - return _getKeyWithKeyIdCheck(keyId, forThisTime); -} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::getKeyForSigning( - OperationContext* opCtx, const LogicalTime& forThisTime) { - return _getKey(forThisTime); -} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::_getKeyWithKeyIdCheck( - long long keyId, const LogicalTime& forThisTime) { - auto keyStatus = _keysCache.getKeyById(keyId, forThisTime); - - if (!keyStatus.isOK()) { - return keyStatus; - } - - return keyStatus.getValue(); -} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerSharding::_getKey( - const LogicalTime& forThisTime) { - auto keyStatus = _keysCache.getKey(forThisTime); - - if (!keyStatus.isOK()) { - return keyStatus; - } - - const auto& key = keyStatus.getValue(); - - if (key.getExpiresAt() < forThisTime) { - return {ErrorCodes::KeyNotFound, - str::stream() << "No keys found for " << _purpose << " that is valid for " - << forThisTime.toString()}; - } - - return key; -} - -void KeysCollectionManagerSharding::refreshNow(OperationContext* opCtx) { - _refresher.refreshNow(opCtx); -} - -void KeysCollectionManagerSharding::startMonitoring(ServiceContext* service) { - _keysCache.resetCache(); - _refresher.setFunc([this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); }); - _refresher.start( - service, str::stream() << "monitoring keys for " << _purpose, _keyValidForInterval); -} - -void KeysCollectionManagerSharding::stopMonitoring() { - _refresher.stop(); -} - -void KeysCollectionManagerSharding::enableKeyGenerator(OperationContext* opCtx, bool doEnable) { - if (doEnable) { - _refresher.switchFunc(opCtx, [this](OperationContext* opCtx) { - KeysCollectionCacheReaderAndUpdater keyGenerator( - _purpose, _client.get(), _keyValidForInterval); - auto keyGenerationStatus = keyGenerator.refresh(opCtx); - - if (ErrorCodes::isShutdownError(keyGenerationStatus.getStatus().code())) { - return keyGenerationStatus; - } - - // An error encountered by the keyGenerator should not prevent refreshing the cache - auto cacheRefreshStatus = _keysCache.refresh(opCtx); - - if (!keyGenerationStatus.isOK()) { - return keyGenerationStatus; - } - - return cacheRefreshStatus; - }); - } else { - _refresher.switchFunc( - opCtx, [this](OperationContext* opCtx) { return _keysCache.refresh(opCtx); }); - } -} - -bool KeysCollectionManagerSharding::hasSeenKeys() { - return _refresher.hasSeenKeys(); -} - -void KeysCollectionManagerSharding::PeriodicRunner::refreshNow(OperationContext* opCtx) { - auto refreshRequest = [this]() { - stdx::lock_guard<stdx::mutex> lk(_mutex); - - if (_inShutdown) { - uasserted(ErrorCodes::ShutdownInProgress, - "aborting keys cache refresh because node is shutting down"); - } - - if (_refreshRequest) { - return _refreshRequest; - } - - _refreshNeededCV.notify_all(); - _refreshRequest = std::make_shared<Notification<void>>(); - return _refreshRequest; - }(); - - // note: waitFor waits min(maxTimeMS, kDefaultRefreshWaitTime). - // waitFor also throws if timeout, so also throw when notification was not satisfied after - // waiting. - if (!refreshRequest->waitFor(opCtx, kDefaultRefreshWaitTime)) { - uasserted(ErrorCodes::ExceededTimeLimit, "timed out waiting for refresh"); - } -} - -void KeysCollectionManagerSharding::PeriodicRunner::_doPeriodicRefresh( - ServiceContext* service, std::string threadName, Milliseconds refreshInterval) { - Client::initThreadIfNotAlready(threadName); - - while (true) { - bool hasRefreshRequestInitially = false; - unsigned errorCount = 0; - std::shared_ptr<RefreshFunc> doRefresh; - { - stdx::lock_guard<stdx::mutex> lock(_mutex); - - if (_inShutdown) { - break; - } - - invariant(_doRefresh.get() != nullptr); - doRefresh = _doRefresh; - hasRefreshRequestInitially = _refreshRequest.get() != nullptr; - } - - Milliseconds nextWakeup = kRefreshIntervalIfErrored; - - // No need to refresh keys in FCV 3.4, since key generation will be disabled. - if (serverGlobalParams.featureCompatibility.getVersion() == - ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo36) { - auto opCtx = cc().makeOperationContext(); - - auto latestKeyStatusWith = (*doRefresh)(opCtx.get()); - if (latestKeyStatusWith.getStatus().isOK()) { - errorCount = 0; - const auto& latestKey = latestKeyStatusWith.getValue(); - auto currentTime = LogicalClock::get(service)->getClusterTime(); - - { - stdx::unique_lock<stdx::mutex> lock(_mutex); - _hasSeenKeys = true; - } - - nextWakeup = - howMuchSleepNeedFor(currentTime, latestKey.getExpiresAt(), refreshInterval); - } else { - errorCount += 1; - nextWakeup = Milliseconds(kRefreshIntervalIfErrored.count() * errorCount); - if (nextWakeup > kMaxRefreshWaitTime) { - nextWakeup = kMaxRefreshWaitTime; - } - } - } else { - nextWakeup = kDefaultRefreshWaitTime; - } - - MONGO_FAIL_POINT_BLOCK(maxKeyRefreshWaitTimeOverrideMS, data) { - const BSONObj& dataObj = data.getData(); - auto overrideMS = Milliseconds(dataObj["overrideMS"].numberInt()); - if (nextWakeup > overrideMS) { - nextWakeup = overrideMS; - } - } - - stdx::unique_lock<stdx::mutex> lock(_mutex); - - if (_refreshRequest) { - if (!hasRefreshRequestInitially) { - // A fresh request came in, fulfill the request before going to sleep. - continue; - } - - _refreshRequest->set(); - _refreshRequest.reset(); - } - - if (_inShutdown) { - break; - } - - // Use a new opCtx so we won't be holding any RecoveryUnit while this thread goes to sleep. - auto opCtx = cc().makeOperationContext(); - - MONGO_IDLE_THREAD_BLOCK; - auto sleepStatus = opCtx->waitForConditionOrInterruptNoAssertUntil( - _refreshNeededCV, lock, Date_t::now() + nextWakeup); - - if (ErrorCodes::isShutdownError(sleepStatus.getStatus().code())) { - break; - } - } - - stdx::unique_lock<stdx::mutex> lock(_mutex); - if (_refreshRequest) { - _refreshRequest->set(); - _refreshRequest.reset(); - } -} - -void KeysCollectionManagerSharding::PeriodicRunner::setFunc(RefreshFunc newRefreshStrategy) { - stdx::lock_guard<stdx::mutex> lock(_mutex); - _doRefresh = std::make_shared<RefreshFunc>(std::move(newRefreshStrategy)); - _refreshNeededCV.notify_all(); -} - -void KeysCollectionManagerSharding::PeriodicRunner::switchFunc(OperationContext* opCtx, - RefreshFunc newRefreshStrategy) { - setFunc(newRefreshStrategy); -} - -void KeysCollectionManagerSharding::PeriodicRunner::start(ServiceContext* service, - const std::string& threadName, - Milliseconds refreshInterval) { - stdx::lock_guard<stdx::mutex> lock(_mutex); - invariant(!_backgroundThread.joinable()); - invariant(!_inShutdown); - - _backgroundThread = stdx::thread([this, service, threadName, refreshInterval] { - _doPeriodicRefresh(service, threadName, refreshInterval); - }); -} - -void KeysCollectionManagerSharding::PeriodicRunner::stop() { - { - stdx::lock_guard<stdx::mutex> lock(_mutex); - if (!_backgroundThread.joinable()) { - return; - } - - _inShutdown = true; - _refreshNeededCV.notify_all(); - } - - _backgroundThread.join(); -} - -bool KeysCollectionManagerSharding::PeriodicRunner::hasSeenKeys() { - stdx::lock_guard<stdx::mutex> lock(_mutex); - return _hasSeenKeys; -} - -} // namespace mongo diff --git a/src/mongo/db/keys_collection_manager_sharding.h b/src/mongo/db/keys_collection_manager_sharding.h deleted file mode 100644 index d1ebd96e540..00000000000 --- a/src/mongo/db/keys_collection_manager_sharding.h +++ /dev/null @@ -1,197 +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 <memory> - -#include "mongo/base/status_with.h" -#include "mongo/db/keys_collection_cache_reader.h" -#include "mongo/db/keys_collection_cache_reader_and_updater.h" -#include "mongo/db/keys_collection_document.h" -#include "mongo/db/keys_collection_manager.h" -#include "mongo/stdx/functional.h" -#include "mongo/stdx/mutex.h" -#include "mongo/stdx/thread.h" -#include "mongo/util/concurrency/notification.h" -#include "mongo/util/duration.h" - -namespace mongo { - -class OperationContext; -class LogicalTime; -class ServiceContext; -class KeysCollectionClient; - -/** - * This implementation of the KeysCollectionManager queries the config servers for keys. - * It maintains in internal background thread that is used to periodically refresh - * the local key cache against the keys collection stored on the config servers. - */ -class KeysCollectionManagerSharding : public KeysCollectionManager { -public: - static const Seconds kKeyValidInterval; - - KeysCollectionManagerSharding(std::string purpose, - std::unique_ptr<KeysCollectionClient> client, - Seconds keyValidForInterval); - - /** - * Return a key that is valid for the given time and also matches the keyId. Note that this call - * can block if it will need to do a refresh. - * - * Throws ErrorCode::ExceededTimeLimit if it times out. - */ - StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx, - long long keyId, - const LogicalTime& forThisTime) override; - - /** - * Returns a key that is valid for the given time. Note that unlike getKeyForValidation, this - * will never do a refresh. - * - * Throws ErrorCode::ExceededTimeLimit if it times out. - */ - StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx, - const LogicalTime& forThisTime) override; - - /** - * Request this manager to perform a refresh. - */ - void refreshNow(OperationContext* opCtx); - - /** - * Starts a background thread that will constantly update the internal cache of keys. - * - * Cannot call this after stopMonitoring was called at least once. - */ - void startMonitoring(ServiceContext* service); - - /** - * Stops the background thread updating the cache. - */ - void stopMonitoring(); - - /** - * Enable writing new keys to the config server primary. Should only be called if current node - * is the config primary. - */ - void enableKeyGenerator(OperationContext* opCtx, bool doEnable); - - /** - * Returns true if the refresher has ever successfully returned keys from the config server. - */ - bool hasSeenKeys(); - -private: - /** - * This is responsible for periodically performing refresh in the background. - */ - class PeriodicRunner { - public: - using RefreshFunc = stdx::function<StatusWith<KeysCollectionDocument>(OperationContext*)>; - - /** - * Preemptively inform the monitoring thread it needs to perform a refresh. Returns an - * object - * that gets notified after the current round of refresh is over. Note that being notified - * can - * mean either of these things: - * - * 1. An error occurred and refresh was not performed. - * 2. No error occurred but no new key was found. - * 3. No error occurred and new keys were found. - */ - void refreshNow(OperationContext* opCtx); - - /** - * Sets the refresh function to use. - * Should only be used to bootstrap this refresher with initial strategy. - */ - void setFunc(RefreshFunc newRefreshStrategy); - - /** - * Switches the current strategy with a new one. This also waits to make sure that the old - * strategy is not being used and will no longer be used after this call. - */ - void switchFunc(OperationContext* opCtx, RefreshFunc newRefreshStrategy); - - /** - * Starts the refresh thread. - */ - void start(ServiceContext* service, - const std::string& threadName, - Milliseconds refreshInterval); - - /** - * Stops the refresh thread. - */ - void stop(); - - /** - * Returns true if keys have ever successfully been returned from the config server. - */ - bool hasSeenKeys(); - - private: - void _doPeriodicRefresh(ServiceContext* service, - std::string threadName, - Milliseconds refreshInterval); - - stdx::mutex _mutex; // protects all the member variables below. - std::shared_ptr<Notification<void>> _refreshRequest; - stdx::condition_variable _refreshNeededCV; - - stdx::thread _backgroundThread; - std::shared_ptr<RefreshFunc> _doRefresh; - - bool _hasSeenKeys = false; - bool _inShutdown = false; - }; - - /** - * Return a key that is valid for the given time and also matches the keyId. - */ - StatusWith<KeysCollectionDocument> _getKeyWithKeyIdCheck(long long keyId, - const LogicalTime& forThisTime); - - /** - * Return a key that is valid for the given time. - */ - StatusWith<KeysCollectionDocument> _getKey(const LogicalTime& forThisTime); - - std::unique_ptr<KeysCollectionClient> _client; - const std::string _purpose; - const Seconds _keyValidForInterval; - - // No mutex needed since the members below have their own mutexes. - KeysCollectionCacheReader _keysCache; - PeriodicRunner _refresher; -}; - -} // namespace mongo diff --git a/src/mongo/db/keys_collection_manager_sharding_test.cpp b/src/mongo/db/keys_collection_manager_sharding_test.cpp index 0ba9588ce50..0646ea41167 100644 --- a/src/mongo/db/keys_collection_manager_sharding_test.cpp +++ b/src/mongo/db/keys_collection_manager_sharding_test.cpp @@ -34,7 +34,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/keys_collection_client_sharded.h" #include "mongo/db/keys_collection_document.h" -#include "mongo/db/keys_collection_manager_sharding.h" +#include "mongo/db/keys_collection_manager.h" #include "mongo/db/logical_clock.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" @@ -51,7 +51,7 @@ namespace mongo { class KeysManagerShardedTest : public ConfigServerTestFixture { public: - KeysCollectionManagerSharding* keyManager() { + KeysCollectionManager* keyManager() { return _keyManager.get(); } @@ -71,8 +71,8 @@ protected: operationContext()->getServiceContext()->setFastClockSource(std::move(clockSource)); auto catalogClient = stdx::make_unique<KeysCollectionClientSharded>( Grid::get(operationContext())->catalogClient()); - _keyManager = stdx::make_unique<KeysCollectionManagerSharding>( - "dummy", std::move(catalogClient), Seconds(1)); + _keyManager = + stdx::make_unique<KeysCollectionManager>("dummy", std::move(catalogClient), Seconds(1)); } void tearDown() override { @@ -88,7 +88,7 @@ protected: } private: - std::unique_ptr<KeysCollectionManagerSharding> _keyManager; + std::unique_ptr<KeysCollectionManager> _keyManager; }; TEST_F(KeysManagerShardedTest, GetKeyForValidationTimesOutIfRefresherIsNotRunning) { diff --git a/src/mongo/db/keys_collection_manager_zero.cpp b/src/mongo/db/keys_collection_manager_zero.cpp deleted file mode 100644 index 5f773b0152d..00000000000 --- a/src/mongo/db/keys_collection_manager_zero.cpp +++ /dev/null @@ -1,57 +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/keys_collection_manager_zero.h" - -#include "mongo/db/keys_collection_document.h" - -namespace mongo { - -namespace { - -const TimeProofService::Key kTimeProofServiceKey{}; -const long long kKeyId = 1; - -} // namespace - -KeysCollectionManagerZero::KeysCollectionManagerZero(std::string purpose) - : _purpose(std::move(purpose)) {} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerZero::getKeyForValidation( - OperationContext* opCtx, long long keyId, const LogicalTime& forThisTime) { - return KeysCollectionDocument(keyId, _purpose, kTimeProofServiceKey, forThisTime); -} - -StatusWith<KeysCollectionDocument> KeysCollectionManagerZero::getKeyForSigning( - OperationContext* opCtx, const LogicalTime& forThisTime) { - return KeysCollectionDocument(kKeyId, _purpose, kTimeProofServiceKey, forThisTime); -} - -} // namespace mongo diff --git a/src/mongo/db/keys_collection_manager_zero.h b/src/mongo/db/keys_collection_manager_zero.h deleted file mode 100644 index 71f2dcc89ee..00000000000 --- a/src/mongo/db/keys_collection_manager_zero.h +++ /dev/null @@ -1,69 +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 <memory> -#include <string> - -#include "mongo/db/keys_collection_document.h" -#include "mongo/db/keys_collection_manager.h" - -namespace mongo { - -class OperationContext; -class LogicalTime; -class ServiceContext; - -/** - * This implementation of the KeysCollectionManager always returns a zeroed key. This is a - * transitional type to bridge the gap until we decide how to store and rotate keys in standalones - * and non-clustered replica sets. - */ -class KeysCollectionManagerZero : public KeysCollectionManager { -public: - KeysCollectionManagerZero(std::string purpose); - - /** - * Return a key that is valid for the given time and also matches the keyId. - */ - StatusWith<KeysCollectionDocument> getKeyForValidation(OperationContext* opCtx, - long long keyId, - const LogicalTime& forThisTime) override; - - /** - * Returns a key that is valid for the given time. - */ - StatusWith<KeysCollectionDocument> getKeyForSigning(OperationContext* opCtx, - const LogicalTime& forThisTime) override; - -private: - std::string _purpose; -}; - -} // namespace mongo diff --git a/src/mongo/db/logical_time_validator.cpp b/src/mongo/db/logical_time_validator.cpp index 5c751eddf06..27133b5fcc0 100644 --- a/src/mongo/db/logical_time_validator.cpp +++ b/src/mongo/db/logical_time_validator.cpp @@ -37,7 +37,7 @@ #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/auth/privilege.h" -#include "mongo/db/keys_collection_manager_sharding.h" +#include "mongo/db/keys_collection_manager.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" #include "mongo/util/assert_util.h" @@ -80,8 +80,7 @@ void LogicalTimeValidator::set(ServiceContext* service, validator = std::move(newValidator); } -LogicalTimeValidator::LogicalTimeValidator( - std::shared_ptr<KeysCollectionManagerSharding> keyManager) +LogicalTimeValidator::LogicalTimeValidator(std::shared_ptr<KeysCollectionManager> keyManager) : _keyManager(keyManager) {} SignedLogicalTime LogicalTimeValidator::_getProof(const KeysCollectionDocument& keyDoc, @@ -216,7 +215,7 @@ void LogicalTimeValidator::resetKeyManager() { } } -std::shared_ptr<KeysCollectionManagerSharding> LogicalTimeValidator::_getKeyManagerCopy() { +std::shared_ptr<KeysCollectionManager> LogicalTimeValidator::_getKeyManagerCopy() { stdx::lock_guard<stdx::mutex> lk(_mutexKeyManager); invariant(_keyManager); return _keyManager; diff --git a/src/mongo/db/logical_time_validator.h b/src/mongo/db/logical_time_validator.h index 43d1c1c2678..0598fa8ec44 100644 --- a/src/mongo/db/logical_time_validator.h +++ b/src/mongo/db/logical_time_validator.h @@ -39,7 +39,7 @@ namespace mongo { class OperationContext; class ServiceContext; class KeysCollectionDocument; -class KeysCollectionManagerSharding; +class KeysCollectionManager; /** * This is responsible for signing cluster times that can be used to sent to other servers and @@ -56,7 +56,7 @@ public: * Constructs a new LogicalTimeValidator that uses the given key manager. The passed-in * key manager must outlive this object. */ - explicit LogicalTimeValidator(std::shared_ptr<KeysCollectionManagerSharding> keyManager); + explicit LogicalTimeValidator(std::shared_ptr<KeysCollectionManager> keyManager); /** * Tries to sign the newTime with a valid signature. Can return an empty signature and keyId @@ -121,7 +121,7 @@ private: /** * Returns the copy of the _keyManager to work when its reset by resetKeyManager call. */ - std::shared_ptr<KeysCollectionManagerSharding> _getKeyManagerCopy(); + std::shared_ptr<KeysCollectionManager> _getKeyManagerCopy(); SignedLogicalTime _getProof(const KeysCollectionDocument& keyDoc, LogicalTime newTime); @@ -130,7 +130,7 @@ private: stdx::mutex _mutexKeyManager; // protects _keyManager SignedLogicalTime _lastSeenValidTime; TimeProofService _timeProofService; - std::shared_ptr<KeysCollectionManagerSharding> _keyManager; + std::shared_ptr<KeysCollectionManager> _keyManager; }; } // namespace mongo diff --git a/src/mongo/db/logical_time_validator_test.cpp b/src/mongo/db/logical_time_validator_test.cpp index 1bb46ba0802..bbd7826eae8 100644 --- a/src/mongo/db/logical_time_validator_test.cpp +++ b/src/mongo/db/logical_time_validator_test.cpp @@ -31,7 +31,6 @@ #include "mongo/bson/timestamp.h" #include "mongo/db/keys_collection_client_sharded.h" #include "mongo/db/keys_collection_manager.h" -#include "mongo/db/keys_collection_manager_sharding.h" #include "mongo/db/logical_clock.h" #include "mongo/db/logical_time.h" #include "mongo/db/logical_time_validator.h" @@ -73,7 +72,7 @@ protected: const LogicalTime currentTime(LogicalTime(Timestamp(1, 0))); LogicalClock::get(operationContext())->setClusterTimeFromTrustedSource(currentTime); - _keyManager = std::make_shared<KeysCollectionManagerSharding>( + _keyManager = std::make_shared<KeysCollectionManager>( "dummy", std::move(catalogClient), Seconds(1000)); _validator = stdx::make_unique<LogicalTimeValidator>(_keyManager); _validator->init(operationContext()->getServiceContext()); @@ -99,7 +98,7 @@ protected: private: std::unique_ptr<LogicalTimeValidator> _validator; - std::shared_ptr<KeysCollectionManagerSharding> _keyManager; + std::shared_ptr<KeysCollectionManager> _keyManager; }; TEST_F(LogicalTimeValidatorTest, GetTimeWithIncreasingTimes) { diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h index 6fa9fa96157..681bbdc6262 100644 --- a/src/mongo/db/service_context.h +++ b/src/mongo/db/service_context.h @@ -31,7 +31,6 @@ #include <vector> #include "mongo/base/disallow_copying.h" -#include "mongo/db/keys_collection_manager.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/storage/storage_engine.h" #include "mongo/platform/atomic_word.h" diff --git a/src/mongo/db/service_liason.cpp b/src/mongo/db/service_liason.cpp index 22edb98b5c2..ade0f4b65f6 100644 --- a/src/mongo/db/service_liason.cpp +++ b/src/mongo/db/service_liason.cpp @@ -30,7 +30,6 @@ #include "mongo/db/service_liason.h" -#include "mongo/db/keys_collection_manager_zero.h" #include "mongo/db/logical_clock.h" #include "mongo/db/service_context.h" diff --git a/src/mongo/s/sharding_initialization.cpp b/src/mongo/s/sharding_initialization.cpp index 0ae318e1e9b..3dd9b60f8ce 100644 --- a/src/mongo/s/sharding_initialization.cpp +++ b/src/mongo/s/sharding_initialization.cpp @@ -39,7 +39,6 @@ #include "mongo/db/audit.h" #include "mongo/db/keys_collection_client_sharded.h" #include "mongo/db/keys_collection_manager.h" -#include "mongo/db/keys_collection_manager_sharding.h" #include "mongo/db/logical_clock.h" #include "mongo/db/logical_time_validator.h" #include "mongo/db/repl/replication_coordinator.h" @@ -247,10 +246,10 @@ Status initializeGlobalShardingState(OperationContext* opCtx, auto keysCollectionClient = stdx::make_unique<KeysCollectionClientSharded>(grid->catalogClient()); - auto keyManager = std::make_shared<KeysCollectionManagerSharding>( - KeysCollectionManager::kKeyManagerPurposeString, - std::move(keysCollectionClient), - Seconds(KeysRotationIntervalSec)); + auto keyManager = + std::make_shared<KeysCollectionManager>(KeysCollectionManager::kKeyManagerPurposeString, + std::move(keysCollectionClient), + Seconds(KeysRotationIntervalSec)); keyManager->startMonitoring(opCtx->getServiceContext()); LogicalTimeValidator::set(opCtx->getServiceContext(), |