summaryrefslogtreecommitdiff
path: root/src/mongo/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r--src/mongo/rpc/SConscript3
-rw-r--r--src/mongo/rpc/get_status_from_command_result.cpp2
-rw-r--r--src/mongo/rpc/legacy_reply_builder.h2
-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
8 files changed, 38 insertions, 180 deletions
diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript
index 10d73388ce1..c29f3802726 100644
--- a/src/mongo/rpc/SConscript
+++ b/src/mongo/rpc/SConscript
@@ -40,7 +40,6 @@ protoEnv.Library(
'$BUILD_DIR/mongo/db/wire_version',
],
LIBDEPS_PRIVATE=[
- '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/bson/util/bson_extract',
'$BUILD_DIR/mongo/db/auth/security_token',
'$BUILD_DIR/mongo/db/bson/dotted_path_support',
@@ -65,7 +64,6 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
- '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/db/dbmessage',
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/db/stats/counters',
@@ -167,7 +165,6 @@ env.Library(
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/s/is_mongos',
- '$BUILD_DIR/mongo/transport/message_compressor',
'$BUILD_DIR/mongo/transport/transport_layer_common',
"$BUILD_DIR/mongo/util/concurrency/spin_lock",
'$BUILD_DIR/mongo/util/net/network',
diff --git a/src/mongo/rpc/get_status_from_command_result.cpp b/src/mongo/rpc/get_status_from_command_result.cpp
index 315d4ef3135..2607ff15e3c 100644
--- a/src/mongo/rpc/get_status_from_command_result.cpp
+++ b/src/mongo/rpc/get_status_from_command_result.cpp
@@ -50,7 +50,7 @@ Status getStatusFromCommandResult(const BSONObj& result) {
BSONElement codeElement = result["code"];
BSONElement errmsgElement = result["errmsg"];
- // StaleConfig doesn't pass "ok" in legacy servers
+ // StaleConfigException doesn't pass "ok" in legacy servers
BSONElement dollarErrElement = result["$err"];
if (okElement.eoo() && dollarErrElement.eoo()) {
diff --git a/src/mongo/rpc/legacy_reply_builder.h b/src/mongo/rpc/legacy_reply_builder.h
index 22a9c4566f6..45e986ab9ed 100644
--- a/src/mongo/rpc/legacy_reply_builder.h
+++ b/src/mongo/rpc/legacy_reply_builder.h
@@ -49,7 +49,7 @@ public:
LegacyReplyBuilder(Message&&);
~LegacyReplyBuilder() final;
- // Override of setCommandReply specifically used to handle StaleConfig errors
+ // Override of setCommandReply specifically used to handle StaleConfigException.
LegacyReplyBuilder& setCommandReply(Status nonOKStatus, BSONObj extraErrorInfo) final;
LegacyReplyBuilder& setRawCommandReply(const BSONObj& commandReply) final;
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