@@ -34,20 +34,365 @@ describe_only_db('mongo')('GridFSBucket and GridStore interop', () => {
34
34
expect ( gfsResult . toString ( 'utf8' ) ) . toBe ( originalString ) ;
35
35
} ) ;
36
36
37
- it ( 'an encypted file created in GridStore should be available in GridFS' , async ( ) => {
38
- const gsAdapter = new GridStoreAdapter ( databaseURI ) ;
39
- const gfsAdapter = new GridFSBucketAdapter (
37
+ it ( 'should save an encrypted file that can only be decrypted by a GridFS adapter with the encryptionKey ' , async ( ) => {
38
+ const unencryptedAdapter = new GridFSBucketAdapter ( databaseURI ) ;
39
+ const encryptedAdapter = new GridFSBucketAdapter (
40
40
databaseURI ,
41
41
{ } ,
42
42
'89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
43
43
) ;
44
- await expectMissingFile ( gfsAdapter , 'myFileName' ) ;
44
+ await expectMissingFile ( encryptedAdapter , 'myFileName' ) ;
45
45
const originalString = 'abcdefghi' ;
46
- await gfsAdapter . createFile ( 'myFileName' , originalString ) ;
47
- const gsResult = await gsAdapter . getFileData ( 'myFileName' ) ;
48
- expect ( gsResult . toString ( 'utf8' ) ) . not . toBe ( originalString ) ;
49
- const gfsResult = await gfsAdapter . getFileData ( 'myFileName' ) ;
50
- expect ( gfsResult . toString ( 'utf8' ) ) . toBe ( originalString ) ;
46
+ await encryptedAdapter . createFile ( 'myFileName' , originalString ) ;
47
+ const unencryptedResult = await unencryptedAdapter . getFileData (
48
+ 'myFileName'
49
+ ) ;
50
+ expect ( unencryptedResult . toString ( 'utf8' ) ) . not . toBe ( originalString ) ;
51
+ const encryptedResult = await encryptedAdapter . getFileData ( 'myFileName' ) ;
52
+ expect ( encryptedResult . toString ( 'utf8' ) ) . toBe ( originalString ) ;
53
+ } ) ;
54
+
55
+ it ( 'should rotate key of all unencrypted GridFS files to encrypted files' , async ( ) => {
56
+ const unencryptedAdapter = new GridFSBucketAdapter ( databaseURI ) ;
57
+ const encryptedAdapter = new GridFSBucketAdapter (
58
+ databaseURI ,
59
+ { } ,
60
+ '89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
61
+ ) ;
62
+ const fileName1 = 'file1.txt' ;
63
+ const data1 = 'hello world' ;
64
+ const fileName2 = 'file2.txt' ;
65
+ const data2 = 'hello new world' ;
66
+ //Store unecrypted files
67
+ await unencryptedAdapter . createFile ( fileName1 , data1 ) ;
68
+ const unencryptedResult1 = await unencryptedAdapter . getFileData ( fileName1 ) ;
69
+ expect ( unencryptedResult1 . toString ( 'utf8' ) ) . toBe ( data1 ) ;
70
+ await unencryptedAdapter . createFile ( fileName2 , data2 ) ;
71
+ const unencryptedResult2 = await unencryptedAdapter . getFileData ( fileName2 ) ;
72
+ expect ( unencryptedResult2 . toString ( 'utf8' ) ) . toBe ( data2 ) ;
73
+ //Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
74
+ const {
75
+ rotated,
76
+ notRotated,
77
+ } = await encryptedAdapter . rotateEncryptionKey ( ) ;
78
+ expect ( rotated . length ) . toEqual ( 2 ) ;
79
+ expect (
80
+ rotated . filter ( function ( value ) {
81
+ return value === fileName1 ;
82
+ } ) . length
83
+ ) . toEqual ( 1 ) ;
84
+ expect (
85
+ rotated . filter ( function ( value ) {
86
+ return value === fileName2 ;
87
+ } ) . length
88
+ ) . toEqual ( 1 ) ;
89
+ expect ( notRotated . length ) . toEqual ( 0 ) ;
90
+ let result = await encryptedAdapter . getFileData ( fileName1 ) ;
91
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
92
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data1 ) ;
93
+ const encryptedData1 = await unencryptedAdapter . getFileData ( fileName1 ) ;
94
+ expect ( encryptedData1 . toString ( 'utf-8' ) ) . not . toEqual ( unencryptedResult1 ) ;
95
+ result = await encryptedAdapter . getFileData ( fileName2 ) ;
96
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
97
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data2 ) ;
98
+ const encryptedData2 = await unencryptedAdapter . getFileData ( fileName2 ) ;
99
+ expect ( encryptedData2 . toString ( 'utf-8' ) ) . not . toEqual ( unencryptedResult2 ) ;
100
+ } ) ;
101
+
102
+ it ( 'should rotate key of all old encrypted GridFS files to encrypted files' , async ( ) => {
103
+ const oldEncryptionKey = 'oldKeyThatILoved' ;
104
+ const oldEncryptedAdapter = new GridFSBucketAdapter (
105
+ databaseURI ,
106
+ { } ,
107
+ oldEncryptionKey
108
+ ) ;
109
+ const encryptedAdapter = new GridFSBucketAdapter (
110
+ databaseURI ,
111
+ { } ,
112
+ 'newKeyThatILove'
113
+ ) ;
114
+ const fileName1 = 'file1.txt' ;
115
+ const data1 = 'hello world' ;
116
+ const fileName2 = 'file2.txt' ;
117
+ const data2 = 'hello new world' ;
118
+ //Store unecrypted files
119
+ await oldEncryptedAdapter . createFile ( fileName1 , data1 ) ;
120
+ const oldEncryptedResult1 = await oldEncryptedAdapter . getFileData (
121
+ fileName1
122
+ ) ;
123
+ expect ( oldEncryptedResult1 . toString ( 'utf8' ) ) . toBe ( data1 ) ;
124
+ await oldEncryptedAdapter . createFile ( fileName2 , data2 ) ;
125
+ const oldEncryptedResult2 = await oldEncryptedAdapter . getFileData (
126
+ fileName2
127
+ ) ;
128
+ expect ( oldEncryptedResult2 . toString ( 'utf8' ) ) . toBe ( data2 ) ;
129
+ //Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
130
+ const { rotated, notRotated } = await encryptedAdapter . rotateEncryptionKey ( {
131
+ oldKey : oldEncryptionKey ,
132
+ } ) ;
133
+ expect ( rotated . length ) . toEqual ( 2 ) ;
134
+ expect (
135
+ rotated . filter ( function ( value ) {
136
+ return value === fileName1 ;
137
+ } ) . length
138
+ ) . toEqual ( 1 ) ;
139
+ expect (
140
+ rotated . filter ( function ( value ) {
141
+ return value === fileName2 ;
142
+ } ) . length
143
+ ) . toEqual ( 1 ) ;
144
+ expect ( notRotated . length ) . toEqual ( 0 ) ;
145
+ let result = await encryptedAdapter . getFileData ( fileName1 ) ;
146
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
147
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data1 ) ;
148
+ let decryptionError1 ;
149
+ let encryptedData1 ;
150
+ try {
151
+ encryptedData1 = await oldEncryptedAdapter . getFileData ( fileName1 ) ;
152
+ } catch ( err ) {
153
+ decryptionError1 = err ;
154
+ }
155
+ expect ( decryptionError1 ) . toMatch ( 'Error' ) ;
156
+ expect ( encryptedData1 ) . toBeUndefined ( ) ;
157
+ result = await encryptedAdapter . getFileData ( fileName2 ) ;
158
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
159
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data2 ) ;
160
+ let decryptionError2 ;
161
+ let encryptedData2 ;
162
+ try {
163
+ encryptedData2 = await oldEncryptedAdapter . getFileData ( fileName2 ) ;
164
+ } catch ( err ) {
165
+ decryptionError2 = err ;
166
+ }
167
+ expect ( decryptionError2 ) . toMatch ( 'Error' ) ;
168
+ expect ( encryptedData2 ) . toBeUndefined ( ) ;
169
+ } ) ;
170
+
171
+ it ( 'should rotate key of all old encrypted GridFS files to unencrypted files' , async ( ) => {
172
+ const oldEncryptionKey = 'oldKeyThatILoved' ;
173
+ const oldEncryptedAdapter = new GridFSBucketAdapter (
174
+ databaseURI ,
175
+ { } ,
176
+ oldEncryptionKey
177
+ ) ;
178
+ const unEncryptedAdapter = new GridFSBucketAdapter ( databaseURI ) ;
179
+ const fileName1 = 'file1.txt' ;
180
+ const data1 = 'hello world' ;
181
+ const fileName2 = 'file2.txt' ;
182
+ const data2 = 'hello new world' ;
183
+ //Store unecrypted files
184
+ await oldEncryptedAdapter . createFile ( fileName1 , data1 ) ;
185
+ const oldEncryptedResult1 = await oldEncryptedAdapter . getFileData (
186
+ fileName1
187
+ ) ;
188
+ expect ( oldEncryptedResult1 . toString ( 'utf8' ) ) . toBe ( data1 ) ;
189
+ await oldEncryptedAdapter . createFile ( fileName2 , data2 ) ;
190
+ const oldEncryptedResult2 = await oldEncryptedAdapter . getFileData (
191
+ fileName2
192
+ ) ;
193
+ expect ( oldEncryptedResult2 . toString ( 'utf8' ) ) . toBe ( data2 ) ;
194
+ //Check if unEncrypted adapter can read data and make sure it's not the same as oldEncrypted adapter
195
+ const {
196
+ rotated,
197
+ notRotated,
198
+ } = await unEncryptedAdapter . rotateEncryptionKey ( {
199
+ oldKey : oldEncryptionKey ,
200
+ } ) ;
201
+ expect ( rotated . length ) . toEqual ( 2 ) ;
202
+ expect (
203
+ rotated . filter ( function ( value ) {
204
+ return value === fileName1 ;
205
+ } ) . length
206
+ ) . toEqual ( 1 ) ;
207
+ expect (
208
+ rotated . filter ( function ( value ) {
209
+ return value === fileName2 ;
210
+ } ) . length
211
+ ) . toEqual ( 1 ) ;
212
+ expect ( notRotated . length ) . toEqual ( 0 ) ;
213
+ let result = await unEncryptedAdapter . getFileData ( fileName1 ) ;
214
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
215
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data1 ) ;
216
+ let decryptionError1 ;
217
+ let encryptedData1 ;
218
+ try {
219
+ encryptedData1 = await oldEncryptedAdapter . getFileData ( fileName1 ) ;
220
+ } catch ( err ) {
221
+ decryptionError1 = err ;
222
+ }
223
+ expect ( decryptionError1 ) . toMatch ( 'Error' ) ;
224
+ expect ( encryptedData1 ) . toBeUndefined ( ) ;
225
+ result = await unEncryptedAdapter . getFileData ( fileName2 ) ;
226
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
227
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data2 ) ;
228
+ let decryptionError2 ;
229
+ let encryptedData2 ;
230
+ try {
231
+ encryptedData2 = await oldEncryptedAdapter . getFileData ( fileName2 ) ;
232
+ } catch ( err ) {
233
+ decryptionError2 = err ;
234
+ }
235
+ expect ( decryptionError2 ) . toMatch ( 'Error' ) ;
236
+ expect ( encryptedData2 ) . toBeUndefined ( ) ;
237
+ } ) ;
238
+
239
+ it ( 'should only encrypt specified fileNames' , async ( ) => {
240
+ const oldEncryptionKey = 'oldKeyThatILoved' ;
241
+ const oldEncryptedAdapter = new GridFSBucketAdapter (
242
+ databaseURI ,
243
+ { } ,
244
+ oldEncryptionKey
245
+ ) ;
246
+ const encryptedAdapter = new GridFSBucketAdapter (
247
+ databaseURI ,
248
+ { } ,
249
+ 'newKeyThatILove'
250
+ ) ;
251
+ const unEncryptedAdapter = new GridFSBucketAdapter ( databaseURI ) ;
252
+ const fileName1 = 'file1.txt' ;
253
+ const data1 = 'hello world' ;
254
+ const fileName2 = 'file2.txt' ;
255
+ const data2 = 'hello new world' ;
256
+ //Store unecrypted files
257
+ await oldEncryptedAdapter . createFile ( fileName1 , data1 ) ;
258
+ const oldEncryptedResult1 = await oldEncryptedAdapter . getFileData (
259
+ fileName1
260
+ ) ;
261
+ expect ( oldEncryptedResult1 . toString ( 'utf8' ) ) . toBe ( data1 ) ;
262
+ await oldEncryptedAdapter . createFile ( fileName2 , data2 ) ;
263
+ const oldEncryptedResult2 = await oldEncryptedAdapter . getFileData (
264
+ fileName2
265
+ ) ;
266
+ expect ( oldEncryptedResult2 . toString ( 'utf8' ) ) . toBe ( data2 ) ;
267
+ //Inject unecrypted file to see if causes an issue
268
+ const fileName3 = 'file3.txt' ;
269
+ const data3 = 'hello past world' ;
270
+ await unEncryptedAdapter . createFile ( fileName3 , data3 , 'text/utf8' ) ;
271
+ //Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
272
+ const { rotated, notRotated } = await encryptedAdapter . rotateEncryptionKey ( {
273
+ oldKey : oldEncryptionKey ,
274
+ fileNames : [ fileName1 , fileName2 ] ,
275
+ } ) ;
276
+ expect ( rotated . length ) . toEqual ( 2 ) ;
277
+ expect (
278
+ rotated . filter ( function ( value ) {
279
+ return value === fileName1 ;
280
+ } ) . length
281
+ ) . toEqual ( 1 ) ;
282
+ expect (
283
+ rotated . filter ( function ( value ) {
284
+ return value === fileName2 ;
285
+ } ) . length
286
+ ) . toEqual ( 1 ) ;
287
+ expect ( notRotated . length ) . toEqual ( 0 ) ;
288
+ expect (
289
+ rotated . filter ( function ( value ) {
290
+ return value === fileName3 ;
291
+ } ) . length
292
+ ) . toEqual ( 0 ) ;
293
+ let result = await encryptedAdapter . getFileData ( fileName1 ) ;
294
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
295
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data1 ) ;
296
+ let decryptionError1 ;
297
+ let encryptedData1 ;
298
+ try {
299
+ encryptedData1 = await oldEncryptedAdapter . getFileData ( fileName1 ) ;
300
+ } catch ( err ) {
301
+ decryptionError1 = err ;
302
+ }
303
+ expect ( decryptionError1 ) . toMatch ( 'Error' ) ;
304
+ expect ( encryptedData1 ) . toBeUndefined ( ) ;
305
+ result = await encryptedAdapter . getFileData ( fileName2 ) ;
306
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
307
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data2 ) ;
308
+ let decryptionError2 ;
309
+ let encryptedData2 ;
310
+ try {
311
+ encryptedData2 = await oldEncryptedAdapter . getFileData ( fileName2 ) ;
312
+ } catch ( err ) {
313
+ decryptionError2 = err ;
314
+ }
315
+ expect ( decryptionError2 ) . toMatch ( 'Error' ) ;
316
+ expect ( encryptedData2 ) . toBeUndefined ( ) ;
317
+ } ) ;
318
+
319
+ it ( "should return fileNames of those it can't encrypt with the new key" , async ( ) => {
320
+ const oldEncryptionKey = 'oldKeyThatILoved' ;
321
+ const oldEncryptedAdapter = new GridFSBucketAdapter (
322
+ databaseURI ,
323
+ { } ,
324
+ oldEncryptionKey
325
+ ) ;
326
+ const encryptedAdapter = new GridFSBucketAdapter (
327
+ databaseURI ,
328
+ { } ,
329
+ 'newKeyThatILove'
330
+ ) ;
331
+ const unEncryptedAdapter = new GridFSBucketAdapter ( databaseURI ) ;
332
+ const fileName1 = 'file1.txt' ;
333
+ const data1 = 'hello world' ;
334
+ const fileName2 = 'file2.txt' ;
335
+ const data2 = 'hello new world' ;
336
+ //Store unecrypted files
337
+ await oldEncryptedAdapter . createFile ( fileName1 , data1 ) ;
338
+ const oldEncryptedResult1 = await oldEncryptedAdapter . getFileData (
339
+ fileName1
340
+ ) ;
341
+ expect ( oldEncryptedResult1 . toString ( 'utf8' ) ) . toBe ( data1 ) ;
342
+ await oldEncryptedAdapter . createFile ( fileName2 , data2 ) ;
343
+ const oldEncryptedResult2 = await oldEncryptedAdapter . getFileData (
344
+ fileName2
345
+ ) ;
346
+ expect ( oldEncryptedResult2 . toString ( 'utf8' ) ) . toBe ( data2 ) ;
347
+ //Inject unecrypted file to see if causes an issue
348
+ const fileName3 = 'file3.txt' ;
349
+ const data3 = 'hello past world' ;
350
+ await unEncryptedAdapter . createFile ( fileName3 , data3 , 'text/utf8' ) ;
351
+ //Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
352
+ const { rotated, notRotated } = await encryptedAdapter . rotateEncryptionKey ( {
353
+ oldKey : oldEncryptionKey ,
354
+ } ) ;
355
+ expect ( rotated . length ) . toEqual ( 2 ) ;
356
+ expect (
357
+ rotated . filter ( function ( value ) {
358
+ return value === fileName1 ;
359
+ } ) . length
360
+ ) . toEqual ( 1 ) ;
361
+ expect (
362
+ rotated . filter ( function ( value ) {
363
+ return value === fileName2 ;
364
+ } ) . length
365
+ ) . toEqual ( 1 ) ;
366
+ expect ( notRotated . length ) . toEqual ( 1 ) ;
367
+ expect (
368
+ notRotated . filter ( function ( value ) {
369
+ return value === fileName3 ;
370
+ } ) . length
371
+ ) . toEqual ( 1 ) ;
372
+ let result = await encryptedAdapter . getFileData ( fileName1 ) ;
373
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
374
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data1 ) ;
375
+ let decryptionError1 ;
376
+ let encryptedData1 ;
377
+ try {
378
+ encryptedData1 = await oldEncryptedAdapter . getFileData ( fileName1 ) ;
379
+ } catch ( err ) {
380
+ decryptionError1 = err ;
381
+ }
382
+ expect ( decryptionError1 ) . toMatch ( 'Error' ) ;
383
+ expect ( encryptedData1 ) . toBeUndefined ( ) ;
384
+ result = await encryptedAdapter . getFileData ( fileName2 ) ;
385
+ expect ( result instanceof Buffer ) . toBe ( true ) ;
386
+ expect ( result . toString ( 'utf-8' ) ) . toEqual ( data2 ) ;
387
+ let decryptionError2 ;
388
+ let encryptedData2 ;
389
+ try {
390
+ encryptedData2 = await oldEncryptedAdapter . getFileData ( fileName2 ) ;
391
+ } catch ( err ) {
392
+ decryptionError2 = err ;
393
+ }
394
+ expect ( decryptionError2 ) . toMatch ( 'Error' ) ;
395
+ expect ( encryptedData2 ) . toBeUndefined ( ) ;
51
396
} ) ;
52
397
53
398
it ( 'should save metadata' , async ( ) => {
0 commit comments