diff options
| author | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-11 15:07:35 -0300 |
|---|---|---|
| committer | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-11 15:07:35 -0300 |
| commit | 4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch) | |
| tree | 1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/rpc/metadata | |
| parent | aa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff) | |
| parent | 8f0827553e09872941945a093b647a4211a9db7f (diff) | |
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0'
with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'src/mongo/rpc/metadata')
| -rw-r--r-- | src/mongo/rpc/metadata/client_metadata.cpp | 52 | ||||
| -rw-r--r-- | src/mongo/rpc/metadata/client_metadata.h | 31 | ||||
| -rw-r--r-- | src/mongo/rpc/metadata/client_metadata_test.cpp | 72 | ||||
| -rw-r--r-- | src/mongo/rpc/metadata/impersonated_user_metadata.cpp | 50 | ||||
| -rw-r--r-- | src/mongo/rpc/metadata/impersonated_user_metadata.h | 6 |
5 files changed, 36 insertions, 175 deletions
diff --git a/src/mongo/rpc/metadata/client_metadata.cpp b/src/mongo/rpc/metadata/client_metadata.cpp index 8ac4f4a9d97..86d7230120e 100644 --- a/src/mongo/rpc/metadata/client_metadata.cpp +++ b/src/mongo/rpc/metadata/client_metadata.cpp @@ -43,8 +43,6 @@ #include "mongo/db/operation_context.h" #include "mongo/logv2/log.h" #include "mongo/s/is_mongos.h" -#include "mongo/transport/message_compressor_base.h" -#include "mongo/transport/message_compressor_manager.h" #include "mongo/util/debug_util.h" #include "mongo/util/net/socket_utils.h" #include "mongo/util/processinfo.h" @@ -158,7 +156,7 @@ ClientMetadata::ClientMetadata(BSONObj doc) { foundOperatingSystem); } -StatusWith<std::string> ClientMetadata::parseApplicationDocument(const BSONObj& doc) { +StatusWith<StringData> ClientMetadata::parseApplicationDocument(const BSONObj& doc) { BSONObjIterator i(doc); while (i.more()) { @@ -175,7 +173,7 @@ StatusWith<std::string> ClientMetadata::parseApplicationDocument(const BSONObj& << "' field must be a string in the client metadata document"}; } - std::string value = str::escape(e.checkAndGetStringData().toString()); + StringData value = e.checkAndGetStringData(); if (value.size() > kMaxApplicationNameByteLength) { return {ErrorCodes::ClientMetadataAppNameTooLarge, @@ -185,11 +183,11 @@ StatusWith<std::string> ClientMetadata::parseApplicationDocument(const BSONObj& << " bytes in the client metadata document"}; } - return std::move(value); + return {std::move(value)}; } } - return std::string(); + return {StringData()}; } Status ClientMetadata::validateDriverDocument(const BSONObj& doc) { @@ -269,7 +267,6 @@ Status ClientMetadata::validateOperatingSystemDocument(const BSONObj& doc) { void ClientMetadata::setMongoSMetadata(StringData hostAndPort, StringData mongosClient, StringData version) { - _documentWithoutMongosInfo = _document; BSONObjBuilder builder; builder.appendElements(_document); @@ -280,7 +277,25 @@ void ClientMetadata::setMongoSMetadata(StringData hostAndPort, sub.append(kVersion, version); } - _document = builder.obj(); + auto document = builder.obj(); + + if (!_appName.empty()) { + // The _appName field points into the existing _document, which we are about to replace. + // We must redirect _appName to point into the new doc *before* replacing the old doc. We + // expect the 'application' metadata of the new document to be identical to the old. + auto appMetaData = document[kApplication]; + invariant(appMetaData.isABSONObj()); + + auto appNameEl = appMetaData[kName]; + invariant(appNameEl.type() == BSONType::String); + + auto appName = appNameEl.valueStringData(); + invariant(appName == _appName); + + _appName = appName; + } + + _document = std::move(document); } void ClientMetadata::serialize(StringData driverName, @@ -375,40 +390,23 @@ Status ClientMetadata::serializePrivate(StringData driverName, } StringData ClientMetadata::getApplicationName() const { - return StringData(_appName); + return _appName; } const BSONObj& ClientMetadata::getDocument() const { return _document; } -unsigned long ClientMetadata::hashWithoutMongosInfo() const { - return _hashWithoutMongos.get(documentWithoutMongosInfo()); -} - -const BSONObj& ClientMetadata::documentWithoutMongosInfo() const { - return _documentWithoutMongosInfo.get(_document); -} - void ClientMetadata::logClientMetadata(Client* client) const { if (getDocument().isEmpty()) { return; } - auto negotiatedCompressors = - MessageCompressorManager::forSession(client->session()).getNegotiatedCompressors(); - std::vector<StringData> negotiatedCompressorNames(negotiatedCompressors.size(), nullptr); - std::transform( - negotiatedCompressors.begin(), - negotiatedCompressors.end(), - negotiatedCompressorNames.begin(), - [](auto& messageCompressor) { return StringData(messageCompressor->getName()); }); - LOGV2(51800, + "received client metadata from {remote} {client}: {doc}", "client metadata", "remote"_attr = client->getRemote(), "client"_attr = client->desc(), - "negotiatedCompressors"_attr = negotiatedCompressorNames, "doc"_attr = getDocument()); } diff --git a/src/mongo/rpc/metadata/client_metadata.h b/src/mongo/rpc/metadata/client_metadata.h index 0c5cabdae7b..309eb5668e0 100644 --- a/src/mongo/rpc/metadata/client_metadata.h +++ b/src/mongo/rpc/metadata/client_metadata.h @@ -36,8 +36,6 @@ #include "mongo/base/string_data.h" #include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobjbuilder.h" -#include "mongo/bson/simple_bsonobj_comparator.h" -#include "mongo/db/query/util/deferred.h" namespace mongo { @@ -289,21 +287,6 @@ public: const BSONObj& getDocument() const; /** - * A lazily computed (and subsequently cached) copy of the metadata with the mongos info - * removed. This is useful for collecting query stats where we want to scrub out this - * high-cardinality field, and we don't want to re-do this computation over and over again. - */ - const BSONObj& documentWithoutMongosInfo() const; - - /** - * Get the simple hash of the client metadata document (simple meaning no collation). - * - * The hash is generated on the first call to this method. Future calls will return the cached - * hash rather than recomputing. - */ - unsigned long hashWithoutMongosInfo() const; - - /** * Log client and client metadata information to disk. */ void logClientMetadata(Client* client) const; @@ -343,7 +326,7 @@ private: static Status validateDriverDocument(const BSONObj& doc); static Status validateOperatingSystemDocument(const BSONObj& doc); - static StatusWith<std::string> parseApplicationDocument(const BSONObj& doc); + static StatusWith<StringData> parseApplicationDocument(const BSONObj& doc); private: // Parsed Client Metadata document @@ -353,17 +336,7 @@ private: // Application Name extracted from the client metadata document. // May be empty - std::string _appName; - - // See documentWithoutMongosInfo(). - Deferred<BSONObj, const BSONObj&> _documentWithoutMongosInfo{ - [](const BSONObj& fullDocument) { return fullDocument.removeField("mongos"); }}; - - // See hashWithoutMongosInfo(). - Deferred<unsigned long, const BSONObj&> _hashWithoutMongos{ - [](const BSONObj& documentWithoutMongosInfo) { - return simpleHash(documentWithoutMongosInfo); - }}; + StringData _appName; }; } // namespace mongo diff --git a/src/mongo/rpc/metadata/client_metadata_test.cpp b/src/mongo/rpc/metadata/client_metadata_test.cpp index 4b698aa3a14..becb3af5698 100644 --- a/src/mongo/rpc/metadata/client_metadata_test.cpp +++ b/src/mongo/rpc/metadata/client_metadata_test.cpp @@ -308,17 +308,16 @@ TEST(ClientMetadataTest, TestMongoSAppend) { auto obj = builder.obj(); auto swParseStatus = ClientMetadata::parse(obj[kMetadataDoc]); ASSERT_OK(swParseStatus.getStatus()); - auto metaObj = swParseStatus.getValue().value(); - ASSERT_EQUALS("g", metaObj.getApplicationName()); - auto docBeforeMongos = obj[kMetadataDoc].Obj(); - ASSERT_BSONOBJ_EQ(metaObj.getDocument(), docBeforeMongos); + ASSERT_EQUALS("g", swParseStatus.getValue().get().getApplicationName()); - metaObj.setMongoSMetadata("h", "i", "j"); - ASSERT_BSONOBJ_NE(metaObj.getDocument(), docBeforeMongos); - ASSERT_EQUALS("g", metaObj.getApplicationName()); + swParseStatus.getValue().get().setMongoSMetadata("h", "i", "j"); + ASSERT_EQUALS("g", swParseStatus.getValue().get().getApplicationName()); - auto docWithMongosInfo = metaObj.getDocument(); - ASSERT_BSONOBJ_EQ(metaObj.documentWithoutMongosInfo(), docBeforeMongos); + auto doc = swParseStatus.getValue().get().getDocument(); + + constexpr auto kMongos = "mongos"_sd; + constexpr auto kClient = "client"_sd; + constexpr auto kHost = "host"_sd; auto pid = ProcessId::getCurrent().toString(); @@ -341,60 +340,7 @@ TEST(ClientMetadataTest, TestMongoSAppend) { .append(kMongos, BOB{}.append(kHost, "h").append(kClient, "i").append(kVersion, "j").obj()) .obj(); - ASSERT_BSONOBJ_EQ(docWithMongosInfo, outDoc); -} - -// Test that if mongos information is present from the beginning, we can still request the document -// without the mongos info. -TEST(ClientMetadataTest, MongosMetaCanBeRemoved) { - BSONObjBuilder realBuilder; - BSONObjBuilder tmpBuilder; - ASSERT_OK(ClientMetadata::serializePrivate("a", "b", "c", "d", "e", "f", "g", &tmpBuilder)); - auto objWithoutMongosMeta = tmpBuilder.obj(); - const auto metaBsonNoMongosInfo = objWithoutMongosMeta[kMetadataDoc].Obj(); - { - BSONObjBuilder metaBuilder = realBuilder.subobjStart(kMetadataDoc); - metaBuilder.appendElements(metaBsonNoMongosInfo); - metaBuilder.append("mongos", BSON(kHost << "h" << kClient << "i" << kVersion << "j")); - metaBuilder.doneFast(); - } - - const auto wrappingMetaBson = realBuilder.obj(); - const auto metaElt = wrappingMetaBson[kMetadataDoc]; - // Add this mongos info without calling 'setMongoSMetadata().' - ASSERT_BSONOBJ_NE(metaElt.Obj(), metaBsonNoMongosInfo); - - auto swParseStatus = ClientMetadata::parse(metaElt); - ASSERT_OK(swParseStatus.getStatus()); - const auto& metaObj = swParseStatus.getValue().value(); - // Test the various copy/move constructors. - ClientMetadata copyConstructed(metaObj); - auto tmpThirdCopy = metaObj; - ClientMetadata moveConstructed(std::move(tmpThirdCopy)); - - auto tmpFourthCopy = metaObj; - auto moveAssigned = metaObj; // copy for now, until next line. - moveAssigned = std::move(tmpFourthCopy); - - const auto tmpFifthCopy = metaObj; - auto copyAssigned = metaObj; // copy construct. - copyAssigned = tmpFifthCopy; // copy assign. - - ASSERT_BSONOBJ_EQ(metaObj.getDocument(), metaElt.Obj()); - ASSERT_BSONOBJ_EQ(metaObj.documentWithoutMongosInfo(), metaBsonNoMongosInfo); - ASSERT_BSONOBJ_EQ(metaObj.documentWithoutMongosInfo(), - copyConstructed.documentWithoutMongosInfo()); - ASSERT_BSONOBJ_EQ(metaObj.documentWithoutMongosInfo(), - moveConstructed.documentWithoutMongosInfo()); - ASSERT_BSONOBJ_EQ(metaObj.documentWithoutMongosInfo(), - copyAssigned.documentWithoutMongosInfo()); - ASSERT_BSONOBJ_EQ(metaObj.documentWithoutMongosInfo(), - moveAssigned.documentWithoutMongosInfo()); - - ASSERT_EQ(metaObj.hashWithoutMongosInfo(), copyConstructed.hashWithoutMongosInfo()); - ASSERT_EQ(metaObj.hashWithoutMongosInfo(), moveConstructed.hashWithoutMongosInfo()); - ASSERT_EQ(metaObj.hashWithoutMongosInfo(), copyAssigned.hashWithoutMongosInfo()); - ASSERT_EQ(metaObj.hashWithoutMongosInfo(), moveAssigned.hashWithoutMongosInfo()); + ASSERT_BSONOBJ_EQ(doc, outDoc); } TEST(ClientMetadataTest, TestInvalidDocWhileSettingOpCtxMetadata) { diff --git a/src/mongo/rpc/metadata/impersonated_user_metadata.cpp b/src/mongo/rpc/metadata/impersonated_user_metadata.cpp index 3ee1a8c4320..64b78931f39 100644 --- a/src/mongo/rpc/metadata/impersonated_user_metadata.cpp +++ b/src/mongo/rpc/metadata/impersonated_user_metadata.cpp @@ -95,55 +95,5 @@ void writeAuthDataToImpersonatedUserMetadata(OperationContext* opCtx, BSONObjBui metadata.serialize(§ion); } -std::size_t estimateImpersonatedUserMetadataSize(OperationContext* opCtx) { - if (!opCtx) { - return 0; - } - - // Otherwise construct a metadata section from the list of authenticated users/roles - auto authSession = AuthorizationSession::get(opCtx->getClient()); - auto userNames = authSession->getImpersonatedUserNames(); - auto roleNames = authSession->getImpersonatedRoleNames(); - if (!userNames.more() && !roleNames.more()) { - userNames = authSession->getAuthenticatedUserNames(); - roleNames = authSession->getAuthenticatedRoleNames(); - } - - // If there are no users/roles being impersonated just exit - if (!userNames.more() && !roleNames.more()) { - return 0; - } - - std::size_t ret = 4 + // BSONObj size - 1 + kImpersonationMetadataSectionName.size() + 1 + // "$audit" sub-object key - 4; // $audit object length - - // BSONArrayType + "impersonatedUsers" + NULL + BSONArray Length - ret += 1 + ImpersonatedUserMetadata::kUsersFieldName.size() + 1 + 4; - for (std::size_t i = 0; userNames.more(); userNames.next(), ++i) { - // BSONType::Object + strlen(indexId) + NULL byte - // to_string(i).size() will be log10(i) plus some rounding and fuzzing. - // Increment prior to taking the log so that we never take log10(0) which is NAN. - // This estimates one extra byte every time we reach (i % 10) == 9. - ret += 1 + static_cast<std::size_t>(1.1 + log10(i + 1)) + 1; - ret += userNames.get().getBSONObjSize(); - } - // EOD terminator for impersonatedUsers - ++ret; - - // BSONArrayType + "impersonatedRoles" + NULL + BSONArray Length - ret += 1 + ImpersonatedUserMetadata::kRolesFieldName.size() + 1 + 4; - for (std::size_t i = 0; roleNames.more(); roleNames.next(), ++i) { - // Same calculation as for UserNames above. - ret += 1 + static_cast<std::size_t>(1.1 + log10(i + 1)) + 1; - ret += roleNames.get().getBSONObjSize(); - } - - // EOD terminators for: impersonatedRoles, $audit, and metadata - ret += 1 + 1 + 1; - - return ret; -} - } // namespace rpc } // namespace mongo diff --git a/src/mongo/rpc/metadata/impersonated_user_metadata.h b/src/mongo/rpc/metadata/impersonated_user_metadata.h index 21f010d5447..71c927e80b1 100644 --- a/src/mongo/rpc/metadata/impersonated_user_metadata.h +++ b/src/mongo/rpc/metadata/impersonated_user_metadata.h @@ -70,11 +70,5 @@ void readImpersonatedUserMetadata(const BSONElement& elem, OperationContext* opC */ void writeAuthDataToImpersonatedUserMetadata(OperationContext* opCtx, BSONObjBuilder* out); -/* - * Estimates the size of impersonation metadata which will be written by - * writeAuthDataToImpersonatedUserMetadata. - */ -std::size_t estimateImpersonatedUserMetadataSize(OperationContext* opCtx); - } // namespace rpc } // namespace mongo |
