Skip to content

Commit 13ec2c8

Browse files
authored
SWIFT-1229, SWIFT-1216, SWIFT-1243 Vendor libmongoc patch and sync command monitoring tests (#643)
1 parent 3779365 commit 13ec2c8

29 files changed

+1069
-81
lines changed

.evergreen/config.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,10 @@ functions:
231231
SWIFT_VERSION=${SWIFT_VERSION} \
232232
bash ${PROJECT_DIRECTORY}/.evergreen/install-tools.sh sourcery
233233
make linuxmain SOURCERY=${PROJECT_DIRECTORY}/opt/sourcery/bin/sourcery
234-
git diff --exit-code Tests/LinuxMain.swift
234+
# use regex to ignore lines starting with a /
235+
git diff -G "^[^\/].*\n" --exit-code Tests/LinuxMain.swift
235236
make exports SOURCERY=${PROJECT_DIRECTORY}/opt/sourcery/bin/sourcery
236-
git diff --exit-code Sources/MongoSwiftSync/Exports.swift
237+
git diff -G "^[^\/].*\n" --exit-code Sources/MongoSwiftSync/Exports.swift
237238
238239
pre:
239240
- func: "fetch source"

.evergreen/install-tools.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ then
4545
build_from_gh swiftformat https://github.com/nicklockwood/SwiftFormat "0.47.3"
4646
elif [ $1 == "sourcery" ]
4747
then
48-
install_from_gh sourcery https://github.com/krzysztofzablocki/Sourcery/releases/download/1.0.0/Sourcery-1.0.0.zip
48+
install_from_gh sourcery https://github.com/krzysztofzablocki/Sourcery/releases/download/1.3.4/Sourcery-1.3.4.zip
4949
else
5050
echo Missing/unknown install option: "$1"
5151
fi

Sources/CLibMongoC/mongoc/mongoc-apm-private.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ struct _mongoc_apm_command_started_t {
6060

6161
struct _mongoc_apm_command_succeeded_t {
6262
int64_t duration;
63-
const bson_t *reply;
63+
bson_t *reply;
64+
bool reply_owned;
6465
const char *command_name;
6566
int64_t request_id;
6667
int64_t operation_id;
@@ -73,7 +74,8 @@ struct _mongoc_apm_command_failed_t {
7374
int64_t duration;
7475
const char *command_name;
7576
const bson_error_t *error;
76-
const bson_t *reply;
77+
bson_t *reply;
78+
bool reply_owned;
7779
int64_t request_id;
7880
int64_t operation_id;
7981
const mongoc_host_list_t *host;
@@ -153,12 +155,14 @@ mongoc_apm_command_started_init (mongoc_apm_command_started_t *event,
153155
int64_t operation_id,
154156
const mongoc_host_list_t *host,
155157
uint32_t server_id,
158+
bool *is_redacted, /* out */
156159
void *context);
157160

158161
void
159162
mongoc_apm_command_started_init_with_cmd (mongoc_apm_command_started_t *event,
160163
struct _mongoc_cmd_t *cmd,
161164
int64_t request_id,
165+
bool *is_redacted, /* out */
162166
void *context);
163167

164168
void
@@ -173,6 +177,7 @@ mongoc_apm_command_succeeded_init (mongoc_apm_command_succeeded_t *event,
173177
int64_t operation_id,
174178
const mongoc_host_list_t *host,
175179
uint32_t server_id,
180+
bool force_redaction,
176181
void *context);
177182

178183
void
@@ -188,11 +193,19 @@ mongoc_apm_command_failed_init (mongoc_apm_command_failed_t *event,
188193
int64_t operation_id,
189194
const mongoc_host_list_t *host,
190195
uint32_t server_id,
196+
bool force_redaction,
191197
void *context);
192198

193199
void
194200
mongoc_apm_command_failed_cleanup (mongoc_apm_command_failed_t *event);
195201

202+
bool
203+
mongoc_apm_is_sensitive_command (const char *command_name,
204+
const bson_t *command);
205+
206+
bool
207+
mongoc_apm_is_sensitive_reply (const char *command_name, const bson_t *reply);
208+
196209
BSON_END_DECLS
197210

198211
#endif /* MONGOC_APM_PRIVATE_H */

Sources/CLibMongoC/mongoc/mongoc-apm.c

Lines changed: 170 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "mongoc-util-private.h"
1818
#include "mongoc-apm-private.h"
1919
#include "mongoc-cmd-private.h"
20+
#include "mongoc-handshake-private.h"
2021

2122
/*
2223
* An Application Performance Management (APM) implementation, complying with
@@ -46,6 +47,24 @@ append_documents_from_cmd (const mongoc_cmd_t *cmd,
4647
* Private initializer / cleanup functions.
4748
*/
4849

50+
static void
51+
mongoc_apm_redact_command (bson_t *command);
52+
53+
static void
54+
mongoc_apm_redact_reply (bson_t *reply);
55+
56+
/*--------------------------------------------------------------------------
57+
*
58+
* mongoc_apm_command_started_init --
59+
*
60+
* Initialises the command started event.
61+
*
62+
* Side effects:
63+
* If provided, is_redacted indicates whether the command document was
64+
* redacted to hide sensitive information.
65+
*
66+
*--------------------------------------------------------------------------
67+
*/
4968
void
5069
mongoc_apm_command_started_init (mongoc_apm_command_started_t *event,
5170
const bson_t *command,
@@ -55,6 +74,7 @@ mongoc_apm_command_started_init (mongoc_apm_command_started_t *event,
5574
int64_t operation_id,
5675
const mongoc_host_list_t *host,
5776
uint32_t server_id,
77+
bool *is_redacted, /* out */
5878
void *context)
5979
{
6080
bson_iter_t iter;
@@ -87,6 +107,21 @@ mongoc_apm_command_started_init (mongoc_apm_command_started_t *event,
87107
event->command_owned = false;
88108
}
89109

110+
if (mongoc_apm_is_sensitive_command (command_name, command)) {
111+
if (!event->command_owned) {
112+
event->command = bson_copy (event->command);
113+
event->command_owned = true;
114+
}
115+
116+
if (is_redacted) {
117+
*is_redacted = true;
118+
}
119+
120+
mongoc_apm_redact_command (event->command);
121+
} else if (is_redacted) {
122+
*is_redacted = false;
123+
}
124+
90125
event->database_name = database_name;
91126
event->command_name = command_name;
92127
event->request_id = request_id;
@@ -97,10 +132,23 @@ mongoc_apm_command_started_init (mongoc_apm_command_started_t *event,
97132
}
98133

99134

135+
/*--------------------------------------------------------------------------
136+
*
137+
* mongoc_apm_command_started_init_with_cmd --
138+
*
139+
* Initialises the command started event from a mongoc_cmd_t.
140+
*
141+
* Side effects:
142+
* If provided, is_redacted indicates whether the command document was
143+
* redacted to hide sensitive information.
144+
*
145+
*--------------------------------------------------------------------------
146+
*/
100147
void
101148
mongoc_apm_command_started_init_with_cmd (mongoc_apm_command_started_t *event,
102149
mongoc_cmd_t *cmd,
103150
int64_t request_id,
151+
bool *is_redacted, /* out */
104152
void *context)
105153
{
106154
mongoc_apm_command_started_init (event,
@@ -111,6 +159,7 @@ mongoc_apm_command_started_init_with_cmd (mongoc_apm_command_started_t *event,
111159
cmd->operation_id,
112160
&cmd->server_stream->sd->host,
113161
cmd->server_stream->sd->id,
162+
is_redacted,
114163
context);
115164

116165
/* OP_MSG document sequence for insert, update, or delete? */
@@ -127,6 +176,18 @@ mongoc_apm_command_started_cleanup (mongoc_apm_command_started_t *event)
127176
}
128177

129178

179+
/*--------------------------------------------------------------------------
180+
*
181+
* mongoc_apm_command_succeeded_init --
182+
*
183+
* Initialises the command succeeded event.
184+
*
185+
* Parameters:
186+
* @force_redaction: If true, the reply document is always redacted,
187+
* regardless of whether the command contains sensitive information.
188+
*
189+
*--------------------------------------------------------------------------
190+
*/
130191
void
131192
mongoc_apm_command_succeeded_init (mongoc_apm_command_succeeded_t *event,
132193
int64_t duration,
@@ -136,12 +197,23 @@ mongoc_apm_command_succeeded_init (mongoc_apm_command_succeeded_t *event,
136197
int64_t operation_id,
137198
const mongoc_host_list_t *host,
138199
uint32_t server_id,
200+
bool force_redaction,
139201
void *context)
140202
{
141203
BSON_ASSERT (reply);
142204

205+
if (force_redaction || mongoc_apm_is_sensitive_reply (command_name, reply)) {
206+
event->reply = bson_copy (reply);
207+
event->reply_owned = true;
208+
209+
mongoc_apm_redact_reply (event->reply);
210+
} else {
211+
/* discard "const", we promise not to modify "reply" */
212+
event->reply = (bson_t *) reply;
213+
event->reply_owned = false;
214+
}
215+
143216
event->duration = duration;
144-
event->reply = reply;
145217
event->command_name = command_name;
146218
event->request_id = request_id;
147219
event->operation_id = operation_id;
@@ -154,10 +226,24 @@ mongoc_apm_command_succeeded_init (mongoc_apm_command_succeeded_t *event,
154226
void
155227
mongoc_apm_command_succeeded_cleanup (mongoc_apm_command_succeeded_t *event)
156228
{
157-
/* no-op */
229+
if (event->reply_owned) {
230+
bson_destroy (event->reply);
231+
}
158232
}
159233

160234

235+
/*--------------------------------------------------------------------------
236+
*
237+
* mongoc_apm_command_failed_init --
238+
*
239+
* Initialises the command failed event.
240+
*
241+
* Parameters:
242+
* @force_redaction: If true, the reply document is always redacted,
243+
* regardless of whether the command contains sensitive information.
244+
*
245+
*--------------------------------------------------------------------------
246+
*/
161247
void
162248
mongoc_apm_command_failed_init (mongoc_apm_command_failed_t *event,
163249
int64_t duration,
@@ -168,14 +254,25 @@ mongoc_apm_command_failed_init (mongoc_apm_command_failed_t *event,
168254
int64_t operation_id,
169255
const mongoc_host_list_t *host,
170256
uint32_t server_id,
257+
bool force_redaction,
171258
void *context)
172259
{
173260
BSON_ASSERT (reply);
174261

262+
if (force_redaction || mongoc_apm_is_sensitive_reply (command_name, reply)) {
263+
event->reply = bson_copy (reply);
264+
event->reply_owned = true;
265+
266+
mongoc_apm_redact_reply (event->reply);
267+
} else {
268+
/* discard "const", we promise not to modify "reply" */
269+
event->reply = (bson_t *) reply;
270+
event->reply_owned = false;
271+
}
272+
175273
event->duration = duration;
176274
event->command_name = command_name;
177275
event->error = error;
178-
event->reply = reply;
179276
event->request_id = request_id;
180277
event->operation_id = operation_id;
181278
event->host = host;
@@ -187,7 +284,9 @@ mongoc_apm_command_failed_init (mongoc_apm_command_failed_t *event,
187284
void
188285
mongoc_apm_command_failed_cleanup (mongoc_apm_command_failed_t *event)
189286
{
190-
/* no-op */
287+
if (event->reply_owned) {
288+
bson_destroy (event->reply);
289+
}
191290
}
192291

193292

@@ -775,3 +874,70 @@ mongoc_apm_set_server_heartbeat_failed_cb (
775874
{
776875
callbacks->server_heartbeat_failed = cb;
777876
}
877+
878+
static bool
879+
_mongoc_apm_is_sensitive_command_name (const char *command_name)
880+
{
881+
return 0 == strcasecmp (command_name, "authenticate") ||
882+
0 == strcasecmp (command_name, "saslStart") ||
883+
0 == strcasecmp (command_name, "saslContinue") ||
884+
0 == strcasecmp (command_name, "getnonce") ||
885+
0 == strcasecmp (command_name, "createUser") ||
886+
0 == strcasecmp (command_name, "updateUser") ||
887+
0 == strcasecmp (command_name, "copydbgetnonce") ||
888+
0 == strcasecmp (command_name, "copydbsaslstart") ||
889+
0 == strcasecmp (command_name, "copydb");
890+
}
891+
892+
bool
893+
mongoc_apm_is_sensitive_command (const char *command_name,
894+
const bson_t *command)
895+
{
896+
BSON_ASSERT (command);
897+
898+
if (_mongoc_apm_is_sensitive_command_name (command_name)) {
899+
return true;
900+
}
901+
902+
if (0 != strcasecmp (command_name, "hello") &&
903+
0 != strcasecmp (command_name, "ismaster")) {
904+
return false;
905+
}
906+
907+
return bson_has_field (command, "speculativeAuthenticate");
908+
}
909+
910+
void
911+
mongoc_apm_redact_command (bson_t *command)
912+
{
913+
BSON_ASSERT (command);
914+
915+
/* Reinit the command to have an empty document */
916+
bson_reinit (command);
917+
}
918+
919+
bool
920+
mongoc_apm_is_sensitive_reply (const char *command_name, const bson_t *reply)
921+
{
922+
BSON_ASSERT (reply);
923+
924+
if (_mongoc_apm_is_sensitive_command_name (command_name)) {
925+
return true;
926+
}
927+
928+
if (0 != strcasecmp (command_name, "hello") &&
929+
0 != strcasecmp (command_name, "ismaster")) {
930+
return false;
931+
}
932+
933+
return bson_has_field (reply, "speculativeAuthenticate");
934+
}
935+
936+
void
937+
mongoc_apm_redact_reply (bson_t *reply)
938+
{
939+
BSON_ASSERT (reply);
940+
941+
/* Reinit the reply to have an empty document */
942+
bson_reinit (reply);
943+
}

0 commit comments

Comments
 (0)