secureFiles.spec.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. 'use strict';
  2. const FileSystemAdapter = require('../index.js');
  3. const fs = require('fs');
  4. const path = require('path');
  5. describe('File encryption tests', () => {
  6. const directory = 'sub1/sub2';
  7. afterEach(function() {
  8. const filePath = path.join('files', directory);
  9. const fileNames = fs.readdirSync(filePath);
  10. fileNames.filter(fileName => fileName.indexOf('.') === 0);
  11. fileNames.forEach(fileName => {
  12. fs.unlinkSync(path.join(filePath, fileName));
  13. })
  14. });
  15. it('should create file location based on config', async function () {
  16. const fsAdapter = new FileSystemAdapter();
  17. const config = {mount: '/parse', applicationId: 'yolo'}
  18. const location = fsAdapter.getFileLocation(config, 'hello.txt')
  19. expect(location).toBe('/parse/files/yolo/hello.txt');
  20. }, 5000)
  21. it("should save encrypted file in default directory", async function() {
  22. const adapter = new FileSystemAdapter({
  23. encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
  24. });
  25. const filename = 'file2.txt';
  26. const filePath = 'files/' + filename;
  27. await adapter.createFile(filename, "hello world", 'text/utf8');
  28. const result = await adapter.getFileData(filename);
  29. expect(result instanceof Buffer).toBe(true);
  30. expect(result.toString('utf-8')).toEqual("hello world");
  31. const data = fs.readFileSync(filePath);
  32. expect(data.toString('utf-8')).not.toEqual("hello world");
  33. }, 5000);
  34. it("should save encrypted file in specified directory", async function() {
  35. const adapter = new FileSystemAdapter({
  36. filesSubDirectory: directory,
  37. encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
  38. });
  39. const filename = 'file2.txt';
  40. const filePath = 'files/' + directory + '/' + filename;
  41. await adapter.createFile(filename, "hello world", 'text/utf8');
  42. const result = await adapter.getFileData(filename);
  43. expect(result instanceof Buffer).toBe(true);
  44. expect(result.toString('utf-8')).toEqual("hello world");
  45. const data = fs.readFileSync(filePath);
  46. expect(data.toString('utf-8')).not.toEqual("hello world");
  47. }, 5000);
  48. it("should save encrypted file in specified directory when directory starts with /", async function() {
  49. const adapter = new FileSystemAdapter({
  50. filesSubDirectory: '/sub1/sub2',
  51. encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
  52. });
  53. const filename = 'file2.txt';
  54. const filePath = 'files/' + directory + '/' + filename;
  55. await adapter.createFile(filename, "hello world", 'text/utf8');
  56. const result = await adapter.getFileData(filename);
  57. expect(result instanceof Buffer).toBe(true);
  58. expect(result.toString('utf-8')).toEqual("hello world");
  59. const data = fs.readFileSync(filePath);
  60. expect(data.toString('utf-8')).not.toEqual("hello world");
  61. }, 5000);
  62. it("should rotate key of all unencrypted files to encrypted files", async function() {
  63. const unEncryptedAdapter = new FileSystemAdapter({
  64. filesSubDirectory: directory
  65. });
  66. const encryptedAdapter = new FileSystemAdapter({
  67. filesSubDirectory: directory,
  68. encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD'
  69. });
  70. const fileName1 = 'file1.txt';
  71. const data1 = "hello world";
  72. const fileName2 = 'file2.txt';
  73. const data2 = "hello new world";
  74. const filePath1 = 'files/' + directory + '/' + fileName1;
  75. const filePath2 = 'files/' + directory + '/' + fileName2;
  76. // Store unecrypted files
  77. await unEncryptedAdapter.createFile(fileName1, data1, 'text/utf8');
  78. let result = await unEncryptedAdapter.getFileData(fileName1);
  79. expect(result instanceof Buffer).toBe(true);
  80. expect(result.toString('utf-8')).toEqual(data1);
  81. const unEncryptedData1 = fs.readFileSync(filePath1);
  82. await unEncryptedAdapter.createFile(fileName2, data2, 'text/utf8');
  83. result = await unEncryptedAdapter.getFileData(fileName2);
  84. expect(result instanceof Buffer).toBe(true);
  85. expect(result.toString('utf-8')).toEqual(data2);
  86. const unEncryptedData2 = fs.readFileSync(filePath2);
  87. // Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
  88. const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey();
  89. expect(rotated.length).toEqual(2);
  90. expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1);
  91. expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1);
  92. expect(notRotated.length).toEqual(0);
  93. result = await encryptedAdapter.getFileData(fileName1);
  94. expect(result instanceof Buffer).toBe(true);
  95. expect(result.toString('utf-8')).toEqual(data1);
  96. const encryptedData1 = fs.readFileSync(filePath1);
  97. expect(encryptedData1.toString('utf-8')).not.toEqual(unEncryptedData1);
  98. result = await encryptedAdapter.getFileData(fileName2);
  99. expect(result instanceof Buffer).toBe(true);
  100. expect(result.toString('utf-8')).toEqual(data2);
  101. const encryptedData2 = fs.readFileSync(filePath2);
  102. expect(encryptedData2.toString('utf-8')).not.toEqual(unEncryptedData2);
  103. }, 5000);
  104. it("should rotate key of all old encrypted files to files encrypted with a new key", async function() {
  105. const oldEncryptionKey = 'oldKeyThatILoved';
  106. const oldEncryptedAdapter = new FileSystemAdapter({
  107. filesSubDirectory: directory,
  108. encryptionKey: oldEncryptionKey
  109. });
  110. const encryptedAdapter = new FileSystemAdapter({
  111. filesSubDirectory: directory,
  112. encryptionKey: 'newKeyThatILove'
  113. });
  114. const fileName1 = 'file1.txt';
  115. const data1 = "hello world";
  116. const fileName2 = 'file2.txt';
  117. const data2 = "hello new world";
  118. const filePath1 = 'files/' + directory + '/' + fileName1;
  119. const filePath2 = 'files/' + directory + '/' + fileName2;
  120. // Store original encrypted files
  121. await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8');
  122. let result = await oldEncryptedAdapter.getFileData(fileName1);
  123. expect(result instanceof Buffer).toBe(true);
  124. expect(result.toString('utf-8')).toEqual(data1);
  125. const oldEncryptedData1 = fs.readFileSync(filePath1);
  126. await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8');
  127. result = await oldEncryptedAdapter.getFileData(fileName2);
  128. expect(result instanceof Buffer).toBe(true);
  129. expect(result.toString('utf-8')).toEqual(data2);
  130. const oldEncryptedData2 = fs.readFileSync(filePath2);
  131. // Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
  132. const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey});
  133. expect(rotated.length).toEqual(2);
  134. expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1);
  135. expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1);
  136. expect(notRotated.length).toEqual(0);
  137. const result2 = await encryptedAdapter.getFileData(fileName1);
  138. expect(result2 instanceof Buffer).toBe(true);
  139. expect(result2.toString('utf-8')).toEqual(data1);
  140. const encryptedData1 = fs.readFileSync(filePath1);
  141. expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1);
  142. result = await encryptedAdapter.getFileData(fileName2);
  143. expect(result instanceof Buffer).toBe(true);
  144. expect(result.toString('utf-8')).toEqual(data2);
  145. const encryptedData2 = fs.readFileSync(filePath2);
  146. expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2);
  147. }, 5000);
  148. it("should rotate key of all old encrypted files to unencrypted files", async function() {
  149. const oldEncryptionKey = 'oldKeyThatILoved';
  150. const oldEncryptedAdapter = new FileSystemAdapter({
  151. filesSubDirectory: directory,
  152. encryptionKey: oldEncryptionKey
  153. });
  154. const unEncryptedAdapter = new FileSystemAdapter({
  155. filesSubDirectory: directory
  156. });
  157. const fileName1 = 'file1.txt';
  158. const data1 = "hello world";
  159. const fileName2 = 'file2.txt';
  160. const data2 = "hello new world";
  161. const filePath1 = 'files/' + directory + '/' + fileName1;
  162. const filePath2 = 'files/' + directory + '/' + fileName2;
  163. // Store original encrypted files
  164. await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8');
  165. let result = await oldEncryptedAdapter.getFileData(fileName1);
  166. expect(result instanceof Buffer).toBe(true);
  167. expect(result.toString('utf-8')).toEqual(data1);
  168. const oldEncryptedData1 = fs.readFileSync(filePath1);
  169. await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8');
  170. result = await oldEncryptedAdapter.getFileData(fileName2);
  171. expect(result instanceof Buffer).toBe(true);
  172. expect(result.toString('utf-8')).toEqual(data2);
  173. const oldEncryptedData2 = fs.readFileSync(filePath2);
  174. // Check if unEncrypted adapter can read data and make sure it's not the same as oldEncrypted adapter
  175. const {rotated, notRotated} = await unEncryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey});
  176. expect(rotated.length).toEqual(2);
  177. expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1);
  178. expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1);
  179. expect(notRotated.length).toEqual(0);
  180. const result2 = await unEncryptedAdapter.getFileData(fileName1);
  181. expect(result2 instanceof Buffer).toBe(true);
  182. expect(result2.toString('utf-8')).toEqual(data1);
  183. const encryptedData1 = fs.readFileSync(filePath1);
  184. expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1);
  185. result = await unEncryptedAdapter.getFileData(fileName2);
  186. expect(result instanceof Buffer).toBe(true);
  187. expect(result.toString('utf-8')).toEqual(data2);
  188. const encryptedData2 = fs.readFileSync(filePath2);
  189. expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2);
  190. }, 5000);
  191. it("should only encrypt specified fileNames with the new key", async function() {
  192. const oldEncryptionKey = 'oldKeyThatILoved';
  193. const oldEncryptedAdapter = new FileSystemAdapter({
  194. filesSubDirectory: directory,
  195. encryptionKey: oldEncryptionKey
  196. });
  197. const encryptedAdapter = new FileSystemAdapter({
  198. filesSubDirectory: directory,
  199. encryptionKey: 'newKeyThatILove'
  200. });
  201. const unEncryptedAdapter = new FileSystemAdapter({
  202. filesSubDirectory: directory
  203. });
  204. const fileName1 = 'file1.txt';
  205. const data1 = "hello world";
  206. const fileName2 = 'file2.txt';
  207. const data2 = "hello new world";
  208. const filePath1 = 'files/' + directory + '/' + fileName1;
  209. const filePath2 = 'files/' + directory + '/' + fileName2;
  210. // Store original encrypted files
  211. await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8');
  212. let result = await oldEncryptedAdapter.getFileData(fileName1);
  213. expect(result instanceof Buffer).toBe(true);
  214. expect(result.toString('utf-8')).toEqual(data1);
  215. const oldEncryptedData1 = fs.readFileSync(filePath1);
  216. await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8');
  217. result = await oldEncryptedAdapter.getFileData(fileName2);
  218. expect(result instanceof Buffer).toBe(true);
  219. expect(result.toString('utf-8')).toEqual(data2);
  220. const oldEncryptedData2 = fs.readFileSync(filePath2);
  221. // Inject unecrypted file to see if causes an issue
  222. const fileName3 = 'file3.txt';
  223. const data3 = "hello past world";
  224. await unEncryptedAdapter.createFile(fileName3, data3, 'text/utf8');
  225. // Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
  226. const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey, fileNames: [fileName1,fileName2]});
  227. expect(rotated.length).toEqual(2);
  228. expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1);
  229. expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1);
  230. expect(notRotated.length).toEqual(0);
  231. expect(rotated.filter(function(value){ return value === fileName3;}).length).toEqual(0);
  232. const result2 = await encryptedAdapter.getFileData(fileName1);
  233. expect(result2 instanceof Buffer).toBe(true);
  234. expect(result2.toString('utf-8')).toEqual(data1);
  235. const encryptedData1 = fs.readFileSync(filePath1);
  236. expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1);
  237. result = await encryptedAdapter.getFileData(fileName2);
  238. expect(result instanceof Buffer).toBe(true);
  239. expect(result.toString('utf-8')).toEqual(data2);
  240. const encryptedData2 = fs.readFileSync(filePath2);
  241. expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2);
  242. }, 5000);
  243. it("should return fileNames of those it can't encrypt with the new key", async function() {
  244. const oldEncryptionKey = 'oldKeyThatILoved';
  245. const oldEncryptedAdapter = new FileSystemAdapter({
  246. filesSubDirectory: directory,
  247. encryptionKey: oldEncryptionKey
  248. });
  249. const encryptedAdapter = new FileSystemAdapter({
  250. filesSubDirectory: directory,
  251. encryptionKey: 'newKeyThatILove'
  252. });
  253. const unEncryptedAdapter = new FileSystemAdapter({
  254. filesSubDirectory: directory
  255. });
  256. const fileName1 = 'file1.txt';
  257. const data1 = "hello world";
  258. const fileName2 = 'file2.txt';
  259. const data2 = "hello new world";
  260. const filePath1 = 'files/' + directory + '/' + fileName1;
  261. const filePath2 = 'files/' + directory + '/' + fileName2;
  262. // Store original encrypted files
  263. await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8');
  264. let result = await oldEncryptedAdapter.getFileData(fileName1);
  265. expect(result instanceof Buffer).toBe(true);
  266. expect(result.toString('utf-8')).toEqual(data1);
  267. const oldEncryptedData1 = fs.readFileSync(filePath1);
  268. await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8');
  269. result = await oldEncryptedAdapter.getFileData(fileName2);
  270. expect(result instanceof Buffer).toBe(true);
  271. expect(result.toString('utf-8')).toEqual(data2);
  272. const oldEncryptedData2 = fs.readFileSync(filePath2);
  273. // Inject unecrypted file to cause an issue
  274. const fileName3 = 'file3.txt';
  275. const data3 = "hello past world";
  276. await unEncryptedAdapter.createFile(fileName3, data3, 'text/utf8');
  277. result = await unEncryptedAdapter.getFileData(fileName3);
  278. expect(result instanceof Buffer).toBe(true);
  279. expect(result.toString('utf-8')).toEqual(data3);
  280. // Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter
  281. const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey});
  282. expect(rotated.length).toEqual(2);
  283. expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1);
  284. expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1);
  285. expect(notRotated.length).toEqual(1);
  286. expect(notRotated.filter(function(value){ return value === fileName3;}).length).toEqual(1);
  287. const result2 = await encryptedAdapter.getFileData(fileName1);
  288. expect(result2 instanceof Buffer).toBe(true);
  289. expect(result2.toString('utf-8')).toEqual(data1);
  290. const encryptedData1 = fs.readFileSync(filePath1);
  291. expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1);
  292. result = await encryptedAdapter.getFileData(fileName2);
  293. expect(result instanceof Buffer).toBe(true);
  294. expect(result.toString('utf-8')).toEqual(data2);
  295. const encryptedData2 = fs.readFileSync(filePath2);
  296. expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2);
  297. }, 5000);
  298. })