@@ -18,10 +18,9 @@ import {
1818 StateMachine
1919} from '../../mongodb' ;
2020import { ClientSideEncryptionFilter } from '../../tools/runner/filters/client_encryption_filter' ;
21- import { getEncryptExtraOptions } from '../../tools/utils' ;
2221
2322const { EJSON } = BSON ;
24- const cryptShared = ( status : 'enabled' | 'disabled' ) => ( ) => {
23+ export const cryptShared = ( status : 'enabled' | 'disabled' ) => ( ) => {
2524 const isCryptSharedLoaded = ClientSideEncryptionFilter . cryptShared != null ;
2625
2726 if ( status === 'enabled' ) {
@@ -51,7 +50,7 @@ const MOCK_MONGOCRYPTD_RESPONSE = readExtendedJsonToBuffer(dataPath(`mongocryptd
5150const MOCK_KEYDOCUMENT_RESPONSE = readExtendedJsonToBuffer ( dataPath ( `key-document.json` ) ) ;
5251const MOCK_KMS_DECRYPT_REPLY = readHttpResponse ( dataPath ( `kms-decrypt-reply.txt` ) ) ;
5352
54- describe . only ( 'crypt_shared library ' , function ( ) {
53+ describe . only ( 'mongocryptd auto spawn ' , function ( ) {
5554 let client : MongoClient ;
5655 let autoEncrypter : AutoEncrypter | undefined ;
5756
@@ -92,227 +91,151 @@ describe.only('crypt_shared library', function () {
9291 sandbox . restore ( ) ;
9392 } ) ;
9493
95- describe ( 'autoSpawn' , function ( ) {
96- it (
97- 'should autoSpawn a mongocryptd on init by default' ,
98- { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
99-
100- async function ( ) {
101- autoEncrypter = new AutoEncrypter ( client , {
102- keyVaultNamespace : 'admin.datakeys' ,
103- kmsProviders : {
104- aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
105- local : { key : Buffer . alloc ( 96 ) }
106- }
107- } ) ;
108-
109- expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
110-
111- const localMcdm = autoEncrypter . _mongocryptdManager ;
112- sandbox . spy ( localMcdm , 'spawn' ) ;
113-
114- await autoEncrypter . init ( ) ;
115- expect ( localMcdm . spawn ) . to . have . been . calledOnce ;
116- }
117- ) ;
118-
119- it (
120- 'should not attempt to kick off mongocryptd on a normal error' ,
121- { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
122- async function ( ) {
123- let called = false ;
124- StateMachine . prototype . markCommand . callsFake ( async ( _client , _ns , _filter ) => {
125- if ( ! called ) {
126- called = true ;
127- throw new Error ( 'msg' ) ;
128- }
129-
130- return MOCK_MONGOCRYPTD_RESPONSE ;
131- } ) ;
132-
133- autoEncrypter = new AutoEncrypter ( client , {
134- keyVaultNamespace : 'admin.datakeys' ,
135- kmsProviders : {
136- aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
137- local : { key : Buffer . alloc ( 96 ) }
138- }
139- } ) ;
140- expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
141-
142- const localMcdm = autoEncrypter . _mongocryptdManager ;
143- await autoEncrypter . init ( ) ;
144-
145- sandbox . spy ( localMcdm , 'spawn' ) ;
146-
147- const err = await autoEncrypter . encrypt ( 'test.test' , TEST_COMMAND ) . catch ( e => e ) ;
148- expect ( localMcdm . spawn ) . to . not . have . been . called ;
149- expect ( err ) . to . be . an . instanceOf ( Error ) ;
150- }
151- ) ;
152-
153- it (
154- 'should restore the mongocryptd and retry once if a MongoNetworkTimeoutError is experienced' ,
155- { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
156- async function ( ) {
157- let called = false ;
158- StateMachine . prototype . markCommand . callsFake ( async ( _client , _ns , _filter ) => {
159- if ( ! called ) {
160- called = true ;
161- throw new MongoNetworkTimeoutError ( 'msg' ) ;
162- }
163-
164- return MOCK_MONGOCRYPTD_RESPONSE ;
165- } ) ;
166-
167- autoEncrypter = new AutoEncrypter ( client , {
168- keyVaultNamespace : 'admin.datakeys' ,
169- kmsProviders : {
170- aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
171- local : { key : Buffer . alloc ( 96 ) }
172- }
173- } ) ;
174- expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
175-
176- const localMcdm = autoEncrypter . _mongocryptdManager ;
177- await autoEncrypter . init ( ) ;
178-
179- sandbox . spy ( localMcdm , 'spawn' ) ;
180-
181- await autoEncrypter . encrypt ( 'test.test' , TEST_COMMAND ) ;
182- expect ( localMcdm . spawn ) . to . have . been . calledOnce ;
183- }
184- ) ;
185-
186- it (
187- 'should propagate error if MongoNetworkTimeoutError is experienced twice in a row' ,
188- { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
189- async function ( ) {
190- let counter = 2 ;
191- StateMachine . prototype . markCommand . callsFake ( async ( _client , _ns , _filter ) => {
192- if ( counter ) {
193- counter -= 1 ;
194- throw new MongoNetworkTimeoutError ( 'msg' ) ;
195- }
196-
197- return MOCK_MONGOCRYPTD_RESPONSE ;
198- } ) ;
199-
200- autoEncrypter = new AutoEncrypter ( client , {
201- keyVaultNamespace : 'admin.datakeys' ,
202- kmsProviders : {
203- aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
204- local : { key : Buffer . alloc ( 96 ) }
205- }
206- } ) ;
207- expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
208-
209- const localMcdm = autoEncrypter . _mongocryptdManager ;
210- await autoEncrypter . init ( ) ;
211-
212- sandbox . spy ( localMcdm , 'spawn' ) ;
213-
214- const err = await autoEncrypter . encrypt ( 'test.test' , TEST_COMMAND ) . catch ( e => e ) ;
215- expect ( localMcdm . spawn ) . to . have . been . calledOnce ;
216- expect ( err ) . to . be . an . instanceof ( MongoNetworkTimeoutError ) ;
217- }
218- ) ;
219-
220- it (
221- 'should return a useful message if mongocryptd fails to autospawn' ,
222- { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
223- async function ( ) {
224- autoEncrypter = new AutoEncrypter ( client , {
225- keyVaultNamespace : 'admin.datakeys' ,
226- kmsProviders : {
227- aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
228- local : { key : Buffer . alloc ( 96 ) }
229- } ,
230- extraOptions : {
231- mongocryptdURI : 'mongodb://something.invalid:27020/'
232- }
233- } ) ;
234- expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
235-
236- sandbox . stub ( MongocryptdManager . prototype , 'spawn' ) . resolves ( ) ;
237-
238- const err = await autoEncrypter . init ( ) . catch ( e => e ) ;
239- expect ( err ) . to . exist ;
240- expect ( err ) . to . be . instanceOf ( MongoError ) ;
241- }
242- ) ;
243- } ) ;
94+ it (
95+ 'should autoSpawn a mongocryptd on init by default' ,
96+ { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
24497
245- describe ( 'crypt shared library' , ( ) => {
246- it ( 'should fail if no library can be found in the search path and cryptSharedLibRequired is set' , async function ( ) {
247- const env = {
248- MONGODB_URI : this . configuration . url ( ) ,
249- EXTRA_OPTIONS : JSON . stringify ( {
250- cryptSharedLibSearchPaths : [ '/nonexistent' ] ,
251- cryptSharedLibRequired : true
252- } )
253- } ;
254- const file = `${ __dirname } /../../tools/fixtures/shared_library_test.js` ;
255- const { stderr } = spawnSync ( process . execPath , [ file ] , {
256- env,
257- encoding : 'utf-8'
98+ async function ( ) {
99+ autoEncrypter = new AutoEncrypter ( client , {
100+ keyVaultNamespace : 'admin.datakeys' ,
101+ kmsProviders : {
102+ aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
103+ local : { key : Buffer . alloc ( 96 ) }
104+ }
258105 } ) ;
259106
260- expect ( stderr ) . to . include ( '`cryptSharedLibRequired` set but no crypt_shared library loaded' ) ;
261- } ) ;
107+ expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
108+
109+ const localMcdm = autoEncrypter . _mongocryptdManager ;
110+ sandbox . spy ( localMcdm , 'spawn' ) ;
111+
112+ await autoEncrypter . init ( ) ;
113+ expect ( localMcdm . spawn ) . to . have . been . calledOnce ;
114+ }
115+ ) ;
116+
117+ it (
118+ 'should not attempt to kick off mongocryptd on a normal error' ,
119+ { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
120+ async function ( ) {
121+ let called = false ;
122+ StateMachine . prototype . markCommand . callsFake ( async ( _client , _ns , _filter ) => {
123+ if ( ! called ) {
124+ called = true ;
125+ throw new Error ( 'msg' ) ;
126+ }
127+
128+ return MOCK_MONGOCRYPTD_RESPONSE ;
129+ } ) ;
262130
263- it (
264- 'should load a shared library by specifying its path ',
265- {
266- requires : {
267- predicate : cryptShared ( 'enabled' )
131+ autoEncrypter = new AutoEncrypter ( client , {
132+ keyVaultNamespace : 'admin.datakeys ',
133+ kmsProviders : {
134+ aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
135+ local : { key : Buffer . alloc ( 96 ) }
268136 }
269- } ,
270- async function ( ) {
271- const env = {
272- MONGODB_URI : this . configuration . url ( ) ,
273- EXTRA_OPTIONS : JSON . stringify ( {
274- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
275- cryptSharedLibPath : getEncryptExtraOptions ( ) . cryptSharedLibPath !
276- } )
277- } ;
278- const file = `${ __dirname } /../../tools/fixtures/shared_library_test.js` ;
279- const { stdout } = spawnSync ( process . execPath , [ file ] , { env, encoding : 'utf-8' } ) ;
280-
281- const response = EJSON . parse ( stdout , { useBigInt64 : true } ) ;
282-
283- expect ( response ) . not . to . be . null ;
284-
285- expect ( response ) . to . have . property ( 'version' ) . that . is . a ( 'bigint' ) ;
286- expect ( response ) . to . have . property ( 'versionStr' ) . that . is . a ( 'string' ) ;
287- }
288- ) ;
289-
290- it (
291- 'should load a shared library by specifying a search path' ,
292- {
293- requires : {
294- predicate : cryptShared ( 'enabled' )
137+ } ) ;
138+ expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
139+
140+ const localMcdm = autoEncrypter . _mongocryptdManager ;
141+ await autoEncrypter . init ( ) ;
142+
143+ sandbox . spy ( localMcdm , 'spawn' ) ;
144+
145+ const err = await autoEncrypter . encrypt ( 'test.test' , TEST_COMMAND ) . catch ( e => e ) ;
146+ expect ( localMcdm . spawn ) . to . not . have . been . called ;
147+ expect ( err ) . to . be . an . instanceOf ( Error ) ;
148+ }
149+ ) ;
150+
151+ it (
152+ 'should restore the mongocryptd and retry once if a MongoNetworkTimeoutError is experienced' ,
153+ { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
154+ async function ( ) {
155+ let called = false ;
156+ StateMachine . prototype . markCommand . callsFake ( async ( _client , _ns , _filter ) => {
157+ if ( ! called ) {
158+ called = true ;
159+ throw new MongoNetworkTimeoutError ( 'msg' ) ;
295160 }
296- } ,
297- async function ( ) {
298- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
299- const cryptDir = dirname ( getEncryptExtraOptions ( ) . cryptSharedLibPath ! ) ;
300- const env = {
301- MONGODB_URI : this . configuration . url ( ) ,
302- EXTRA_OPTIONS : JSON . stringify ( {
303- cryptSharedLibSearchPaths : [ cryptDir ]
304- } )
305- } ;
306- const file = `${ __dirname } /../../tools/fixtures/shared_library_test.js` ;
307- const { stdout } = spawnSync ( process . execPath , [ file ] , { env, encoding : 'utf-8' } ) ;
308-
309- const response = EJSON . parse ( stdout , { useBigInt64 : true } ) ;
310-
311- expect ( response ) . not . to . be . null ;
312-
313- expect ( response ) . to . have . property ( 'version' ) . that . is . a ( 'bigint' ) ;
314- expect ( response ) . to . have . property ( 'versionStr' ) . that . is . a ( 'string' ) ;
315- }
316- ) ;
317- } ) ;
161+
162+ return MOCK_MONGOCRYPTD_RESPONSE ;
163+ } ) ;
164+
165+ autoEncrypter = new AutoEncrypter ( client , {
166+ keyVaultNamespace : 'admin.datakeys' ,
167+ kmsProviders : {
168+ aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
169+ local : { key : Buffer . alloc ( 96 ) }
170+ }
171+ } ) ;
172+ expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
173+
174+ const localMcdm = autoEncrypter . _mongocryptdManager ;
175+ await autoEncrypter . init ( ) ;
176+
177+ sandbox . spy ( localMcdm , 'spawn' ) ;
178+
179+ await autoEncrypter . encrypt ( 'test.test' , TEST_COMMAND ) ;
180+ expect ( localMcdm . spawn ) . to . have . been . calledOnce ;
181+ }
182+ ) ;
183+
184+ it (
185+ 'should propagate error if MongoNetworkTimeoutError is experienced twice in a row' ,
186+ { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
187+ async function ( ) {
188+ let counter = 2 ;
189+ StateMachine . prototype . markCommand . callsFake ( async ( _client , _ns , _filter ) => {
190+ if ( counter ) {
191+ counter -= 1 ;
192+ throw new MongoNetworkTimeoutError ( 'msg' ) ;
193+ }
194+
195+ return MOCK_MONGOCRYPTD_RESPONSE ;
196+ } ) ;
197+
198+ autoEncrypter = new AutoEncrypter ( client , {
199+ keyVaultNamespace : 'admin.datakeys' ,
200+ kmsProviders : {
201+ aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
202+ local : { key : Buffer . alloc ( 96 ) }
203+ }
204+ } ) ;
205+ expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
206+
207+ const localMcdm = autoEncrypter . _mongocryptdManager ;
208+ await autoEncrypter . init ( ) ;
209+
210+ sandbox . spy ( localMcdm , 'spawn' ) ;
211+
212+ const err = await autoEncrypter . encrypt ( 'test.test' , TEST_COMMAND ) . catch ( e => e ) ;
213+ expect ( localMcdm . spawn ) . to . have . been . calledOnce ;
214+ expect ( err ) . to . be . an . instanceof ( MongoNetworkTimeoutError ) ;
215+ }
216+ ) ;
217+
218+ it (
219+ 'should return a useful message if mongocryptd fails to autospawn' ,
220+ { requires : { clientSideEncryption : true , predicate : cryptShared ( 'disabled' ) } } ,
221+ async function ( ) {
222+ autoEncrypter = new AutoEncrypter ( client , {
223+ keyVaultNamespace : 'admin.datakeys' ,
224+ kmsProviders : {
225+ aws : { accessKeyId : 'example' , secretAccessKey : 'example' } ,
226+ local : { key : Buffer . alloc ( 96 ) }
227+ } ,
228+ extraOptions : {
229+ mongocryptdURI : 'mongodb://something.invalid:27020/'
230+ }
231+ } ) ;
232+ expect ( autoEncrypter ) . to . have . property ( 'cryptSharedLibVersionInfo' , null ) ;
233+
234+ sandbox . stub ( MongocryptdManager . prototype , 'spawn' ) . resolves ( ) ;
235+
236+ const err = await autoEncrypter . init ( ) . catch ( e => e ) ;
237+ expect ( err ) . to . exist ;
238+ expect ( err ) . to . be . instanceOf ( MongoError ) ;
239+ }
240+ ) ;
318241} ) ;
0 commit comments