@backstage/backend-defaults 0.5.1-next.1 → 0.5.1-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/auth/package.json +1 -1
  3. package/cache/package.json +1 -1
  4. package/database/package.json +1 -1
  5. package/discovery/package.json +1 -1
  6. package/dist/CreateBackend.cjs.js +49 -0
  7. package/dist/CreateBackend.cjs.js.map +1 -0
  8. package/dist/PackageDiscoveryService.cjs.js +109 -0
  9. package/dist/PackageDiscoveryService.cjs.js.map +1 -0
  10. package/dist/auth.cjs.js +2 -996
  11. package/dist/auth.cjs.js.map +1 -1
  12. package/dist/cache.cjs.js +4 -204
  13. package/dist/cache.cjs.js.map +1 -1
  14. package/dist/database.cjs.js +4 -957
  15. package/dist/database.cjs.js.map +1 -1
  16. package/dist/database.d.ts +4 -1
  17. package/dist/discovery.cjs.js +4 -92
  18. package/dist/discovery.cjs.js.map +1 -1
  19. package/dist/discoveryFeatureLoader.cjs.js +19 -0
  20. package/dist/discoveryFeatureLoader.cjs.js.map +1 -0
  21. package/dist/entrypoints/auth/DefaultAuthService.cjs.js +130 -0
  22. package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -0
  23. package/dist/entrypoints/auth/JwksClient.cjs.js +49 -0
  24. package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -0
  25. package/dist/entrypoints/auth/authServiceFactory.cjs.js +57 -0
  26. package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -0
  27. package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js +78 -0
  28. package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -0
  29. package/dist/entrypoints/auth/external/helpers.cjs.js +92 -0
  30. package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -0
  31. package/dist/entrypoints/auth/external/jwks.cjs.js +63 -0
  32. package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -0
  33. package/dist/entrypoints/auth/external/legacy.cjs.js +73 -0
  34. package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -0
  35. package/dist/entrypoints/auth/external/static.cjs.js +33 -0
  36. package/dist/entrypoints/auth/external/static.cjs.js.map +1 -0
  37. package/dist/{cjs/helpers-D2f1CG0o.cjs.js → entrypoints/auth/helpers.cjs.js} +1 -1
  38. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -0
  39. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +147 -0
  40. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -0
  41. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js +73 -0
  42. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -0
  43. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js +75 -0
  44. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -0
  45. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js +91 -0
  46. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -0
  47. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js +29 -0
  48. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -0
  49. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js +110 -0
  50. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -0
  51. package/dist/entrypoints/cache/CacheClient.cjs.js +50 -0
  52. package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -0
  53. package/dist/entrypoints/cache/CacheManager.cjs.js +147 -0
  54. package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -0
  55. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js +22 -0
  56. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -0
  57. package/dist/entrypoints/cache/types.cjs.js +10 -0
  58. package/dist/entrypoints/cache/types.cjs.js.map +1 -0
  59. package/dist/entrypoints/database/DatabaseManager.cjs.js +173 -0
  60. package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -0
  61. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js +14 -0
  62. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -0
  63. package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js +12 -0
  64. package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -0
  65. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js +10 -0
  66. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -0
  67. package/dist/entrypoints/database/connectors/mysql.cjs.js +278 -0
  68. package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -0
  69. package/dist/entrypoints/database/connectors/postgres.cjs.js +304 -0
  70. package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -0
  71. package/dist/entrypoints/database/connectors/sqlite3.cjs.js +251 -0
  72. package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -0
  73. package/dist/entrypoints/database/databaseServiceFactory.cjs.js +36 -0
  74. package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -0
  75. package/dist/entrypoints/discovery/HostDiscovery.cjs.js +86 -0
  76. package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -0
  77. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js +17 -0
  78. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -0
  79. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js +192 -0
  80. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -0
  81. package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js +19 -0
  82. package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js.map +1 -0
  83. package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js +26 -0
  84. package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js.map +1 -0
  85. package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js +63 -0
  86. package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js.map +1 -0
  87. package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js +52 -0
  88. package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js.map +1 -0
  89. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js +48 -0
  90. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -0
  91. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js +88 -0
  92. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -0
  93. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js +17 -0
  94. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -0
  95. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js +22 -0
  96. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -0
  97. package/dist/{cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js → entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js} +1 -1
  98. package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -0
  99. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js +26 -0
  100. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -0
  101. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js +41 -0
  102. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -0
  103. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js +77 -0
  104. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -0
  105. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js +29 -0
  106. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -0
  107. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js +187 -0
  108. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -0
  109. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js +28 -0
  110. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -0
  111. package/dist/{cjs/config-BDOwXIyo.cjs.js → entrypoints/rootHttpRouter/http/config.cjs.js} +1 -1
  112. package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -0
  113. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js +88 -0
  114. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -0
  115. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js +130 -0
  116. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -0
  117. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js +51 -0
  118. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -0
  119. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js +62 -0
  120. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -0
  121. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +73 -0
  122. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -0
  123. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js +76 -0
  124. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -0
  125. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js +114 -0
  126. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -0
  127. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js +30 -0
  128. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -0
  129. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js +18 -0
  130. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -0
  131. package/dist/entrypoints/scheduler/database/tables.cjs.js +8 -0
  132. package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -0
  133. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js +37 -0
  134. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -0
  135. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js +105 -0
  136. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -0
  137. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js +138 -0
  138. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -0
  139. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js +59 -0
  140. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -0
  141. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js +275 -0
  142. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -0
  143. package/dist/entrypoints/scheduler/lib/types.cjs.js +60 -0
  144. package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -0
  145. package/dist/entrypoints/scheduler/lib/util.cjs.js +66 -0
  146. package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -0
  147. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js +19 -0
  148. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -0
  149. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js +274 -0
  150. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -0
  151. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js +261 -0
  152. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -0
  153. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js +148 -0
  154. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -0
  155. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js +174 -0
  156. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -0
  157. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js +170 -0
  158. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -0
  159. package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js +182 -0
  160. package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -0
  161. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js +132 -0
  162. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -0
  163. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js +147 -0
  164. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -0
  165. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js +122 -0
  166. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -0
  167. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js +226 -0
  168. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -0
  169. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +277 -0
  170. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -0
  171. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js +129 -0
  172. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -0
  173. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js +120 -0
  174. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -0
  175. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js +49 -0
  176. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -0
  177. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js +46 -0
  178. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -0
  179. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js +68 -0
  180. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -0
  181. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js +46 -0
  182. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -0
  183. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js +78 -0
  184. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -0
  185. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js +147 -0
  186. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -0
  187. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js +161 -0
  188. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -0
  189. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js +28 -0
  190. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -0
  191. package/dist/entrypoints/urlReader/lib/util.cjs.js +11 -0
  192. package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -0
  193. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js +29 -0
  194. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -0
  195. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js +59 -0
  196. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -0
  197. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js +17 -0
  198. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -0
  199. package/dist/httpAuth.cjs.js +3 -187
  200. package/dist/httpAuth.cjs.js.map +1 -1
  201. package/dist/httpRouter.cjs.js +2 -166
  202. package/dist/httpRouter.cjs.js.map +1 -1
  203. package/dist/index.cjs.js +4 -160
  204. package/dist/index.cjs.js.map +1 -1
  205. package/dist/lib/escapeRegExp.cjs.js +8 -0
  206. package/dist/lib/escapeRegExp.cjs.js.map +1 -0
  207. package/dist/lifecycle.cjs.js +3 -58
  208. package/dist/lifecycle.cjs.js.map +1 -1
  209. package/dist/logger.cjs.js +3 -12
  210. package/dist/logger.cjs.js.map +1 -1
  211. package/dist/package.json.cjs.js +252 -0
  212. package/dist/package.json.cjs.js.map +1 -0
  213. package/dist/permissions.cjs.js +3 -17
  214. package/dist/permissions.cjs.js.map +1 -1
  215. package/dist/rootConfig.cjs.js +4 -22
  216. package/dist/rootConfig.cjs.js.map +1 -1
  217. package/dist/rootHealth.cjs.js +3 -35
  218. package/dist/rootHealth.cjs.js.map +1 -1
  219. package/dist/rootHttpRouter.cjs.js +15 -651
  220. package/dist/rootHttpRouter.cjs.js.map +1 -1
  221. package/dist/rootLifecycle.cjs.js +3 -70
  222. package/dist/rootLifecycle.cjs.js.map +1 -1
  223. package/dist/rootLogger.cjs.js +4 -137
  224. package/dist/rootLogger.cjs.js.map +1 -1
  225. package/dist/scheduler.cjs.js +4 -693
  226. package/dist/scheduler.cjs.js.map +1 -1
  227. package/dist/scheduler.d.ts +2 -1
  228. package/dist/urlReader.cjs.js +32 -2962
  229. package/dist/urlReader.cjs.js.map +1 -1
  230. package/dist/userInfo.cjs.js +2 -64
  231. package/dist/userInfo.cjs.js.map +1 -1
  232. package/httpAuth/package.json +1 -1
  233. package/httpRouter/package.json +1 -1
  234. package/lifecycle/package.json +1 -1
  235. package/logger/package.json +1 -1
  236. package/package.json +13 -13
  237. package/permissions/package.json +1 -1
  238. package/rootConfig/package.json +1 -1
  239. package/rootHealth/package.json +1 -1
  240. package/rootHttpRouter/package.json +1 -1
  241. package/rootLifecycle/package.json +1 -1
  242. package/rootLogger/package.json +1 -1
  243. package/scheduler/package.json +1 -1
  244. package/urlReader/package.json +1 -1
  245. package/userInfo/package.json +1 -1
  246. package/dist/cjs/config-BDOwXIyo.cjs.js.map +0 -1
  247. package/dist/cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js.map +0 -1
  248. package/dist/cjs/helpers-D2f1CG0o.cjs.js.map +0 -1
