summaryrefslogtreecommitdiff
path: root/src/mongo/rpc/metadata
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/rpc/metadata
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (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.cpp52
-rw-r--r--src/mongo/rpc/metadata/client_metadata.h31
-rw-r--r--src/mongo/rpc/metadata/client_metadata_test.cpp72
-rw-r--r--src/mongo/rpc/metadata/impersonated_user_metadata.cpp50
-rw-r--r--src/mongo/rpc/metadata/impersonated_user_metadata.h6
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(&section);
}
-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