TestConfig.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. const fs = require('node:fs')
  2. const Path = require('node:path')
  3. const crypto = require('node:crypto')
  4. const {
  5. RootKeyEncryptionKey,
  6. } = require('@overleaf/object-persistor/src/PerProjectEncryptedS3Persistor')
  7. const AWS_S3_USER_FILES_STORAGE_CLASS =
  8. process.env.AWS_S3_USER_FILES_STORAGE_CLASS
  9. // use functions to get a fresh copy, not a reference, each time
  10. function s3BaseConfig() {
  11. return {
  12. endpoint: process.env.AWS_S3_ENDPOINT,
  13. pathStyle: true,
  14. partSize: 100 * 1024 * 1024,
  15. ca: [fs.readFileSync('/certs/public.crt')],
  16. }
  17. }
  18. function s3Config() {
  19. return {
  20. key: process.env.AWS_ACCESS_KEY_ID,
  21. secret: process.env.AWS_SECRET_ACCESS_KEY,
  22. ...s3BaseConfig(),
  23. }
  24. }
  25. const S3SSECKeys = [
  26. new RootKeyEncryptionKey(
  27. crypto.generateKeySync('aes', { length: 256 }).export(),
  28. Buffer.alloc(32)
  29. ),
  30. ]
  31. function s3SSECConfig() {
  32. return {
  33. ...s3Config(),
  34. ignoreErrorsFromDEKReEncryption: false,
  35. automaticallyRotateDEKEncryption: true,
  36. dataEncryptionKeyBucketName: process.env.AWS_S3_USER_FILES_DEK_BUCKET_NAME,
  37. pathToProjectFolder(_bucketName, path) {
  38. const [projectFolder] = path.match(/^[a-f0-9]+\//)
  39. return projectFolder
  40. },
  41. async getRootKeyEncryptionKeys() {
  42. return S3SSECKeys
  43. },
  44. storageClass: {
  45. [process.env.AWS_S3_USER_FILES_BUCKET_NAME]:
  46. AWS_S3_USER_FILES_STORAGE_CLASS,
  47. },
  48. }
  49. }
  50. function s3ConfigDefaultProviderCredentials() {
  51. return {
  52. ...s3BaseConfig(),
  53. }
  54. }
  55. function s3Stores() {
  56. return {
  57. user_files: process.env.AWS_S3_USER_FILES_BUCKET_NAME,
  58. template_files: process.env.AWS_S3_TEMPLATE_FILES_BUCKET_NAME,
  59. }
  60. }
  61. function gcsConfig() {
  62. return {
  63. endpoint: {
  64. apiEndpoint: process.env.GCS_API_ENDPOINT,
  65. projectId: 'fake',
  66. },
  67. directoryKeyRegex: /^[0-9a-fA-F]{24}\/[0-9a-fA-F]{24}/,
  68. unlockBeforeDelete: false, // fake-gcs does not support this
  69. deletedBucketSuffix: '-deleted',
  70. }
  71. }
  72. function gcsStores() {
  73. return {
  74. user_files: process.env.GCS_USER_FILES_BUCKET_NAME,
  75. template_files: process.env.GCS_TEMPLATE_FILES_BUCKET_NAME,
  76. }
  77. }
  78. function fsStores() {
  79. return {
  80. user_files: Path.resolve(__dirname, '../../../user_files'),
  81. template_files: Path.resolve(__dirname, '../../../template_files'),
  82. }
  83. }
  84. function fallbackStores(primaryConfig, fallbackConfig) {
  85. return {
  86. [primaryConfig.user_files]: fallbackConfig.user_files,
  87. [primaryConfig.template_files]: fallbackConfig.template_files,
  88. }
  89. }
  90. const BackendSettings = {
  91. SHARD_01_FSPersistor: {
  92. backend: 'fs',
  93. stores: fsStores(),
  94. },
  95. SHARD_01_S3Persistor: {
  96. backend: 's3',
  97. s3: s3Config(),
  98. stores: s3Stores(),
  99. },
  100. SHARD_01_S3PersistorDefaultProviderCredentials: {
  101. backend: 's3',
  102. s3: s3ConfigDefaultProviderCredentials(),
  103. stores: s3Stores(),
  104. },
  105. SHARD_01_GcsPersistor: {
  106. backend: 'gcs',
  107. gcs: gcsConfig(),
  108. stores: gcsStores(),
  109. },
  110. SHARD_01_PerProjectEncryptedS3Persistor: {
  111. backend: 's3SSEC',
  112. s3SSEC: s3SSECConfig(),
  113. stores: s3Stores(),
  114. },
  115. SHARD_02_FallbackS3ToFSPersistor: {
  116. backend: 's3',
  117. s3: s3Config(),
  118. stores: s3Stores(),
  119. fallback: {
  120. backend: 'fs',
  121. buckets: fallbackStores(s3Stores(), fsStores()),
  122. },
  123. },
  124. SHARD_02_FallbackFSToS3Persistor: {
  125. backend: 'fs',
  126. s3: s3Config(),
  127. stores: fsStores(),
  128. fallback: {
  129. backend: 's3',
  130. buckets: fallbackStores(fsStores(), s3Stores()),
  131. },
  132. },
  133. SHARD_03_FallbackGcsToS3Persistor: {
  134. backend: 'gcs',
  135. gcs: gcsConfig(),
  136. stores: gcsStores(),
  137. s3: s3Config(),
  138. fallback: {
  139. backend: 's3',
  140. buckets: fallbackStores(gcsStores(), s3Stores()),
  141. },
  142. },
  143. SHARD_03_FallbackS3ToGcsPersistor: {
  144. backend: 's3',
  145. // can use the same bucket names for gcs and s3 (in tests)
  146. stores: s3Stores(),
  147. s3: s3Config(),
  148. gcs: gcsConfig(),
  149. fallback: {
  150. backend: 'gcs',
  151. buckets: fallbackStores(s3Stores(), gcsStores()),
  152. },
  153. },
  154. }
  155. function checkForUnexpectedTestFile() {
  156. const awareOfSharding = [
  157. 'FilestoreApp.js',
  158. 'FilestoreTests.js',
  159. 'TestConfig.js',
  160. 'TestHelper.js',
  161. ]
  162. for (const file of fs.readdirSync(__dirname).sort()) {
  163. if (!awareOfSharding.includes(file)) {
  164. throw new Error(
  165. `Found new test file ${file}: All tests must be aware of the SHARD_ prefix.`
  166. )
  167. }
  168. }
  169. }
  170. checkForUnexpectedTestFile()
  171. module.exports = {
  172. AWS_S3_USER_FILES_STORAGE_CLASS,
  173. BackendSettings,
  174. s3Config,
  175. s3SSECConfig,
  176. }