Skip to content

Commit c3c4c3f

Browse files
GODRIVER-2458 Do not append maxTimeMS when connected to mongocryptd. (#1074)
Co-authored-by: Kevin Albertson <[email protected]>
1 parent e7fe408 commit c3c4c3f

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

mongo/description/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type Server struct {
4040
HeartbeatInterval time.Duration
4141
HelloOK bool
4242
Hosts []string
43+
IsCryptd bool
4344
LastError error
4445
LastUpdateTime time.Time
4546
LastWriteTime time.Time
@@ -101,6 +102,12 @@ func NewServer(addr address.Address, response bson.Raw) Server {
101102
desc.LastError = fmt.Errorf("expected 'electionId' to be a objectID but it's a BSON %s", element.Value().Type)
102103
return desc
103104
}
105+
case "iscryptd":
106+
desc.IsCryptd, ok = element.Value().BooleanOK()
107+
if !ok {
108+
desc.LastError = fmt.Errorf("expected 'iscryptd' to be a boolean but it's a BSON %s", element.Value().Type)
109+
return desc
110+
}
104111
case "helloOk":
105112
desc.HelloOK, ok = element.Value().BooleanOK()
106113
if !ok {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (C) MongoDB, Inc. 2022-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
//go:build cse
8+
// +build cse
9+
10+
package integration
11+
12+
import (
13+
"context"
14+
"testing"
15+
16+
"go.mongodb.org/mongo-driver/event"
17+
"go.mongodb.org/mongo-driver/internal/testutil"
18+
"go.mongodb.org/mongo-driver/internal/testutil/assert"
19+
"go.mongodb.org/mongo-driver/mongo"
20+
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
21+
"go.mongodb.org/mongo-driver/mongo/options"
22+
)
23+
24+
// CSOT prose tests that require the 'cse' Go build tag.
25+
func TestCSOTClientSideEncryptionProse(t *testing.T) {
26+
verifyClientSideEncryptionVarsSet(t)
27+
mt := mtest.New(t, mtest.NewOptions().MinServerVersion("4.2").CreateClient(false))
28+
defer mt.Close()
29+
30+
mt.RunOpts("1. maxTimeMS is not set for commands sent to mongocryptd",
31+
noClientOpts, func(mt *mtest.T) {
32+
kmsProviders := map[string]map[string]interface{}{
33+
"local": {
34+
"key": localMasterKey,
35+
},
36+
}
37+
mongocryptdSpawnArgs := map[string]interface{}{
38+
// Pass a custom pidfilepath to ensure a new mongocryptd process is spawned.
39+
"mongocryptdSpawnArgs": []string{"--port=23000", "--pidfilepath=TestCSOTClientSideEncryptionProse_1.pid"},
40+
"mongocryptdUri": "mongodb://localhost:23000",
41+
// Do not use the shared library to ensure mongocryptd is spawned.
42+
"__cryptSharedLibDisabledForTestOnly": true,
43+
}
44+
45+
// Setup encrypted client to cause spawning of mongocryptd on port 23000.
46+
aeo := options.AutoEncryption().SetKmsProviders(kmsProviders).
47+
SetExtraOptions(mongocryptdSpawnArgs)
48+
cliOpts := options.Client().ApplyURI(mtest.ClusterURI()).SetAutoEncryptionOptions(aeo)
49+
testutil.AddTestServerAPIVersion(cliOpts)
50+
encClient, err := mongo.Connect(context.Background(), cliOpts)
51+
assert.Nil(mt, err, "Connect error: %v", err)
52+
defer func() {
53+
err = encClient.Disconnect(context.Background())
54+
assert.Nil(mt, err, "encrypted client Disconnect error: %v", err)
55+
}()
56+
57+
// Use a new Client to connect to 23000 where mongocryptd should be running. Use a custom
58+
// command monitor to examine the eventual 'ping'.
59+
var started *event.CommandStartedEvent
60+
mcryptMonitor := &event.CommandMonitor{
61+
Started: func(_ context.Context, evt *event.CommandStartedEvent) {
62+
started = evt
63+
},
64+
}
65+
mcryptOpts := options.Client().SetMonitor(mcryptMonitor).
66+
ApplyURI("mongodb://localhost:23000/?timeoutMS=1000")
67+
testutil.AddTestServerAPIVersion(mcryptOpts)
68+
mcryptClient, err := mongo.Connect(context.Background(), mcryptOpts)
69+
assert.Nil(mt, err, "mongocryptd Connect error: %v", err)
70+
defer func() {
71+
err = mcryptClient.Disconnect(context.Background())
72+
assert.Nil(mt, err, "mongocryptd Disconnect error: %v", err)
73+
}()
74+
75+
// Run Ping and assert that sent command does not contain 'maxTimeMS'. The 'ping' command
76+
// does not exist on mongocryptd, so ignore the CommandNotFound error.
77+
_ = mcryptClient.Ping(context.Background(), nil)
78+
assert.NotNil(mt, started, "expected a CommandStartedEvent, got nil")
79+
assert.Equal(mt, started.CommandName, "ping", "expected 'ping', got %q", started.CommandName)
80+
commandElems, err := started.Command.Elements()
81+
assert.Nil(mt, err, "Elements error: %v", err)
82+
for _, elem := range commandElems {
83+
assert.NotEqual(mt, elem.Key(), "maxTimeMS",
84+
"expected no 'maxTimeMS' field in ping to mongocryptd")
85+
}
86+
})
87+
}

x/mongo/driver/operation.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,12 @@ func (op Operation) Execute(ctx context.Context) error {
491491
return err
492492
}
493493

494+
// Set maxTimeMS to 0 if connected to mongocryptd to avoid appending the field. The final
495+
// encrypted command may contain multiple maxTimeMS fields otherwise.
496+
if conn.Description().IsCryptd {
497+
maxTimeMS = 0
498+
}
499+
494500
desc := description.SelectedServer{Server: conn.Description(), Kind: op.Deployment.Kind()}
495501
if desc.WireVersion == nil || desc.WireVersion.Max < 4 {
496502
switch op.Legacy {

0 commit comments

Comments
 (0)