@@ -0,0 +1,274 @@
1
+ 'use strict';
2
+
3
+ var integrationAwsNode = require('@backstage/integration-aws-node');
4
+ var integration = require('@backstage/integration');
5
+ var errors = require('@backstage/errors');
6
+ var credentialProviders = require('@aws-sdk/credential-providers');
7
+ var clientCodecommit = require('@aws-sdk/client-codecommit');
8
+ var stream = require('stream');
9
+ var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
10
+ var posix = require('path/posix');
11
+ var abortController = require('@aws-sdk/abort-controller');
12
+
13
+ function parseUrl(url, requireGitPath = false) {
14
+ const parsedUrl = new URL(url);
15
+ if (parsedUrl.pathname.includes("/files/edit/")) {
16
+ throw new Error(
17
+ "Please provide the view url to yaml file from CodeCommit, not the edit url"
18
+ );
19
+ }
20
+ if (requireGitPath && !parsedUrl.pathname.includes("/browse/")) {
21
+ throw new Error("Please provide full path to yaml file from CodeCommit");
22
+ }
23
+ const hostMatch = parsedUrl.host.match(
24
+ /^([^\.]+)\.console\.aws\.amazon\.com$/
25
+ );
26
+ if (!hostMatch) {
27
+ throw new Error(
28
+ `Invalid AWS CodeCommit URL (unexpected host format): ${url}`
29
+ );
30
+ }
31
+ const [, region] = hostMatch;
32
+ const pathMatch = parsedUrl.pathname.match(
33
+ /^\/codesuite\/codecommit\/repositories\/([^\/]+)\/browse\/((.*)\/)?--\/(.*)$/
34
+ );
35
+ if (!pathMatch) {
36
+ if (!requireGitPath) {
37
+ const pathname = parsedUrl.pathname.split("/--/")[0].replace("/codesuite/codecommit/repositories/", "");
38
+ const [repositoryName2, commitSpecifier2] = pathname.split("/browse");
39
+ return {
40
+ region,
41
+ repositoryName: repositoryName2.replace(/^\/|\/$/g, ""),
42
+ path: "/",
43
+ commitSpecifier: commitSpecifier2 === "" ? void 0 : commitSpecifier2?.replace(/^\/|\/$/g, "")
44
+ };
45
+ }
46
+ throw new Error(
47
+ `Invalid AWS CodeCommit URL (unexpected path format): ${url}`
48
+ );
49
+ }
50
+ const [, repositoryName, , commitSpecifier, path] = pathMatch;
51
+ return {
52
+ region,
53
+ repositoryName,
54
+ path,
55
+ // the commitSpecifier is passed to AWS SDK which does not allow empty strings so replace empty string with undefined
56
+ commitSpecifier: commitSpecifier === "" ? void 0 : commitSpecifier
57
+ };
58
+ }
59
+ class AwsCodeCommitUrlReader {
60
+ constructor(credsManager, integration, deps) {
61
+ this.credsManager = credsManager;
62
+ this.integration = integration;
63
+ this.deps = deps;
64
+ }
65
+ static factory = ({ config, treeResponseFactory }) => {
66
+ const integrations = integration.ScmIntegrations.fromConfig(config);
67
+ const credsManager = integrationAwsNode.DefaultAwsCredentialsManager.fromConfig(config);
68
+ return integrations.awsCodeCommit.list().map((integration) => {
69
+ const reader = new AwsCodeCommitUrlReader(credsManager, integration, {
70
+ treeResponseFactory
71
+ });
72
+ const predicate = (url) => {
73
+ return url.host.endsWith(integration.config.host) && url.pathname.startsWith("/codesuite/codecommit");
74
+ };
75
+ return { reader, predicate };
76
+ });
77
+ };
78
+ /**
79
+ * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:
80
+ * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html
81
+ */
82
+ static buildStaticCredentials(accessKeyId, secretAccessKey) {
83
+ return async () => {
84
+ return {
85
+ accessKeyId,
86
+ secretAccessKey
87
+ };
88
+ };
89
+ }
90
+ static async buildCredentials(credsManager, region, integration) {
91
+ if (!integration) {
92
+ return (await credsManager.getCredentialProvider()).sdkCredentialProvider;
93
+ }
94
+ const accessKeyId = integration.config.accessKeyId;
95
+ const secretAccessKey = integration.config.secretAccessKey;
96
+ let explicitCredentials;
97
+ if (accessKeyId && secretAccessKey) {
98
+ explicitCredentials = AwsCodeCommitUrlReader.buildStaticCredentials(
99
+ accessKeyId,
100
+ secretAccessKey
101
+ );
102
+ } else {
103
+ explicitCredentials = (await credsManager.getCredentialProvider()).sdkCredentialProvider;
104
+ }
105
+ const roleArn = integration.config.roleArn;
106
+ if (roleArn) {
107
+ return credentialProviders.fromTemporaryCredentials({
108
+ masterCredentials: explicitCredentials,
109
+ params: {
110
+ RoleSessionName: "backstage-aws-code-commit-url-reader",
111
+ RoleArn: roleArn,
112
+ ExternalId: integration.config.externalId
113
+ },
114
+ clientConfig: { region }
115
+ });
116
+ }
117
+ return explicitCredentials;
118
+ }
119
+ async buildCodeCommitClient(credsManager, region, integration) {
120
+ const credentials = await AwsCodeCommitUrlReader.buildCredentials(
121
+ credsManager,
122
+ region,
123
+ integration
124
+ );
125
+ const codeCommit = new clientCodecommit.CodeCommitClient({
126
+ customUserAgent: "backstage-aws-codecommit-url-reader",
127
+ region,
128
+ credentials
129
+ });
130
+ return codeCommit;
131
+ }
132
+ async readUrl(url, options) {
133
+ try {
134
+ const { path, repositoryName, region, commitSpecifier } = parseUrl(
135
+ url,
136
+ true
137
+ );
138
+ const codeCommitClient = await this.buildCodeCommitClient(
139
+ this.credsManager,
140
+ region,
141
+ this.integration
142
+ );
143
+ const abortController$1 = new abortController.AbortController();
144
+ const input = {
145
+ repositoryName,
146
+ commitSpecifier,
147
+ filePath: path
148
+ };
149
+ options?.signal?.addEventListener("abort", () => abortController$1.abort());
150
+ const getObjectCommand = new clientCodecommit.GetFileCommand(input);
151
+ const response = await codeCommitClient.send(
152
+ getObjectCommand,
153
+ {
154
+ abortSignal: abortController$1.signal
155
+ }
156
+ );
157
+ if (options?.etag && options.etag === response.commitId) {
158
+ throw new errors.NotModifiedError();
159
+ }
160
+ return ReadUrlResponseFactory.ReadUrlResponseFactory.fromReadable(
161
+ stream.Readable.from([response?.fileContent]),
162
+ {
163
+ etag: response.commitId
164
+ }
165
+ );
166
+ } catch (e) {
167
+ if (e.$metadata && e.$metadata.httpStatusCode === 304) {
168
+ throw new errors.NotModifiedError();
169
+ }
170
+ if (e.name && e.name === "NotModifiedError") {
171
+ throw new errors.NotModifiedError();
172
+ }
173
+ throw new errors.ForwardedError("Could not retrieve file from CodeCommit", e);
174
+ }
175
+ }
176
+ async readTreePath(codeCommitClient, abortSignal, path, repositoryName, commitSpecifier, etag) {
177
+ const getFolderCommand = new clientCodecommit.GetFolderCommand({
178
+ folderPath: path,
179
+ repositoryName,
180
+ commitSpecifier
181
+ });
182
+ const response = await codeCommitClient.send(getFolderCommand, {
183
+ abortSignal
184
+ });
185
+ if (etag && etag === response.commitId) {
186
+ throw new errors.NotModifiedError();
187
+ }
188
+ const output = [];
189
+ if (response.files) {
190
+ response.files.forEach((file) => {
191
+ if (file.absolutePath) {
192
+ output.push(file.absolutePath);
193
+ }
194
+ });
195
+ }
196
+ if (!response.subFolders) {
197
+ return output;
198
+ }
199
+ for (const subFolder of response.subFolders) {
200
+ if (subFolder.absolutePath) {
201
+ output.push(
202
+ ...await this.readTreePath(
203
+ codeCommitClient,
204
+ abortSignal,
205
+ subFolder.absolutePath,
206
+ repositoryName,
207
+ commitSpecifier,
208
+ etag
209
+ )
210
+ );
211
+ }
212
+ }
213
+ return output;
214
+ }
215
+ async readTree(url, options) {
216
+ try {
217
+ const { path, repositoryName, region, commitSpecifier } = parseUrl(url);
218
+ const codeCommitClient = await this.buildCodeCommitClient(
219
+ this.credsManager,
220
+ region,
221
+ this.integration
222
+ );
223
+ const abortController$1 = new abortController.AbortController();
224
+ options?.signal?.addEventListener("abort", () => abortController$1.abort());
225
+ const allFiles = await this.readTreePath(
226
+ codeCommitClient,
227
+ abortController$1.signal,
228
+ path,
229
+ repositoryName,
230
+ commitSpecifier,
231
+ options?.etag
232
+ );
233
+ const responses = [];
234
+ for (let i = 0; i < allFiles.length; i++) {
235
+ const getFileCommand = new clientCodecommit.GetFileCommand({
236
+ repositoryName,
237
+ filePath: String(allFiles[i]),
238
+ commitSpecifier
239
+ });
240
+ const response = await codeCommitClient.send(getFileCommand);
241
+ const objectData = await stream.Readable.from([response?.fileContent]);
242
+ responses.push({
243
+ data: objectData,
244
+ path: posix.relative(
245
+ path.startsWith("/") ? path : `/${path}`,
246
+ allFiles[i].startsWith("/") ? allFiles[i] : `/${allFiles[i]}`
247
+ )
248
+ });
249
+ }
250
+ return await this.deps.treeResponseFactory.fromReadableArray(responses);
251
+ } catch (e) {
252
+ if (e.name && e.name === "NotModifiedError") {
253
+ throw new errors.NotModifiedError();
254
+ }
255
+ throw new errors.ForwardedError(
256
+ "Could not retrieve file tree from CodeCommit",
257
+ e
258
+ );
259
+ }
260
+ }
261
+ async search() {
262
+ throw new Error("AwsCodeCommitReader does not implement search");
263
+ }
264
+ toString() {
265
+ const secretAccessKey = this.integration.config.secretAccessKey;
266
+ return `awsCodeCommit{host=${this.integration.config.host},authed=${Boolean(
267
+ secretAccessKey
268
+ )}}`;
269
+ }
270
+ }
271
+
272
+ exports.AwsCodeCommitUrlReader = AwsCodeCommitUrlReader;
273
+ exports.parseUrl = parseUrl;
274
+ //# sourceMappingURL=AwsCodeCommitUrlReader.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AwsCodeCommitUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport {\n AwsCodeCommitIntegration,\n ScmIntegrations,\n} from '@backstage/integration';\nimport { ForwardedError, NotModifiedError } from '@backstage/errors';\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport {\n CodeCommitClient,\n GetFileCommand,\n GetFileCommandInput,\n GetFileCommandOutput,\n GetFolderCommand,\n} from '@aws-sdk/client-codecommit';\nimport { AwsCredentialIdentityProvider } from '@aws-sdk/types';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { relative } from 'path/posix';\nimport { AbortController } from '@aws-sdk/abort-controller';\n\nexport function parseUrl(\n url: string,\n requireGitPath: boolean = false,\n): {\n path: string;\n repositoryName: string;\n region: string;\n commitSpecifier?: string;\n} {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.pathname.includes('/files/edit/')) {\n throw new Error(\n 'Please provide the view url to yaml file from CodeCommit, not the edit url',\n );\n }\n if (requireGitPath && !parsedUrl.pathname.includes('/browse/')) {\n throw new Error('Please provide full path to yaml file from CodeCommit');\n }\n\n const hostMatch = parsedUrl.host.match(\n /^([^\\.]+)\\.console\\.aws\\.amazon\\.com$/,\n );\n if (!hostMatch) {\n throw new Error(\n `Invalid AWS CodeCommit URL (unexpected host format): ${url}`,\n );\n }\n const [, region] = hostMatch;\n\n const pathMatch = parsedUrl.pathname.match(\n /^\\/codesuite\\/codecommit\\/repositories\\/([^\\/]+)\\/browse\\/((.*)\\/)?--\\/(.*)$/,\n );\n\n if (!pathMatch) {\n if (!requireGitPath) {\n const pathname = parsedUrl.pathname\n .split('/--/')[0]\n .replace('/codesuite/codecommit/repositories/', '');\n const [repositoryName, commitSpecifier] = pathname.split('/browse');\n\n return {\n region,\n repositoryName: repositoryName.replace(/^\\/|\\/$/g, ''),\n path: '/',\n commitSpecifier:\n commitSpecifier === ''\n ? undefined\n : commitSpecifier?.replace(/^\\/|\\/$/g, ''),\n };\n }\n throw new Error(\n `Invalid AWS CodeCommit URL (unexpected path format): ${url}`,\n );\n }\n const [, repositoryName, , commitSpecifier, path] = pathMatch;\n\n return {\n region,\n repositoryName,\n path,\n // the commitSpecifier is passed to AWS SDK which does not allow empty strings so replace empty string with undefined\n commitSpecifier: commitSpecifier === '' ? undefined : commitSpecifier,\n };\n}\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for AWS CodeCommit.\n *\n * @public\n */\nexport class AwsCodeCommitUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n const credsManager = DefaultAwsCredentialsManager.fromConfig(config);\n\n return integrations.awsCodeCommit.list().map(integration => {\n const reader = new AwsCodeCommitUrlReader(credsManager, integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => {\n return (\n url.host.endsWith(integration.config.host) &&\n url.pathname.startsWith('/codesuite/codecommit')\n );\n };\n\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly credsManager: AwsCredentialsManager,\n private readonly integration: AwsCodeCommitIntegration,\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {}\n\n /**\n * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:\n * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html\n */\n private static buildStaticCredentials(\n accessKeyId: string,\n secretAccessKey: string,\n ): AwsCredentialIdentityProvider {\n return async () => {\n return {\n accessKeyId,\n secretAccessKey,\n };\n };\n }\n\n private static async buildCredentials(\n credsManager: AwsCredentialsManager,\n region: string,\n integration?: AwsCodeCommitIntegration,\n ): Promise<AwsCredentialIdentityProvider> {\n // Fall back to the default credential chain if neither account ID\n // nor explicit credentials are provided\n if (!integration) {\n return (await credsManager.getCredentialProvider()).sdkCredentialProvider;\n }\n\n const accessKeyId = integration.config.accessKeyId;\n const secretAccessKey = integration.config.secretAccessKey;\n let explicitCredentials: AwsCredentialIdentityProvider;\n if (accessKeyId && secretAccessKey) {\n explicitCredentials = AwsCodeCommitUrlReader.buildStaticCredentials(\n accessKeyId,\n secretAccessKey,\n );\n } else {\n explicitCredentials = (await credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const roleArn = integration.config.roleArn;\n if (roleArn) {\n return fromTemporaryCredentials({\n masterCredentials: explicitCredentials,\n params: {\n RoleSessionName: 'backstage-aws-code-commit-url-reader',\n RoleArn: roleArn,\n ExternalId: integration.config.externalId,\n },\n clientConfig: { region },\n });\n }\n\n return explicitCredentials;\n }\n\n private async buildCodeCommitClient(\n credsManager: AwsCredentialsManager,\n region: string,\n integration: AwsCodeCommitIntegration,\n ): Promise<CodeCommitClient> {\n const credentials = await AwsCodeCommitUrlReader.buildCredentials(\n credsManager,\n region,\n integration,\n );\n\n const codeCommit = new CodeCommitClient({\n customUserAgent: 'backstage-aws-codecommit-url-reader',\n region: region,\n credentials: credentials,\n });\n return codeCommit;\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // etag and lastModifiedAfter are not supported by the CodeCommit API\n try {\n const { path, repositoryName, region, commitSpecifier } = parseUrl(\n url,\n true,\n );\n const codeCommitClient = await this.buildCodeCommitClient(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n\n const input: GetFileCommandInput = {\n repositoryName: repositoryName,\n commitSpecifier: commitSpecifier,\n filePath: path,\n };\n\n options?.signal?.addEventListener('abort', () => abortController.abort());\n const getObjectCommand = new GetFileCommand(input);\n const response: GetFileCommandOutput = await codeCommitClient.send(\n getObjectCommand,\n {\n abortSignal: abortController.signal,\n },\n );\n\n if (options?.etag && options.etag === response.commitId) {\n throw new NotModifiedError();\n }\n\n return ReadUrlResponseFactory.fromReadable(\n Readable.from([response?.fileContent] || []),\n {\n etag: response.commitId,\n },\n );\n } catch (e) {\n if (e.$metadata && e.$metadata.httpStatusCode === 304) {\n throw new NotModifiedError();\n }\n if (e.name && e.name === 'NotModifiedError') {\n throw new NotModifiedError();\n }\n\n throw new ForwardedError('Could not retrieve file from CodeCommit', e);\n }\n }\n\n async readTreePath(\n codeCommitClient: CodeCommitClient,\n abortSignal: any,\n path: string,\n repositoryName: string,\n commitSpecifier?: string,\n etag?: string,\n ): Promise<string[]> {\n const getFolderCommand = new GetFolderCommand({\n folderPath: path,\n repositoryName: repositoryName,\n commitSpecifier: commitSpecifier,\n });\n const response = await codeCommitClient.send(getFolderCommand, {\n abortSignal: abortSignal,\n });\n\n if (etag && etag === response.commitId) {\n throw new NotModifiedError();\n }\n\n const output: string[] = [];\n if (response.files) {\n response.files.forEach(file => {\n if (file.absolutePath) {\n output.push(file.absolutePath);\n }\n });\n }\n if (!response.subFolders) {\n return output;\n }\n\n for (const subFolder of response.subFolders) {\n if (subFolder.absolutePath) {\n output.push(\n ...(await this.readTreePath(\n codeCommitClient,\n abortSignal,\n subFolder.absolutePath,\n repositoryName,\n commitSpecifier,\n etag,\n )),\n );\n }\n }\n return output;\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n // url: https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/test-stijn-delete-techdocs/browse?region=eu-west-1\n try {\n const { path, repositoryName, region, commitSpecifier } = parseUrl(url);\n const codeCommitClient = await this.buildCodeCommitClient(\n this.credsManager,\n region,\n this.integration,\n );\n\n const abortController = new AbortController();\n options?.signal?.addEventListener('abort', () => abortController.abort());\n\n const allFiles: string[] = await this.readTreePath(\n codeCommitClient,\n abortController.signal,\n path,\n repositoryName,\n commitSpecifier,\n options?.etag,\n );\n const responses = [];\n\n for (let i = 0; i < allFiles.length; i++) {\n const getFileCommand = new GetFileCommand({\n repositoryName: repositoryName,\n filePath: String(allFiles[i]),\n commitSpecifier: commitSpecifier,\n });\n const response = await codeCommitClient.send(getFileCommand);\n const objectData = await Readable.from([response?.fileContent] || []);\n\n responses.push({\n data: objectData,\n path: relative(\n path.startsWith('/') ? path : `/${path}`,\n allFiles[i].startsWith('/') ? allFiles[i] : `/${allFiles[i]}`,\n ),\n });\n }\n\n return await this.deps.treeResponseFactory.fromReadableArray(responses);\n } catch (e) {\n if (e.name && e.name === 'NotModifiedError') {\n throw new NotModifiedError();\n }\n throw new ForwardedError(\n 'Could not retrieve file tree from CodeCommit',\n e,\n );\n }\n }\n\n async search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('AwsCodeCommitReader does not implement search');\n }\n\n toString() {\n const secretAccessKey = this.integration.config.secretAccessKey;\n return `awsCodeCommit{host=${this.integration.config.host},authed=${Boolean(\n secretAccessKey,\n )}}`;\n }\n}\n"],"names":["repositoryName","commitSpecifier","ScmIntegrations","DefaultAwsCredentialsManager","fromTemporaryCredentials","CodeCommitClient","abortController","AbortController","GetFileCommand","NotModifiedError","ReadUrlResponseFactory","Readable","ForwardedError","GetFolderCommand","relative"],"mappings":"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"}
@@ -0,0 +1,261 @@
1
+ 'use strict';
2
+
3
+ var integrationAwsNode = require('@backstage/integration-aws-node');
4
+ var integration = require('@backstage/integration');
5
+ var errors = require('@backstage/errors');
6
+ var credentialProviders = require('@aws-sdk/credential-providers');
7
+ var clientS3 = require('@aws-sdk/client-s3');
8
+ var abortController = require('@aws-sdk/abort-controller');
9
+ var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
10
+ var stream = require('stream');
11
+ var posix = require('path/posix');
12
+
13
+ const DEFAULT_REGION = "us-east-1";
14
+ function parseUrl(url, config) {
15
+ const parsedUrl = new URL(url);
16
+ const pathname = parsedUrl.pathname.substring(1);
17
+ const host = parsedUrl.host;
18
+ if (config.host === "amazonaws.com" || config.host === "amazonaws.com.cn") {
19
+ const match = host.match(
20
+ /^(?:([a-z0-9.-]+)\.)?s3(?:[.-]([a-z0-9-]+))?\.amazonaws\.com(\.cn)?$/
21
+ );
22
+ if (!match) {
23
+ throw new Error(`Invalid AWS S3 URL ${url}`);
24
+ }
25
+ const [, hostBucket, hostRegion] = match;
26
+ if (config.s3ForcePathStyle || !hostBucket) {
27
+ const slashIndex = pathname.indexOf("/");
28
+ if (slashIndex < 0) {
29
+ throw new Error(
30
+ `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`
31
+ );
32
+ }
33
+ return {
34
+ path: pathname.substring(slashIndex + 1),
35
+ bucket: pathname.substring(0, slashIndex),
36
+ region: hostRegion ?? DEFAULT_REGION
37
+ };
38
+ }
39
+ return {
40
+ path: pathname,
41
+ bucket: hostBucket,
42
+ region: hostRegion ?? DEFAULT_REGION
43
+ };
44
+ }
45
+ const usePathStyle = config.s3ForcePathStyle || host.length === config.host.length;
46
+ if (usePathStyle) {
47
+ const slashIndex = pathname.indexOf("/");
48
+ if (slashIndex < 0) {
49
+ throw new Error(
50
+ `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`
51
+ );
52
+ }
53
+ return {
54
+ path: pathname.substring(slashIndex + 1),
55
+ bucket: pathname.substring(0, slashIndex),
56
+ region: DEFAULT_REGION
57
+ };
58
+ }
59
+ return {
60
+ path: pathname,
61
+ bucket: host.substring(0, host.length - config.host.length - 1),
62
+ region: DEFAULT_REGION
63
+ };
64
+ }
65
+ class AwsS3UrlReader {
66
+ constructor(credsManager, integration, deps) {
67
+ this.credsManager = credsManager;
68
+ this.integration = integration;
69
+ this.deps = deps;
70
+ }
71
+ static factory = ({ config, treeResponseFactory }) => {
72
+ const integrations = integration.ScmIntegrations.fromConfig(config);
73
+ const credsManager = integrationAwsNode.DefaultAwsCredentialsManager.fromConfig(config);
74
+ return integrations.awsS3.list().map((integration) => {
75
+ const reader = new AwsS3UrlReader(credsManager, integration, {
76
+ treeResponseFactory
77
+ });
78
+ const predicate = (url) => url.host.endsWith(integration.config.host);
79
+ return { reader, predicate };
80
+ });
81
+ };
82
+ /**
83
+ * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:
84
+ * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html
85
+ */
86
+ static buildStaticCredentials(accessKeyId, secretAccessKey) {
87
+ return async () => {
88
+ return {
89
+ accessKeyId,
90
+ secretAccessKey
91
+ };
92
+ };
93
+ }
94
+ static async buildCredentials(credsManager, region, integration) {
95
+ if (!integration) {
96
+ return (await credsManager.getCredentialProvider()).sdkCredentialProvider;
97
+ }
98
+ const accessKeyId = integration.config.accessKeyId;
99
+ const secretAccessKey = integration.config.secretAccessKey;
100
+ let explicitCredentials;
101
+ if (accessKeyId && secretAccessKey) {
102
+ explicitCredentials = AwsS3UrlReader.buildStaticCredentials(
103
+ accessKeyId,
104
+ secretAccessKey
105
+ );
106
+ } else {
107
+ explicitCredentials = (await credsManager.getCredentialProvider()).sdkCredentialProvider;
108
+ }
109
+ const roleArn = integration.config.roleArn;
110
+ if (roleArn) {
111
+ return credentialProviders.fromTemporaryCredentials({
112
+ masterCredentials: explicitCredentials,
113
+ params: {
114
+ RoleSessionName: "backstage-aws-s3-url-reader",
115
+ RoleArn: roleArn,
116
+ ExternalId: integration.config.externalId
117
+ },
118
+ clientConfig: { region }
119
+ });
120
+ }
121
+ return explicitCredentials;
122
+ }
123
+ async buildS3Client(credsManager, region, integration) {
124
+ const credentials = await AwsS3UrlReader.buildCredentials(
125
+ credsManager,
126
+ region,
127
+ integration
128
+ );
129
+ const s3 = new clientS3.S3Client({
130
+ customUserAgent: "backstage-aws-s3-url-reader",
131
+ region,
132
+ credentials,
133
+ endpoint: integration.config.endpoint,
134
+ forcePathStyle: integration.config.s3ForcePathStyle
135
+ });
136
+ return s3;
137
+ }
138
+ async retrieveS3ObjectData(stream$1) {
139
+ return new Promise((resolve, reject) => {
140
+ try {
141
+ const chunks = [];
142
+ stream$1.on("data", (chunk) => chunks.push(chunk));
143
+ stream$1.on(
144
+ "error",
145
+ (e) => reject(new errors.ForwardedError("Unable to read stream", e))
146
+ );
147
+ stream$1.on("end", () => resolve(stream.Readable.from(Buffer.concat(chunks))));
148
+ } catch (e) {
149
+ throw new errors.ForwardedError("Unable to parse the response data", e);
150
+ }
151
+ });
152
+ }
153
+ async read(url) {
154
+ const response = await this.readUrl(url);
155
+ return response.buffer();
156
+ }
157
+ async readUrl(url, options) {
158
+ const { etag, lastModifiedAfter } = options ?? {};
159
+ try {
160
+ const { path, bucket, region } = parseUrl(url, this.integration.config);
161
+ const s3Client = await this.buildS3Client(
162
+ this.credsManager,
163
+ region,
164
+ this.integration
165
+ );
166
+ const abortController$1 = new abortController.AbortController();
167
+ const params = {
168
+ Bucket: bucket,
169
+ Key: path,
170
+ ...etag && { IfNoneMatch: etag },
171
+ ...lastModifiedAfter && {
172
+ IfModifiedSince: lastModifiedAfter
173
+ }
174
+ };
175
+ options?.signal?.addEventListener("abort", () => abortController$1.abort());
176
+ const getObjectCommand = new clientS3.GetObjectCommand(params);
177
+ const response = await s3Client.send(getObjectCommand, {
178
+ abortSignal: abortController$1.signal
179
+ });
180
+ const s3ObjectData = await this.retrieveS3ObjectData(
181
+ response.Body
182
+ );
183
+ return ReadUrlResponseFactory.ReadUrlResponseFactory.fromReadable(s3ObjectData, {
184
+ etag: response.ETag,
185
+ lastModifiedAt: response.LastModified
186
+ });
187
+ } catch (e) {
188
+ if (e.$metadata && e.$metadata.httpStatusCode === 304) {
189
+ throw new errors.NotModifiedError();
190
+ }
191
+ throw new errors.ForwardedError("Could not retrieve file from S3", e);
192
+ }
193
+ }
194
+ async readTree(url, options) {
195
+ try {
196
+ const { path, bucket, region } = parseUrl(url, this.integration.config);
197
+ const s3Client = await this.buildS3Client(
198
+ this.credsManager,
199
+ region,
200
+ this.integration
201
+ );
202
+ const abortController$1 = new abortController.AbortController();
203
+ const allObjects = [];
204
+ const responses = [];
205
+ let continuationToken;
206
+ let output;
207
+ do {
208
+ const listObjectsV2Command = new clientS3.ListObjectsV2Command({
209
+ Bucket: bucket,
210
+ ContinuationToken: continuationToken,
211
+ Prefix: path
212
+ });
213
+ options?.signal?.addEventListener(
214
+ "abort",
215
+ () => abortController$1.abort()
216
+ );
217
+ output = await s3Client.send(listObjectsV2Command, {
218
+ abortSignal: abortController$1.signal
219
+ });
220
+ if (output.Contents) {
221
+ output.Contents.forEach((contents) => {
222
+ allObjects.push(contents.Key);
223
+ });
224
+ }
225
+ continuationToken = output.NextContinuationToken;
226
+ } while (continuationToken);
227
+ for (let i = 0; i < allObjects.length; i++) {
228
+ const getObjectCommand = new clientS3.GetObjectCommand({
229
+ Bucket: bucket,
230
+ Key: String(allObjects[i])
231
+ });
232
+ const response = await s3Client.send(getObjectCommand);
233
+ const s3ObjectData = await this.retrieveS3ObjectData(
234
+ response.Body
235
+ );
236
+ responses.push({
237
+ data: s3ObjectData,
238
+ path: posix.relative(path, String(allObjects[i])),
239
+ lastModifiedAt: response?.LastModified ?? void 0
240
+ });
241
+ }
242
+ return await this.deps.treeResponseFactory.fromReadableArray(responses);
243
+ } catch (e) {
244
+ throw new errors.ForwardedError("Could not retrieve file tree from S3", e);
245
+ }
246
+ }
247
+ async search() {
248
+ throw new Error("AwsS3Reader does not implement search");
249
+ }
250
+ toString() {
251
+ const secretAccessKey = this.integration.config.secretAccessKey;
252
+ return `awsS3{host=${this.integration.config.host},authed=${Boolean(
253
+ secretAccessKey
254
+ )}}`;
255
+ }
256
+ }
257
+
258
+ exports.AwsS3UrlReader = AwsS3UrlReader;
259
+ exports.DEFAULT_REGION = DEFAULT_REGION;
260
+ exports.parseUrl = parseUrl;
261
+ //# sourceMappingURL=AwsS3UrlReader.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AwsS3UrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/AwsS3UrlReader.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport {\n AwsS3Integration,\n ScmIntegrations,\n AwsS3IntegrationConfig,\n} from '@backstage/integration';\nimport { ForwardedError, NotModifiedError } from '@backstage/errors';\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport { AwsCredentialIdentityProvider } from '@aws-sdk/types';\nimport {\n S3Client,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n GetObjectCommand,\n GetObjectCommandInput,\n} from '@aws-sdk/client-s3';\nimport { AbortController } from '@aws-sdk/abort-controller';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { Readable } from 'stream';\nimport { relative } from 'path/posix';\n\nexport const DEFAULT_REGION = 'us-east-1';\n\n/**\n * Path style URLs: https://s3.(region).amazonaws.com/(bucket)/(key)\n * The region can also be on the old form: https://s3-(region).amazonaws.com/(bucket)/(key)\n * Virtual hosted style URLs: https://(bucket).s3.(region).amazonaws.com/(key)\n * See https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access\n */\nexport function parseUrl(\n url: string,\n config: AwsS3IntegrationConfig,\n): { path: string; bucket: string; region: string } {\n const parsedUrl = new URL(url);\n\n /**\n * Removes the leading '/' from the pathname to be processed\n * as a parameter by AWS S3 SDK getObject method.\n */\n const pathname = parsedUrl.pathname.substring(1);\n const host = parsedUrl.host;\n\n // Treat Amazon hosted separately because it has special region logic\n if (config.host === 'amazonaws.com' || config.host === 'amazonaws.com.cn') {\n const match = host.match(\n /^(?:([a-z0-9.-]+)\\.)?s3(?:[.-]([a-z0-9-]+))?\\.amazonaws\\.com(\\.cn)?$/,\n );\n if (!match) {\n throw new Error(`Invalid AWS S3 URL ${url}`);\n }\n\n const [, hostBucket, hostRegion] = match;\n\n if (config.s3ForcePathStyle || !hostBucket) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: hostBucket,\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n const usePathStyle =\n config.s3ForcePathStyle || host.length === config.host.length;\n\n if (usePathStyle) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: host.substring(0, host.length - config.host.length - 1),\n region: DEFAULT_REGION,\n };\n}\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for AWS S3 buckets.\n *\n * @public\n */\nexport class AwsS3UrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n const credsManager = DefaultAwsCredentialsManager.fromConfig(config);\n\n return integrations.awsS3.list().map(integration => {\n const reader = new AwsS3UrlReader(credsManager, integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) =>\n url.host.endsWith(integration.config.host);\n return { reader, predicate };\n });\n };\n\n constructor(\n private readonly credsManager: AwsCredentialsManager,\n private readonly integration: AwsS3Integration,\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {}\n\n /**\n * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:\n * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html\n */\n private static buildStaticCredentials(\n accessKeyId: string,\n secretAccessKey: string,\n ): AwsCredentialIdentityProvider {\n return async () => {\n return {\n accessKeyId,\n secretAccessKey,\n };\n };\n }\n\n private static async buildCredentials(\n credsManager: AwsCredentialsManager,\n region: string,\n integration?: AwsS3Integration,\n ): Promise<AwsCredentialIdentityProvider> {\n // Fall back to the default credential chain if neither account ID\n // nor explicit credentials are provided\n if (!integration) {\n return (await credsManager.getCredentialProvider()).sdkCredentialProvider;\n }\n\n const accessKeyId = integration.config.accessKeyId;\n const secretAccessKey = integration.config.secretAccessKey;\n let explicitCredentials: AwsCredentialIdentityProvider;\n if (accessKeyId && secretAccessKey) {\n explicitCredentials = AwsS3UrlReader.buildStaticCredentials(\n accessKeyId,\n secretAccessKey,\n );\n } else {\n explicitCredentials = (await credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const roleArn = integration.config.roleArn;\n if (roleArn) {\n return fromTemporaryCredentials({\n masterCredentials: explicitCredentials,\n params: {\n RoleSessionName: 'backstage-aws-s3-url-reader',\n RoleArn: roleArn,\n ExternalId: integration.config.externalId,\n },\n clientConfig: { region },\n });\n }\n\n return explicitCredentials;\n }\n\n private async buildS3Client(\n credsManager: AwsCredentialsManager,\n region: string,\n integration: AwsS3Integration,\n ): Promise<S3Client> {\n const credentials = await AwsS3UrlReader.buildCredentials(\n credsManager,\n region,\n integration,\n );\n\n const s3 = new S3Client({\n customUserAgent: 'backstage-aws-s3-url-reader',\n region: region,\n credentials: credentials,\n endpoint: integration.config.endpoint,\n forcePathStyle: integration.config.s3ForcePathStyle,\n });\n return s3;\n }\n\n private async retrieveS3ObjectData(stream: Readable): Promise<Readable> {\n return new Promise((resolve, reject) => {\n try {\n const chunks: any[] = [];\n stream.on('data', chunk => chunks.push(chunk));\n stream.on('error', (e: Error) =>\n reject(new ForwardedError('Unable to read stream', e)),\n );\n stream.on('end', () => resolve(Readable.from(Buffer.concat(chunks))));\n } catch (e) {\n throw new ForwardedError('Unable to parse the response data', e);\n }\n });\n }\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter } = options ?? {};\n\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n\n const params: GetObjectCommandInput = {\n Bucket: bucket,\n Key: path,\n ...(etag && { IfNoneMatch: etag }),\n ...(lastModifiedAfter && {\n IfModifiedSince: lastModifiedAfter,\n }),\n };\n\n options?.signal?.addEventListener('abort', () => abortController.abort());\n const getObjectCommand = new GetObjectCommand(params);\n const response = await s3Client.send(getObjectCommand, {\n abortSignal: abortController.signal,\n });\n\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n return ReadUrlResponseFactory.fromReadable(s3ObjectData, {\n etag: response.ETag,\n lastModifiedAt: response.LastModified,\n });\n } catch (e) {\n if (e.$metadata && e.$metadata.httpStatusCode === 304) {\n throw new NotModifiedError();\n }\n\n throw new ForwardedError('Could not retrieve file from S3', e);\n }\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n const allObjects: String[] = [];\n const responses = [];\n let continuationToken: string | undefined;\n let output: ListObjectsV2CommandOutput;\n do {\n const listObjectsV2Command = new ListObjectsV2Command({\n Bucket: bucket,\n ContinuationToken: continuationToken,\n Prefix: path,\n });\n options?.signal?.addEventListener('abort', () =>\n abortController.abort(),\n );\n output = await s3Client.send(listObjectsV2Command, {\n abortSignal: abortController.signal,\n });\n if (output.Contents) {\n output.Contents.forEach(contents => {\n allObjects.push(contents.Key!);\n });\n }\n continuationToken = output.NextContinuationToken;\n } while (continuationToken);\n\n for (let i = 0; i < allObjects.length; i++) {\n const getObjectCommand = new GetObjectCommand({\n Bucket: bucket,\n Key: String(allObjects[i]),\n });\n const response = await s3Client.send(getObjectCommand);\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n responses.push({\n data: s3ObjectData,\n path: relative(path, String(allObjects[i])),\n lastModifiedAt: response?.LastModified ?? undefined,\n });\n }\n\n return await this.deps.treeResponseFactory.fromReadableArray(responses);\n } catch (e) {\n throw new ForwardedError('Could not retrieve file tree from S3', e);\n }\n }\n\n async search(): Promise<UrlReaderServiceSearchResponse> {\n throw new Error('AwsS3Reader does not implement search');\n }\n\n toString() {\n const secretAccessKey = this.integration.config.secretAccessKey;\n return `awsS3{host=${this.integration.config.host},authed=${Boolean(\n secretAccessKey,\n )}}`;\n }\n}\n"],"names":["ScmIntegrations","DefaultAwsCredentialsManager","fromTemporaryCredentials","S3Client","stream","ForwardedError","Readable","abortController","AbortController","GetObjectCommand","ReadUrlResponseFactory","NotModifiedError","ListObjectsV2Command","relative"],"mappings":"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"}