@@ -26,6 +26,8 @@ import (
26
26
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
27
27
"go.mongodb.org/mongo-driver/x/mongo/driver"
28
28
"go.mongodb.org/mongo-driver/x/mongo/driver/auth"
29
+ "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt"
30
+ mcopts "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options"
29
31
"go.mongodb.org/mongo-driver/x/mongo/driver/ocsp"
30
32
"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
31
33
"go.mongodb.org/mongo-driver/x/mongo/driver/session"
@@ -71,7 +73,7 @@ type Client struct {
71
73
// client-side encryption fields
72
74
keyVaultClientFLE * Client
73
75
keyVaultCollFLE * Collection
74
- mongocryptdFLE * mcryptClient
76
+ mongocryptdFLE * mongocryptdClient
75
77
cryptFLE driver.Crypt
76
78
metadataClientFLE * Client
77
79
internalClientFLE * Client
@@ -720,10 +722,23 @@ func (c *Client) configureAutoEncryption(clientOpts *options.ClientOptions) erro
720
722
if err := c .configureMetadataClientFLE (clientOpts ); err != nil {
721
723
return err
722
724
}
723
- if err := c .configureMongocryptdClientFLE (clientOpts .AutoEncryptionOptions ); err != nil {
725
+
726
+ mc , err := c .newMongoCrypt (clientOpts .AutoEncryptionOptions )
727
+ if err != nil {
724
728
return err
725
729
}
726
- return c .configureCryptFLE (clientOpts .AutoEncryptionOptions )
730
+
731
+ // If the crypt_shared library was loaded successfully, signal to the mongocryptd client creator
732
+ // that it can bypass spawning mongocryptd.
733
+ cryptSharedLibAvailable := mc .CryptSharedLibVersionString () != ""
734
+ mongocryptdFLE , err := newMongocryptdClient (cryptSharedLibAvailable , clientOpts .AutoEncryptionOptions )
735
+ if err != nil {
736
+ return err
737
+ }
738
+ c .mongocryptdFLE = mongocryptdFLE
739
+
740
+ c .configureCryptFLE (mc , clientOpts .AutoEncryptionOptions )
741
+ return nil
727
742
}
728
743
729
744
func (c * Client ) getOrCreateInternalClient (clientOpts * options.ClientOptions ) (* Client , error ) {
@@ -778,19 +793,13 @@ func (c *Client) configureMetadataClientFLE(clientOpts *options.ClientOptions) e
778
793
return err
779
794
}
780
795
781
- func (c * Client ) configureMongocryptdClientFLE (opts * options.AutoEncryptionOptions ) error {
782
- var err error
783
- c .mongocryptdFLE , err = newMcryptClient (opts )
784
- return err
785
- }
786
-
787
- func (c * Client ) configureCryptFLE (opts * options.AutoEncryptionOptions ) error {
796
+ func (c * Client ) newMongoCrypt (opts * options.AutoEncryptionOptions ) (* mongocrypt.MongoCrypt , error ) {
788
797
// convert schemas in SchemaMap to bsoncore documents
789
798
cryptSchemaMap := make (map [string ]bsoncore.Document )
790
799
for k , v := range opts .SchemaMap {
791
800
schema , err := transformBsoncoreDocument (c .registry , v , true , "schemaMap" )
792
801
if err != nil {
793
- return err
802
+ return nil , err
794
803
}
795
804
cryptSchemaMap [k ] = schema
796
805
}
@@ -800,21 +809,74 @@ func (c *Client) configureCryptFLE(opts *options.AutoEncryptionOptions) error {
800
809
for k , v := range opts .EncryptedFieldsMap {
801
810
encryptedFields , err := transformBsoncoreDocument (c .registry , v , true , "encryptedFieldsMap" )
802
811
if err != nil {
803
- return err
812
+ return nil , err
804
813
}
805
814
cryptEncryptedFieldsMap [k ] = encryptedFields
806
815
}
807
816
808
817
kmsProviders , err := transformBsoncoreDocument (c .registry , opts .KmsProviders , true , "kmsProviders" )
809
818
if err != nil {
810
- return fmt .Errorf ("error creating KMS providers document: %v" , err )
819
+ return nil , fmt .Errorf ("error creating KMS providers document: %v" , err )
820
+ }
821
+
822
+ // Set the crypt_shared library override path from the "cryptSharedLibPath" extra option if one
823
+ // was set.
824
+ cryptSharedLibPath := ""
825
+ if val , ok := opts .ExtraOptions ["cryptSharedLibPath" ]; ok {
826
+ str , ok := val .(string )
827
+ if ! ok {
828
+ return nil , fmt .Errorf (
829
+ `expected AutoEncryption extra option "cryptSharedLibPath" to be a string, but is a %T` , val )
830
+ }
831
+ cryptSharedLibPath = str
832
+ }
833
+
834
+ // Explicitly disable loading the crypt_shared library if requested. Note that this is ONLY
835
+ // intended for use from tests; there is no supported public API for explicitly disabling
836
+ // loading the crypt_shared library.
837
+ cryptSharedLibDisabled := false
838
+ if v , ok := opts .ExtraOptions ["__cryptSharedLibDisabledForTestOnly" ]; ok {
839
+ cryptSharedLibDisabled = v .(bool )
840
+ }
841
+
842
+ bypassAutoEncryption := opts .BypassAutoEncryption != nil && * opts .BypassAutoEncryption
843
+ bypassQueryAnalysis := opts .BypassQueryAnalysis != nil && * opts .BypassQueryAnalysis
844
+
845
+ mc , err := mongocrypt .NewMongoCrypt (mcopts .MongoCrypt ().
846
+ SetKmsProviders (kmsProviders ).
847
+ SetLocalSchemaMap (cryptSchemaMap ).
848
+ SetBypassQueryAnalysis (bypassQueryAnalysis ).
849
+ SetEncryptedFieldsMap (cryptEncryptedFieldsMap ).
850
+ SetCryptSharedLibDisabled (cryptSharedLibDisabled || bypassAutoEncryption ).
851
+ SetCryptSharedLibOverridePath (cryptSharedLibPath ))
852
+ if err != nil {
853
+ return nil , err
811
854
}
812
855
813
- // configure options
814
- var bypass bool
815
- if opts .BypassAutoEncryption != nil {
816
- bypass = * opts .BypassAutoEncryption
856
+ var cryptSharedLibRequired bool
857
+ if val , ok := opts .ExtraOptions ["cryptSharedLibRequired" ]; ok {
858
+ b , ok := val .(bool )
859
+ if ! ok {
860
+ return nil , fmt .Errorf (
861
+ `expected AutoEncryption extra option "cryptSharedLibRequired" to be a bool, but is a %T` , val )
862
+ }
863
+ cryptSharedLibRequired = b
817
864
}
865
+
866
+ // If the "cryptSharedLibRequired" extra option is set to true, check the MongoCrypt version
867
+ // string to confirm that the library was successfully loaded. If the version string is empty,
868
+ // return an error indicating that we couldn't load the crypt_shared library.
869
+ if cryptSharedLibRequired && mc .CryptSharedLibVersionString () == "" {
870
+ return nil , errors .New (
871
+ `AutoEncryption extra option "cryptSharedLibRequired" is true, but we failed to load the crypt_shared library` )
872
+ }
873
+
874
+ return mc , nil
875
+ }
876
+
877
+ //nolint:unused // the unused linter thinks that this function is unreachable because "c.newMongoCrypt" always panics without the "cse" build tag set.
878
+ func (c * Client ) configureCryptFLE (mc * mongocrypt.MongoCrypt , opts * options.AutoEncryptionOptions ) {
879
+ bypass := opts .BypassAutoEncryption != nil && * opts .BypassAutoEncryption
818
880
kr := keyRetriever {coll : c .keyVaultCollFLE }
819
881
var cir collInfoRetriever
820
882
// If bypass is true, c.metadataClientFLE is nil and the collInfoRetriever
@@ -824,20 +886,14 @@ func (c *Client) configureCryptFLE(opts *options.AutoEncryptionOptions) error {
824
886
cir = collInfoRetriever {client : c .metadataClientFLE }
825
887
}
826
888
827
- cryptOpts := & driver.CryptOptions {
889
+ c .cryptFLE = driver .NewCrypt (& driver.CryptOptions {
890
+ MongoCrypt : mc ,
828
891
CollInfoFn : cir .cryptCollInfo ,
829
892
KeyFn : kr .cryptKeys ,
830
893
MarkFn : c .mongocryptdFLE .markCommand ,
831
- KmsProviders : kmsProviders ,
832
894
TLSConfig : opts .TLSConfig ,
833
895
BypassAutoEncryption : bypass ,
834
- SchemaMap : cryptSchemaMap ,
835
- BypassQueryAnalysis : opts .BypassQueryAnalysis != nil && * opts .BypassQueryAnalysis ,
836
- EncryptedFieldsMap : cryptEncryptedFieldsMap ,
837
- }
838
-
839
- c .cryptFLE , err = driver .NewCrypt (cryptOpts )
840
- return err
896
+ })
841
897
}
842
898
843
899
// validSession returns an error if the session doesn't belong to the client
0 commit comments