Skip to content

Commit

Permalink
GODRIVER-2458 Do not append maxTimeMS when connected to mongocryptd. (
Browse files Browse the repository at this point in the history
mongodb#1074)

Co-authored-by: Kevin Albertson <kevin.albertson@10gen.com>
  • Loading branch information
2 people authored and Julien-Beezeelinx committed Oct 20, 2022
1 parent e237c4c commit a2a9b51
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
7 changes: 7 additions & 0 deletions mongo/description/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type Server struct {
HeartbeatInterval time.Duration
HelloOK bool
Hosts []string
IsCryptd bool
LastError error
LastUpdateTime time.Time
LastWriteTime time.Time
Expand Down Expand Up @@ -101,6 +102,12 @@ func NewServer(addr address.Address, response bson.Raw) Server {
desc.LastError = fmt.Errorf("expected 'electionId' to be a objectID but it's a BSON %s", element.Value().Type)
return desc
}
case "iscryptd":
desc.IsCryptd, ok = element.Value().BooleanOK()
if !ok {
desc.LastError = fmt.Errorf("expected 'iscryptd' to be a boolean but it's a BSON %s", element.Value().Type)
return desc
}
case "helloOk":
desc.HelloOK, ok = element.Value().BooleanOK()
if !ok {
Expand Down
87 changes: 87 additions & 0 deletions mongo/integration/csot_cse_prose_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (C) MongoDB, Inc. 2022-present.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

//go:build cse
// +build cse

package integration

import (
"context"
"testing"

"go.mongodb.org/mongo-driver/event"
"go.mongodb.org/mongo-driver/internal/testutil"
"go.mongodb.org/mongo-driver/internal/testutil/assert"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
"go.mongodb.org/mongo-driver/mongo/options"
)

// CSOT prose tests that require the 'cse' Go build tag.
func TestCSOTClientSideEncryptionProse(t *testing.T) {
verifyClientSideEncryptionVarsSet(t)
mt := mtest.New(t, mtest.NewOptions().MinServerVersion("4.2").CreateClient(false))
defer mt.Close()

mt.RunOpts("1. maxTimeMS is not set for commands sent to mongocryptd",
noClientOpts, func(mt *mtest.T) {
kmsProviders := map[string]map[string]interface{}{
"local": {
"key": localMasterKey,
},
}
mongocryptdSpawnArgs := map[string]interface{}{
// Pass a custom pidfilepath to ensure a new mongocryptd process is spawned.
"mongocryptdSpawnArgs": []string{"--port=23000", "--pidfilepath=TestCSOTClientSideEncryptionProse_1.pid"},
"mongocryptdUri": "mongodb://localhost:23000",
// Do not use the shared library to ensure mongocryptd is spawned.
"__cryptSharedLibDisabledForTestOnly": true,
}

// Setup encrypted client to cause spawning of mongocryptd on port 23000.
aeo := options.AutoEncryption().SetKmsProviders(kmsProviders).
SetExtraOptions(mongocryptdSpawnArgs)
cliOpts := options.Client().ApplyURI(mtest.ClusterURI()).SetAutoEncryptionOptions(aeo)
testutil.AddTestServerAPIVersion(cliOpts)
encClient, err := mongo.Connect(context.Background(), cliOpts)
assert.Nil(mt, err, "Connect error: %v", err)
defer func() {
err = encClient.Disconnect(context.Background())
assert.Nil(mt, err, "encrypted client Disconnect error: %v", err)
}()

// Use a new Client to connect to 23000 where mongocryptd should be running. Use a custom
// command monitor to examine the eventual 'ping'.
var started *event.CommandStartedEvent
mcryptMonitor := &event.CommandMonitor{
Started: func(_ context.Context, evt *event.CommandStartedEvent) {
started = evt
},
}
mcryptOpts := options.Client().SetMonitor(mcryptMonitor).
ApplyURI("mongodb://localhost:23000/?timeoutMS=1000")
testutil.AddTestServerAPIVersion(mcryptOpts)
mcryptClient, err := mongo.Connect(context.Background(), mcryptOpts)
assert.Nil(mt, err, "mongocryptd Connect error: %v", err)
defer func() {
err = mcryptClient.Disconnect(context.Background())
assert.Nil(mt, err, "mongocryptd Disconnect error: %v", err)
}()

// Run Ping and assert that sent command does not contain 'maxTimeMS'. The 'ping' command
// does not exist on mongocryptd, so ignore the CommandNotFound error.
_ = mcryptClient.Ping(context.Background(), nil)
assert.NotNil(mt, started, "expected a CommandStartedEvent, got nil")
assert.Equal(mt, started.CommandName, "ping", "expected 'ping', got %q", started.CommandName)
commandElems, err := started.Command.Elements()
assert.Nil(mt, err, "Elements error: %v", err)
for _, elem := range commandElems {
assert.NotEqual(mt, elem.Key(), "maxTimeMS",
"expected no 'maxTimeMS' field in ping to mongocryptd")
}
})
}
6 changes: 6 additions & 0 deletions x/mongo/driver/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,12 @@ func (op Operation) Execute(ctx context.Context) error {
return err
}

// Set maxTimeMS to 0 if connected to mongocryptd to avoid appending the field. The final
// encrypted command may contain multiple maxTimeMS fields otherwise.
if conn.Description().IsCryptd {
maxTimeMS = 0
}

desc := description.SelectedServer{Server: conn.Description(), Kind: op.Deployment.Kind()}
if desc.WireVersion == nil || desc.WireVersion.Max < 4 {
switch op.Legacy {
Expand Down

0 comments on commit a2a9b51

Please sign in to comment.