@@ -34,20 +34,365 @@ describe_only_db('mongo')('GridFSBucket and GridStore interop', () => {
3434 expect ( gfsResult . toString ( 'utf8' ) ) . toBe ( originalString ) ;
3535 } ) ;
3636
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 (
4040 databaseURI ,
4141 { } ,
4242 '89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
4343 ) ;
44- await expectMissingFile ( gfsAdapter , 'myFileName' ) ;
44+ await expectMissingFile ( encryptedAdapter , 'myFileName' ) ;
4545 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 ( ) ;
51396 } ) ;
52397
53398 it ( 'should save metadata' , async ( ) => {
0 commit comments