diff options
author | Kevin Pulo <kevin.pulo@mongodb.com> | 2020-05-19 14:29:26 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-06-05 12:48:36 +0000 |
commit | 7074dee1fbf6763c0d463c377c2e47d8ef2c4f6f (patch) | |
tree | 80d364f790c795d16b77fb1efa1cc5e3788e1d9c /src/mongo/rpc | |
parent | 5072922b32f94857098546366f17c93673154e72 (diff) | |
download | mongo-7074dee1fbf6763c0d463c377c2e47d8ef2c4f6f.tar.gz |
SERVER-47914 Move clusterTime from LogicalClock to VectorClock
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r-- | src/mongo/rpc/SConscript | 4 | ||||
-rw-r--r-- | src/mongo/rpc/metadata.cpp | 46 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/logical_time_metadata.cpp | 124 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/logical_time_metadata.h | 77 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/logical_time_metadata_test.cpp | 195 |
5 files changed, 5 insertions, 441 deletions
diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript index d9814e5345b..997326b96b5 100644 --- a/src/mongo/rpc/SConscript +++ b/src/mongo/rpc/SConscript @@ -95,7 +95,6 @@ env.Library( 'metadata.cpp', 'metadata/config_server_metadata.cpp', 'metadata/egress_metadata_hook_list.cpp', - 'metadata/logical_time_metadata.cpp', 'metadata/sharding_metadata.cpp', 'metadata/repl_set_metadata.cpp', 'metadata/oplog_query_metadata.cpp', @@ -109,9 +108,9 @@ env.Library( '$BUILD_DIR/mongo/bson/util/bson_extract', '$BUILD_DIR/mongo/client/read_preference', '$BUILD_DIR/mongo/db/commands/test_commands_enabled', - '$BUILD_DIR/mongo/db/logical_time_validator', '$BUILD_DIR/mongo/db/repl/optime', '$BUILD_DIR/mongo/db/signed_logical_time', + '$BUILD_DIR/mongo/db/vector_clock', ], ) @@ -159,7 +158,6 @@ env.CppUnitTest( 'metadata/client_metadata_test.cpp', 'metadata/config_server_metadata_test.cpp', 'metadata/egress_metadata_hook_list_test.cpp', - 'metadata/logical_time_metadata_test.cpp', 'metadata/oplog_query_metadata_test.cpp', 'metadata/repl_set_metadata_test.cpp', 'metadata/sharding_metadata_test.cpp', diff --git a/src/mongo/rpc/metadata.cpp b/src/mongo/rpc/metadata.cpp index 9a546b02572..2220e31755e 100644 --- a/src/mongo/rpc/metadata.cpp +++ b/src/mongo/rpc/metadata.cpp @@ -42,7 +42,6 @@ #include "mongo/rpc/metadata/client_metadata_ismaster.h" #include "mongo/rpc/metadata/config_server_metadata.h" #include "mongo/rpc/metadata/impersonated_user_metadata.h" -#include "mongo/rpc/metadata/logical_time_metadata.h" #include "mongo/rpc/metadata/sharding_metadata.h" #include "mongo/rpc/metadata/tracking_metadata.h" #include "mongo/util/string_map.h" @@ -54,12 +53,13 @@ BSONObj makeEmptyMetadata() { return BSONObj(); } -void readRequestMetadata(OperationContext* opCtx, const BSONObj& metadataObj, bool requiresAuth) { +void readRequestMetadata(OperationContext* opCtx, + const BSONObj& metadataObj, + bool cmdRequiresAuth) { BSONElement readPreferenceElem; BSONElement configSvrElem; BSONElement trackingElem; BSONElement clientElem; - BSONElement logicalTimeElem; BSONElement impersonationElem; BSONElement clientOperationKeyElem; @@ -73,8 +73,6 @@ void readRequestMetadata(OperationContext* opCtx, const BSONObj& metadataObj, bo clientElem = metadataElem; } else if (fieldName == TrackingMetadata::fieldName()) { trackingElem = metadataElem; - } else if (fieldName == LogicalTimeMetadata::fieldName()) { - logicalTimeElem = metadataElem; } else if (fieldName == kImpersonationMetadataSectionName) { impersonationElem = metadataElem; } else if (fieldName == "clientOperationKey"_sd) { @@ -107,43 +105,7 @@ void readRequestMetadata(OperationContext* opCtx, const BSONObj& metadataObj, bo TrackingMetadata::get(opCtx) = uassertStatusOK(TrackingMetadata::readFromMetadata(trackingElem)); - VectorClock::get(opCtx)->gossipIn(metadataObj, opCtx->getClient()->getSessionTags()); - - auto logicalClock = LogicalClock::get(opCtx); - if (logicalClock && logicalClock->isEnabled()) { - auto logicalTimeMetadata = - uassertStatusOK(rpc::LogicalTimeMetadata::readFromMetadata(logicalTimeElem)); - - auto& signedTime = logicalTimeMetadata.getSignedTime(); - - if (!requiresAuth && - AuthorizationManager::get(opCtx->getServiceContext())->isAuthEnabled() && - (!signedTime.getProof() || *signedTime.getProof() == TimeProofService::TimeProof())) { - - // The client is not authenticated and is not using localhost auth bypass. - if (authSession && !authSession->isAuthenticated() && - !authSession->isUsingLocalhostBypass()) { - return; - } - } - - // LogicalTimeMetadata is default constructed if no cluster time metadata was sent, so a - // default constructed SignedLogicalTime should be ignored. - if (signedTime.getTime() != LogicalTime::kUninitialized) { - auto logicalTimeValidator = LogicalTimeValidator::get(opCtx); - if (!LogicalTimeValidator::isAuthorizedToAdvanceClock(opCtx)) { - if (!logicalTimeValidator) { - uasserted(ErrorCodes::CannotVerifyAndSignLogicalTime, - "Cannot accept logicalTime: " + signedTime.getTime().toString() + - ". May not be a part of a sharded cluster"); - } else { - uassertStatusOK(logicalTimeValidator->validate(opCtx, signedTime)); - } - } - - uassertStatusOK(logicalClock->advanceClusterTime(signedTime.getTime())); - } - } + VectorClock::get(opCtx)->gossipIn(opCtx, metadataObj, !cmdRequiresAuth); } namespace { diff --git a/src/mongo/rpc/metadata/logical_time_metadata.cpp b/src/mongo/rpc/metadata/logical_time_metadata.cpp deleted file mode 100644 index f10e479aa4a..00000000000 --- a/src/mongo/rpc/metadata/logical_time_metadata.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * 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 Server Side 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/rpc/metadata/logical_time_metadata.h" - -#include "mongo/bson/bsonobjbuilder.h" -#include "mongo/bson/util/bson_extract.h" - -namespace mongo { -namespace rpc { - -namespace { - -const char kClusterTimeFieldName[] = "clusterTime"; -const char kSignatureFieldName[] = "signature"; -const char kSignatureHashFieldName[] = "hash"; -const char kSignatureKeyIdFieldName[] = "keyId"; - -} // unnamed namespace - - -LogicalTimeMetadata::LogicalTimeMetadata(SignedLogicalTime time) : _clusterTime(std::move(time)) {} - -StatusWith<LogicalTimeMetadata> LogicalTimeMetadata::readFromMetadata(const BSONObj& metadata) { - return readFromMetadata(metadata.getField(fieldName())); -} - -StatusWith<LogicalTimeMetadata> LogicalTimeMetadata::readFromMetadata( - const BSONElement& metadataElem) { - if (metadataElem.eoo()) { - return LogicalTimeMetadata(); - } - - const auto& obj = metadataElem.Obj(); - - Timestamp ts; - Status status = bsonExtractTimestampField(obj, kClusterTimeFieldName, &ts); - if (!status.isOK()) { - return status; - } - - BSONElement signatureElem; - status = bsonExtractTypedField(obj, kSignatureFieldName, Object, &signatureElem); - if (!status.isOK()) { - return status; - } - - const auto& signatureObj = signatureElem.Obj(); - - // Extract BinData type signature hash and construct a SHA1Block instance from it. - BSONElement hashElem; - status = bsonExtractTypedField(signatureObj, kSignatureHashFieldName, BinData, &hashElem); - if (!status.isOK()) { - return status; - } - - int hashLength = 0; - auto rawBinSignature = hashElem.binData(hashLength); - BSONBinData proofBinData(rawBinSignature, hashLength, hashElem.binDataType()); - auto proofStatus = SHA1Block::fromBinData(proofBinData); - - if (!proofStatus.isOK()) { - return proofStatus.getStatus(); - } - - long long keyId; - status = bsonExtractIntegerField(signatureObj, kSignatureKeyIdFieldName, &keyId); - if (!status.isOK()) { - return status; - } - - return LogicalTimeMetadata( - SignedLogicalTime(LogicalTime(ts), std::move(proofStatus.getValue()), keyId)); -} - -void LogicalTimeMetadata::writeToMetadata(BSONObjBuilder* metadataBuilder) const { - BSONObjBuilder subObjBuilder(metadataBuilder->subobjStart(fieldName())); - _clusterTime.getTime().asTimestamp().append(subObjBuilder.bb(), kClusterTimeFieldName); - - BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart(kSignatureFieldName)); - // Cluster time metadata is only written when the LogicalTimeValidator is set, which - // means the cluster time should always have a proof. - invariant(_clusterTime.getProof()); - _clusterTime.getProof()->appendAsBinData(signatureObjBuilder, kSignatureHashFieldName); - signatureObjBuilder.append(kSignatureKeyIdFieldName, _clusterTime.getKeyId()); - signatureObjBuilder.doneFast(); - - subObjBuilder.doneFast(); -} - -const SignedLogicalTime& LogicalTimeMetadata::getSignedTime() const { - return _clusterTime; -} - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/metadata/logical_time_metadata.h b/src/mongo/rpc/metadata/logical_time_metadata.h deleted file mode 100644 index 1b8c81e3286..00000000000 --- a/src/mongo/rpc/metadata/logical_time_metadata.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * 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 Server Side 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/base/status_with.h" -#include "mongo/db/signed_logical_time.h" - -namespace mongo { - -class BSONElement; -class BSONObjBuilder; - -namespace rpc { - -/** - * Format: - * logicalTime: { - * clusterTime: <Timestamp>, - * signature: { - * hash: <SHA1 hash of clusterTime as BinData>, - * keyId: <long long> - * } - * } - */ -class LogicalTimeMetadata { -public: - LogicalTimeMetadata() = default; - explicit LogicalTimeMetadata(SignedLogicalTime time); - - /** - * Parses the metadata from BSON. Returns an empty LogicalTimeMetadata If the metadata is not - * present. - */ - static StatusWith<LogicalTimeMetadata> readFromMetadata(const BSONObj& metadata); - static StatusWith<LogicalTimeMetadata> readFromMetadata(const BSONElement& metadataElem); - - void writeToMetadata(BSONObjBuilder* metadataBuilder) const; - - const SignedLogicalTime& getSignedTime() const; - - static StringData fieldName() { - return "$clusterTime"; - } - -private: - SignedLogicalTime _clusterTime; -}; - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/metadata/logical_time_metadata_test.cpp b/src/mongo/rpc/metadata/logical_time_metadata_test.cpp deleted file mode 100644 index a922b176446..00000000000 --- a/src/mongo/rpc/metadata/logical_time_metadata_test.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * 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 Server Side 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_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest - -#include "mongo/platform/basic.h" - -#include "mongo/db/jsobj.h" -#include "mongo/rpc/metadata.h" -#include "mongo/rpc/metadata/logical_time_metadata.h" -#include "mongo/unittest/unittest.h" - - -namespace mongo { -namespace rpc { -namespace { - -TEST(LogicalTimeMetadataTest, Roundtrip) { - const auto ts = LogicalTime(Timestamp(100, 200)); - - SHA1Block::HashType proof; - proof.fill(0); - proof[19] = 6; - proof[0] = 12; - - long long keyId = 1; - - SignedLogicalTime signedTs(LogicalTime(ts), proof, keyId); - - LogicalTimeMetadata origMetadata(signedTs); - BSONObjBuilder builder; - origMetadata.writeToMetadata(&builder); - - auto serializedObj = builder.done(); - auto parseStatus = LogicalTimeMetadata::readFromMetadata(serializedObj); - ASSERT_OK(parseStatus.getStatus()); - - const auto& parsedMetadata = parseStatus.getValue(); - const auto& parsedTs = parsedMetadata.getSignedTime(); - ASSERT_EQ(ts.asTimestamp(), parsedTs.getTime().asTimestamp()); - ASSERT_TRUE(SHA1Block(proof) == parsedTs.getProof()); - ASSERT_TRUE(keyId == parsedTs.getKeyId()); -} - -TEST(LogicalTimeMetadataTest, MissingClusterTimeShouldFailToParse) { - std::array<uint8_t, 20> proof; - proof.fill(0); - - long long keyId = 1; - - BSONObjBuilder builder; - BSONObjBuilder subObjBuilder(builder.subobjStart("$clusterTime")); - BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature")); - signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral)); - signatureObjBuilder.append("keyId", keyId); - signatureObjBuilder.doneFast(); - subObjBuilder.doneFast(); - - auto serializedObj = builder.done(); - auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus(); - ASSERT_EQ(ErrorCodes::NoSuchKey, status); -} - -TEST(LogicalTimeMetadataTest, MissingSignatureShouldFailToParse) { - const auto ts = Timestamp(100, 200); - - BSONObjBuilder builder; - BSONObjBuilder subObjBuilder(builder.subobjStart("$clusterTime")); - ts.append(subObjBuilder.bb(), "clusterTime"); - subObjBuilder.doneFast(); - - auto serializedObj = builder.done(); - auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus(); - ASSERT_EQ(ErrorCodes::NoSuchKey, status); -} - -TEST(LogicalTimeMetadataTest, MissingHashShouldFailToParse) { - const auto ts = Timestamp(100, 200); - - long long keyId = 1; - - BSONObjBuilder builder; - BSONObjBuilder subObjBuilder(builder.subobjStart("$clusterTime")); - ts.append(subObjBuilder.bb(), "clusterTime"); - BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature")); - signatureObjBuilder.append("keyId", keyId); - signatureObjBuilder.doneFast(); - subObjBuilder.doneFast(); - - auto serializedObj = builder.done(); - auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus(); - ASSERT_EQ(ErrorCodes::NoSuchKey, status); -} - -TEST(LogicalTimeMetadataTest, MissingKeyIdShouldFailToParse) { - const auto ts = Timestamp(100, 200); - - std::array<uint8_t, 20> proof; - proof.fill(0); - - BSONObjBuilder builder; - BSONObjBuilder subObjBuilder(builder.subobjStart("$clusterTime")); - ts.append(subObjBuilder.bb(), "clusterTime"); - BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature")); - signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral)); - signatureObjBuilder.doneFast(); - subObjBuilder.doneFast(); - - auto serializedObj = builder.done(); - auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus(); - ASSERT_EQ(ErrorCodes::NoSuchKey, status); -} - -TEST(LogicalTimeMetadataTest, ProofWithWrongLengthShouldFailToParse) { - const auto ts = Timestamp(100, 200); - - std::array<uint8_t, 10> proof; - proof.fill(0); - - long long keyId = 1; - - BSONObjBuilder builder; - BSONObjBuilder subObjBuilder(builder.subobjStart("$clusterTime")); - ts.append(subObjBuilder.bb(), "clusterTime"); - BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature")); - signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral)); - signatureObjBuilder.append("keyId", keyId); - signatureObjBuilder.doneFast(); - subObjBuilder.doneFast(); - - auto serializedObj = builder.done(); - auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus(); - ASSERT_EQ(ErrorCodes::UnsupportedFormat, status); -} - -TEST(LogicalTimeMetadataTest, UpconvertPass) { - - const auto ts = Timestamp(100, 200); - - std::array<uint8_t, 20> proof; - proof.fill(0); - - long long keyId = 1; - - BSONObjBuilder builder; - builder.append("aaa", 1); - builder.append("bbb", 1); - BSONObjBuilder subObjBuilder(builder.subobjStart("$clusterTime")); - ts.append(subObjBuilder.bb(), "clusterTime"); - BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature")); - signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral)); - signatureObjBuilder.append("keyId", keyId); - signatureObjBuilder.doneFast(); - auto logicalTimeMetadata = subObjBuilder.asTempObj(); - subObjBuilder.doneFast(); - - auto commandObj = builder.done(); - BSONObjBuilder metadataBob; - BSONObjBuilder commandBob; - auto converted = upconvertRequest("db", commandObj, 0); - ASSERT_BSONOBJ_EQ(BSON("aaa" << 1 << "bbb" << 1 << "$clusterTime" << logicalTimeMetadata - << "$db" - << "db"), - converted.body); -} - -} // namespace -} // namespace rpc -} // namespace mongo |