@backstage/backend-defaults 0.11.0-next.2 → 0.11.1-next.0

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 (45) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/config.d.ts +86 -0
  3. package/dist/CreateBackend.cjs.js +5 -5
  4. package/dist/CreateBackend.cjs.js.map +1 -1
  5. package/dist/alpha/entrypoints/actions/DefaultActionsService.cjs.js.map +1 -0
  6. package/dist/{entrypoints → alpha/entrypoints}/actions/actionsServiceFactory.cjs.js +2 -1
  7. package/dist/alpha/entrypoints/actions/actionsServiceFactory.cjs.js.map +1 -0
  8. package/dist/{entrypoints → alpha/entrypoints}/actionsRegistry/DefaultActionsRegistryService.cjs.js +9 -2
  9. package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -0
  10. package/dist/{entrypoints → alpha/entrypoints}/actionsRegistry/actionsRegistryServiceFactory.cjs.js +2 -1
  11. package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -0
  12. package/dist/alpha.cjs.js +10 -0
  13. package/dist/alpha.cjs.js.map +1 -0
  14. package/dist/alpha.d.ts +14 -0
  15. package/dist/entrypoints/auth/helpers.cjs.js +111 -33
  16. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
  17. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js +23 -0
  18. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js.map +1 -0
  19. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js +2 -0
  20. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
  21. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js +31 -0
  22. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
  23. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +1 -0
  24. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
  25. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +6 -4
  26. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
  27. package/dist/lib/RateLimitStoreFactory.cjs.js +37 -0
  28. package/dist/lib/RateLimitStoreFactory.cjs.js.map +1 -0
  29. package/dist/lib/rateLimitMiddleware.cjs.js +62 -0
  30. package/dist/lib/rateLimitMiddleware.cjs.js.map +1 -0
  31. package/dist/package.json.cjs.js +7 -9
  32. package/dist/package.json.cjs.js.map +1 -1
  33. package/dist/rootHttpRouter.d.ts +11 -0
  34. package/package.json +20 -26
  35. package/dist/actions.cjs.js +0 -8
  36. package/dist/actions.cjs.js.map +0 -1
  37. package/dist/actions.d.ts +0 -8
  38. package/dist/actionsRegistry.cjs.js +0 -8
  39. package/dist/actionsRegistry.cjs.js.map +0 -1
  40. package/dist/actionsRegistry.d.ts +0 -8
  41. package/dist/entrypoints/actions/DefaultActionsService.cjs.js.map +0 -1
  42. package/dist/entrypoints/actions/actionsServiceFactory.cjs.js.map +0 -1
  43. package/dist/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +0 -1
  44. package/dist/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +0 -1
  45. /package/dist/{entrypoints → alpha/entrypoints}/actions/DefaultActionsService.cjs.js +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,75 @@
1
1
  # @backstage/backend-defaults
2
2
 
3
+ ## 0.11.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - ead925a: Add a standard `toString` on credentials objects
8
+ - e0189b8: UrlReader: Fix handling of access tokens for GitLab readURL requests
9
+ - d1e4a6d: Fixed bug where the GitLab user token and GitLab integration token were being merged together
10
+ - Updated dependencies
11
+ - @backstage/integration@1.17.1-next.0
12
+ - @backstage/backend-app-api@1.2.4
13
+ - @backstage/plugin-auth-node@0.6.4
14
+ - @backstage/plugin-permission-node@0.10.1
15
+ - @backstage/backend-plugin-api@1.4.0
16
+ - @backstage/cli-node@0.2.13
17
+ - @backstage/config-loader@1.10.1
18
+ - @backstage/plugin-events-node@0.4.12
19
+ - @backstage/backend-dev-utils@0.1.5
20
+ - @backstage/config@1.3.2
21
+ - @backstage/errors@1.2.7
22
+ - @backstage/integration-aws-node@0.1.16
23
+ - @backstage/types@1.2.1
24
+
25
+ ## 0.11.0
26
+
27
+ ### Minor Changes
28
+
29
+ - 3ccb7fc: Enhanced error handling in the auditor service factory to pass errors as objects. Aligned WinstonRootAuditorService with the default service factory's error handling.
30
+
31
+ ### Patch Changes
32
+
33
+ - 1220cf8: Added new rate limit middleware to allow rate limiting requests to the backend
34
+
35
+ If you are using the `configure` callback of the root HTTP router service and do NOT call `applyDefaults()` inside it, please see [the relevant changes](https://github.com/backstage/backstage/pull/28708/files#diff-86ad1b6a694dd250823aee39d410428dd837c9d9a04ca8c33bd1081fbe3f22af) that were made, to see if you want to apply them as well to your custom configuration.
36
+ Rate limiting can be turned on by adding the following configuration to `app-config.yaml`:
37
+
38
+ ```yaml
39
+ backend:
40
+ rateLimit:
41
+ window: 6s
42
+ incomingRequestLimit: 100
43
+ ```
44
+
45
+ Plugin specific rate limiting can be configured by adding the following configuration to `app-config.yaml`:
46
+
47
+ ```yaml
48
+ backend:
49
+ rateLimit:
50
+ global: false # This will disable the global rate limiting
51
+ plugin:
52
+ catalog:
53
+ window: 6s
54
+ incomingRequestLimit: 100
55
+ ```
56
+
57
+ - c999c25: Added some default implementations for the experimental `ActionsService` and `ActionsRegistryService` under `/alpha` that allow registration of actions for a particular plugin.
58
+ - Updated dependencies
59
+ - @backstage/plugin-auth-node@0.6.4
60
+ - @backstage/backend-app-api@1.2.4
61
+ - @backstage/backend-plugin-api@1.4.0
62
+ - @backstage/backend-dev-utils@0.1.5
63
+ - @backstage/cli-node@0.2.13
64
+ - @backstage/config@1.3.2
65
+ - @backstage/config-loader@1.10.1
66
+ - @backstage/errors@1.2.7
67
+ - @backstage/integration@1.17.0
68
+ - @backstage/integration-aws-node@0.1.16
69
+ - @backstage/types@1.2.1
70
+ - @backstage/plugin-events-node@0.4.12
71
+ - @backstage/plugin-permission-node@0.10.1
72
+
3
73
  ## 0.11.0-next.2
4
74
 
5
75
  ### Minor Changes
package/config.d.ts CHANGED
@@ -790,6 +790,92 @@ export interface Config {
790
790
  headers?: { [name: string]: string };
791
791
  };
792
792
 
793
+ /**
794
+ * Rate limiting options. Defining this as `true` will enable rate limiting with default values.
795
+ */
796
+ rateLimit?:
797
+ | true
798
+ | {
799
+ store?:
800
+ | {
801
+ type: 'redis';
802
+ connection: string;
803
+ }
804
+ | {
805
+ type: 'memory';
806
+ };
807
+ /**
808
+ * Enable/disable global rate limiting. If this is disabled, plugin specific rate limiting must be
809
+ * used.
810
+ */
811
+ global?: boolean;
812
+ /**
813
+ * Time frame in milliseconds or as human duration for which requests are checked/remembered.
814
+ * Defaults to one minute.
815
+ */
816
+ window?: string | HumanDuration;
817
+ /**
818
+ * The maximum number of connections to allow during the `window` before rate limiting the client.
819
+ * Defaults to 5.
820
+ */
821
+ incomingRequestLimit?: number;
822
+ /**
823
+ * Whether to pass requests in case of store failure.
824
+ * Defaults to false.
825
+ */
826
+ passOnStoreError?: boolean;
827
+ /**
828
+ * List of allowed IP addresses that are not rate limited.
829
+ * Defaults to [127.0.0.1, 0:0:0:0:0:0:0:1, ::1].
830
+ */
831
+ ipAllowList?: string[];
832
+ /**
833
+ * Skip rate limiting for requests that have been successful.
834
+ * Defaults to false.
835
+ */
836
+ skipSuccessfulRequests?: boolean;
837
+ /**
838
+ * Skip rate limiting for requests that have failed.
839
+ * Defaults to false.
840
+ */
841
+ skipFailedRequests?: boolean;
842
+ /** Plugin specific rate limiting configuration */
843
+ plugin?: {
844
+ [pluginId: string]: {
845
+ /**
846
+ * Time frame in milliseconds or as human duration for which requests are checked/remembered.
847
+ * Defaults to one minute.
848
+ */
849
+ window?: string | HumanDuration;
850
+ /**
851
+ * The maximum number of connections to allow during the `window` before rate limiting the client.
852
+ * Defaults to 5.
853
+ */
854
+ incomingRequestLimit?: number;
855
+ /**
856
+ * Whether to pass requests in case of store failure.
857
+ * Defaults to false.
858
+ */
859
+ passOnStoreError?: boolean;
860
+ /**
861
+ * List of allowed IP addresses that are not rate limited.
862
+ * Defaults to [127.0.0.1, 0:0:0:0:0:0:0:1, ::1].
863
+ */
864
+ ipAllowList?: string[];
865
+ /**
866
+ * Skip rate limiting for requests that have been successful.
867
+ * Defaults to false.
868
+ */
869
+ skipSuccessfulRequests?: boolean;
870
+ /**
871
+ * Skip rate limiting for requests that have failed.
872
+ * Defaults to false.
873
+ */
874
+ skipFailedRequests?: boolean;
875
+ };
876
+ };
877
+ };
878
+
793
879
  /**
794
880
  * Configuration related to URL reading, used for example for reading catalog info
795
881
  * files, scaffolder templates, and techdocs content.
@@ -21,12 +21,9 @@ var scheduler = require('@backstage/backend-defaults/scheduler');
21
21
  var urlReader = require('@backstage/backend-defaults/urlReader');
22
22
  var userInfo = require('@backstage/backend-defaults/userInfo');
23
23
  var pluginEventsNode = require('@backstage/plugin-events-node');
24
- var actionsRegistryServiceFactory = require('./entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js');
25
- var actionsServiceFactory = require('./entrypoints/actions/actionsServiceFactory.cjs.js');
24
+ var alpha = require('@backstage/backend-defaults/alpha');
26
25
 
27
26
  const defaultServiceFactories = [
28
- actionsRegistryServiceFactory.actionsRegistryServiceFactory,
29
- actionsServiceFactory.actionsServiceFactory,
30
27
  auditor.auditorServiceFactory,
31
28
  auth.authServiceFactory,
32
29
  cache.cacheServiceFactory,
@@ -46,7 +43,10 @@ const defaultServiceFactories = [
46
43
  scheduler.schedulerServiceFactory,
47
44
  userInfo.userInfoServiceFactory,
48
45
  urlReader.urlReaderServiceFactory,
49
- pluginEventsNode.eventsServiceFactory
46
+ pluginEventsNode.eventsServiceFactory,
47
+ // alpha services
48
+ alpha.actionsRegistryServiceFactory,
49
+ alpha.actionsServiceFactory
50
50
  ];
51
51
  function createBackend() {
52
52
  return backendAppApi.createSpecializedBackend({ defaultServiceFactories });
@@ -1 +1 @@
1
- {"version":3,"file":"CreateBackend.cjs.js","sources":["../src/CreateBackend.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport { auditorServiceFactory } from '@backstage/backend-defaults/auditor';\nimport { authServiceFactory } from '@backstage/backend-defaults/auth';\nimport { cacheServiceFactory } from '@backstage/backend-defaults/cache';\nimport { databaseServiceFactory } from '@backstage/backend-defaults/database';\nimport { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';\nimport { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';\nimport { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';\nimport { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';\nimport { loggerServiceFactory } from '@backstage/backend-defaults/logger';\nimport { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';\nimport { permissionsRegistryServiceFactory } from '@backstage/backend-defaults/permissionsRegistry';\nimport { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';\nimport { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';\nimport { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';\nimport { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';\nimport { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';\nimport { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';\nimport { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo';\nimport { eventsServiceFactory } from '@backstage/plugin-events-node';\nimport { actionsRegistryServiceFactory } from './entrypoints/actionsRegistry';\nimport { actionsServiceFactory } from './entrypoints/actions';\n\nexport const defaultServiceFactories = [\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n auditorServiceFactory,\n authServiceFactory,\n cacheServiceFactory,\n rootConfigServiceFactory,\n databaseServiceFactory,\n discoveryServiceFactory,\n httpAuthServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n permissionsRegistryServiceFactory,\n rootHealthServiceFactory,\n rootHttpRouterServiceFactory,\n rootLifecycleServiceFactory,\n rootLoggerServiceFactory,\n schedulerServiceFactory,\n userInfoServiceFactory,\n urlReaderServiceFactory,\n eventsServiceFactory,\n];\n\n/**\n * @public\n */\nexport function createBackend(): Backend {\n return createSpecializedBackend({ defaultServiceFactories });\n}\n"],"names":["actionsRegistryServiceFactory","actionsServiceFactory","auditorServiceFactory","authServiceFactory","cacheServiceFactory","rootConfigServiceFactory","databaseServiceFactory","discoveryServiceFactory","httpAuthServiceFactory","httpRouterServiceFactory","lifecycleServiceFactory","loggerServiceFactory","permissionsServiceFactory","permissionsRegistryServiceFactory","rootHealthServiceFactory","rootHttpRouterServiceFactory","rootLifecycleServiceFactory","rootLoggerServiceFactory","schedulerServiceFactory","userInfoServiceFactory","urlReaderServiceFactory","eventsServiceFactory","createSpecializedBackend"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwCO,MAAM,uBAA0B,GAAA;AAAA,EACrCA,2DAAA;AAAA,EACAC,2CAAA;AAAA,EACAC,6BAAA;AAAA,EACAC,uBAAA;AAAA,EACAC,yBAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,2BAAA;AAAA,EACAC,qCAAA;AAAA,EACAC,qDAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,2CAAA;AAAA,EACAC,yCAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC;AACF;AAKO,SAAS,aAAyB,GAAA;AACvC,EAAO,OAAAC,sCAAA,CAAyB,EAAE,uBAAA,EAAyB,CAAA;AAC7D;;;;;"}
1
+ {"version":3,"file":"CreateBackend.cjs.js","sources":["../src/CreateBackend.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport { auditorServiceFactory } from '@backstage/backend-defaults/auditor';\nimport { authServiceFactory } from '@backstage/backend-defaults/auth';\nimport { cacheServiceFactory } from '@backstage/backend-defaults/cache';\nimport { databaseServiceFactory } from '@backstage/backend-defaults/database';\nimport { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';\nimport { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';\nimport { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';\nimport { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';\nimport { loggerServiceFactory } from '@backstage/backend-defaults/logger';\nimport { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';\nimport { permissionsRegistryServiceFactory } from '@backstage/backend-defaults/permissionsRegistry';\nimport { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';\nimport { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';\nimport { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';\nimport { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';\nimport { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';\nimport { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';\nimport { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo';\nimport { eventsServiceFactory } from '@backstage/plugin-events-node';\nimport {\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n} from '@backstage/backend-defaults/alpha';\n\nexport const defaultServiceFactories = [\n auditorServiceFactory,\n authServiceFactory,\n cacheServiceFactory,\n rootConfigServiceFactory,\n databaseServiceFactory,\n discoveryServiceFactory,\n httpAuthServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n permissionsRegistryServiceFactory,\n rootHealthServiceFactory,\n rootHttpRouterServiceFactory,\n rootLifecycleServiceFactory,\n rootLoggerServiceFactory,\n schedulerServiceFactory,\n userInfoServiceFactory,\n urlReaderServiceFactory,\n eventsServiceFactory,\n\n // alpha services\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n];\n\n/**\n * @public\n */\nexport function createBackend(): Backend {\n return createSpecializedBackend({ defaultServiceFactories });\n}\n"],"names":["auditorServiceFactory","authServiceFactory","cacheServiceFactory","rootConfigServiceFactory","databaseServiceFactory","discoveryServiceFactory","httpAuthServiceFactory","httpRouterServiceFactory","lifecycleServiceFactory","loggerServiceFactory","permissionsServiceFactory","permissionsRegistryServiceFactory","rootHealthServiceFactory","rootHttpRouterServiceFactory","rootLifecycleServiceFactory","rootLoggerServiceFactory","schedulerServiceFactory","userInfoServiceFactory","urlReaderServiceFactory","eventsServiceFactory","actionsRegistryServiceFactory","actionsServiceFactory","createSpecializedBackend"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA0CO,MAAM,uBAA0B,GAAA;AAAA,EACrCA,6BAAA;AAAA,EACAC,uBAAA;AAAA,EACAC,yBAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,2BAAA;AAAA,EACAC,qCAAA;AAAA,EACAC,qDAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,2CAAA;AAAA,EACAC,yCAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,qCAAA;AAAA;AAAA,EAGAC,mCAAA;AAAA,EACAC;AACF;AAKO,SAAS,aAAyB,GAAA;AACvC,EAAO,OAAAC,sCAAA,CAAyB,EAAE,uBAAA,EAAyB,CAAA;AAC7D;;;;;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultActionsService.cjs.js","sources":["../../../../src/alpha/entrypoints/actions/DefaultActionsService.ts"],"sourcesContent":["/*\n * Copyright 2025 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 */\nimport {\n AuthService,\n BackstageCredentials,\n DiscoveryService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport {\n ActionsService,\n ActionsServiceAction,\n} from '@backstage/backend-plugin-api/alpha';\n\nexport class DefaultActionsService implements ActionsService {\n private constructor(\n private readonly discovery: DiscoveryService,\n private readonly config: RootConfigService,\n private readonly logger: LoggerService,\n private readonly auth: AuthService,\n ) {}\n\n static create({\n discovery,\n config,\n logger,\n auth,\n }: {\n discovery: DiscoveryService;\n config: RootConfigService;\n logger: LoggerService;\n auth: AuthService;\n }) {\n return new DefaultActionsService(discovery, config, logger, auth);\n }\n\n async list({ credentials }: { credentials: BackstageCredentials }) {\n const pluginSources =\n this.config.getOptionalStringArray('backend.actions.pluginSources') ?? [];\n\n const remoteActionsList = await Promise.all(\n pluginSources.map(async source => {\n try {\n const response = await this.makeRequest({\n path: `/.backstage/actions/v1/actions`,\n pluginId: source,\n credentials,\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const { actions } = (await response.json()) as {\n actions: ActionsServiceAction;\n };\n\n return actions;\n } catch (error) {\n this.logger.warn(`Failed to fetch actions from ${source}`, error);\n return [];\n }\n }),\n );\n\n return { actions: remoteActionsList.flat() };\n }\n\n async invoke(opts: {\n id: string;\n input?: JsonObject;\n credentials: BackstageCredentials;\n }) {\n const pluginId = this.pluginIdFromActionId(opts.id);\n const response = await this.makeRequest({\n path: `/.backstage/actions/v1/actions/${encodeURIComponent(\n opts.id,\n )}/invoke`,\n pluginId,\n credentials: opts.credentials,\n options: {\n method: 'POST',\n body: JSON.stringify(opts.input),\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { output } = await response.json();\n return { output };\n }\n\n private async makeRequest(opts: {\n path: string;\n pluginId: string;\n options?: RequestInit;\n credentials: BackstageCredentials;\n }) {\n const { path, pluginId, credentials, options } = opts;\n const baseUrl = await this.discovery.getBaseUrl(pluginId);\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: opts.pluginId,\n });\n\n return fetch(`${baseUrl}${path}`, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${token}`,\n },\n });\n }\n\n private pluginIdFromActionId(id: string): string {\n const colonIndex = id.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid action id: ${id}`);\n }\n return id.substring(0, colonIndex);\n }\n}\n"],"names":["ResponseError"],"mappings":"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"}
@@ -2,9 +2,10 @@
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var DefaultActionsService = require('./DefaultActionsService.cjs.js');
5
+ var alpha = require('@backstage/backend-plugin-api/alpha');
5
6
 
6
7
  const actionsServiceFactory = backendPluginApi.createServiceFactory({
7
- service: backendPluginApi.coreServices.actions,
8
+ service: alpha.actionsServiceRef,
8
9
  deps: {
9
10
  discovery: backendPluginApi.coreServices.discovery,
10
11
  config: backendPluginApi.coreServices.rootConfig,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionsServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actions/actionsServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2025 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 */\nimport { createServiceFactory } from '@backstage/backend-plugin-api';\nimport { coreServices } from '@backstage/backend-plugin-api';\nimport { DefaultActionsService } from './DefaultActionsService';\nimport { actionsServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsServiceFactory = createServiceFactory({\n service: actionsServiceRef,\n deps: {\n discovery: coreServices.discovery,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({ discovery, config, logger, auth }) =>\n DefaultActionsService.create({\n discovery,\n config,\n logger,\n auth,\n }),\n});\n"],"names":["createServiceFactory","actionsServiceRef","coreServices","DefaultActionsService"],"mappings":";;;;;;AAuBO,MAAM,wBAAwBA,qCAAqB,CAAA;AAAA,EACxD,OAAS,EAAAC,uBAAA;AAAA,EACT,IAAM,EAAA;AAAA,IACJ,WAAWC,6BAAa,CAAA,SAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,MAAMA,6BAAa,CAAA;AAAA,GACrB;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,SAAA,EAAW,QAAQ,MAAQ,EAAA,IAAA,EACrC,KAAAC,2CAAA,CAAsB,MAAO,CAAA;AAAA,IAC3B,SAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD;AACL,CAAC;;;;"}
@@ -35,9 +35,16 @@ class DefaultActionsRegistryService {
35
35
  actions: Array.from(this.actions.entries()).map(([id, action]) => ({
36
36
  id,
37
37
  ...action,
38
+ attributes: {
39
+ // Inspired by the @modelcontextprotocol/sdk defaults for the hints.
40
+ // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812
41
+ destructive: action.attributes?.destructive ?? true,
42
+ idempotent: action.attributes?.idempotent ?? false,
43
+ readOnly: action.attributes?.readOnly ?? false
44
+ },
38
45
  schema: {
39
- input: action.schema?.input ? zodToJsonSchema__default.default(action.schema.input(zod.z)) : zodToJsonSchema__default.default(zod.z.any()),
40
- output: action.schema?.output ? zodToJsonSchema__default.default(action.schema.output(zod.z)) : zodToJsonSchema__default.default(zod.z.any())
46
+ input: action.schema?.input ? zodToJsonSchema__default.default(action.schema.input(zod.z)) : zodToJsonSchema__default.default(zod.z.object({})),
47
+ output: action.schema?.output ? zodToJsonSchema__default.default(action.schema.output(zod.z)) : zodToJsonSchema__default.default(zod.z.object({}))
41
48
  }
42
49
  }))
43
50
  });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 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 AuthService,\n HttpAuthService,\n LoggerService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport {\n ForwardedError,\n InputError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any>> =\n new Map();\n\n private constructor(\n private readonly logger: LoggerService,\n private readonly httpAuth: HttpAuthService,\n private readonly auth: AuthService,\n private readonly metadata: PluginMetadataService,\n ) {}\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(logger, httpAuth, auth, metadata);\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use(json());\n\n router.get('/.backstage/actions/v1/actions', (_, res) => {\n return res.json({\n actions: Array.from(this.actions.entries()).map(([id, action]) => ({\n id,\n ...action,\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n },\n })),\n });\n });\n\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'user')) {\n if (!credentials.principal.actor) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not a user`,\n );\n }\n } else if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(req.body)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n try {\n const result = await action.action({\n input: input.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n } catch (error) {\n throw new ForwardedError(\n `Failed execution of action \"${req.params.actionId}\"`,\n error,\n );\n }\n },\n );\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n >(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n this.actions.set(id, options);\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","InputError","ForwardedError"],"mappings":"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"}
@@ -2,9 +2,10 @@
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var DefaultActionsRegistryService = require('./DefaultActionsRegistryService.cjs.js');
5
+ var alpha = require('@backstage/backend-plugin-api/alpha');
5
6
 
6
7
  const actionsRegistryServiceFactory = backendPluginApi.createServiceFactory({
7
- service: backendPluginApi.coreServices.actionsRegistry,
8
+ service: alpha.actionsRegistryServiceRef,
8
9
  deps: {
9
10
  metadata: backendPluginApi.coreServices.pluginMetadata,
10
11
  httpRouter: backendPluginApi.coreServices.httpRouter,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionsRegistryServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2025 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 coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { DefaultActionsRegistryService } from './DefaultActionsRegistryService';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsRegistryServiceFactory = createServiceFactory({\n service: actionsRegistryServiceRef,\n deps: {\n metadata: coreServices.pluginMetadata,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({ metadata, httpRouter, httpAuth, logger, auth }) => {\n const actionsRegistryService = DefaultActionsRegistryService.create({\n httpAuth,\n logger,\n auth,\n metadata,\n });\n\n httpRouter.use(actionsRegistryService.createRouter());\n\n return actionsRegistryService;\n },\n});\n"],"names":["createServiceFactory","actionsRegistryServiceRef","coreServices","DefaultActionsRegistryService"],"mappings":";;;;;;AA0BO,MAAM,gCAAgCA,qCAAqB,CAAA;AAAA,EAChE,OAAS,EAAAC,+BAAA;AAAA,EACT,IAAM,EAAA;AAAA,IACJ,UAAUC,6BAAa,CAAA,cAAA;AAAA,IACvB,YAAYA,6BAAa,CAAA,UAAA;AAAA,IACzB,UAAUA,6BAAa,CAAA,QAAA;AAAA,IACvB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,MAAMA,6BAAa,CAAA;AAAA,GACrB;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,QAAA,EAAU,YAAY,QAAU,EAAA,MAAA,EAAQ,MAAW,KAAA;AAC7D,IAAM,MAAA,sBAAA,GAAyBC,4DAA8B,MAAO,CAAA;AAAA,MAClE,QAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAW,UAAA,CAAA,GAAA,CAAI,sBAAuB,CAAA,YAAA,EAAc,CAAA;AAEpD,IAAO,OAAA,sBAAA;AAAA;AAEX,CAAC;;;;"}
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ var actionsRegistryServiceFactory = require('./alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js');
4
+ var actionsServiceFactory = require('./alpha/entrypoints/actions/actionsServiceFactory.cjs.js');
5
+
6
+
7
+
8
+ exports.actionsRegistryServiceFactory = actionsRegistryServiceFactory.actionsRegistryServiceFactory;
9
+ exports.actionsServiceFactory = actionsServiceFactory.actionsServiceFactory;
10
+ //# sourceMappingURL=alpha.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alpha.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,14 @@
1
+ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
+ import * as _backstage_backend_plugin_api_alpha from '@backstage/backend-plugin-api/alpha';
3
+
4
+ /**
5
+ * @public
6
+ */
7
+ declare const actionsRegistryServiceFactory: _backstage_backend_plugin_api.ServiceFactory<_backstage_backend_plugin_api_alpha.ActionsRegistryService, "plugin", "singleton">;
8
+
9
+ /**
10
+ * @public
11
+ */
12
+ declare const actionsServiceFactory: _backstage_backend_plugin_api.ServiceFactory<_backstage_backend_plugin_api_alpha.ActionsService, "plugin", "singleton">;
13
+
14
+ export { actionsRegistryServiceFactory, actionsServiceFactory };
@@ -1,54 +1,73 @@
1
1
  'use strict';
2
2
 
3
+ var crypto = require('crypto');
4
+
3
5
  function createCredentialsWithServicePrincipal(sub, token, accessRestrictions) {
4
- return Object.defineProperty(
5
- {
6
- $$type: "@backstage/BackstageCredentials",
7
- version: "v1",
8
- principal: {
9
- type: "service",
10
- subject: sub,
11
- accessRestrictions
12
- }
13
- },
14
- "token",
15
- {
6
+ const principal = createServicePrincipal(sub, accessRestrictions);
7
+ const result = {
8
+ $$type: "@backstage/BackstageCredentials",
9
+ version: "v1",
10
+ principal
11
+ };
12
+ Object.defineProperties(result, {
13
+ token: {
16
14
  enumerable: false,
17
15
  configurable: true,
16
+ writable: true,
18
17
  value: token
18
+ },
19
+ toString: {
20
+ enumerable: false,
21
+ configurable: true,
22
+ writable: true,
23
+ value: () => `backstageCredentials{${principal}}`
19
24
  }
20
- );
25
+ });
26
+ return result;
21
27
  }
22
28
  function createCredentialsWithUserPrincipal(sub, token, expiresAt, actor) {
23
- return Object.defineProperty(
24
- {
25
- $$type: "@backstage/BackstageCredentials",
26
- version: "v1",
27
- expiresAt,
28
- principal: {
29
- type: "user",
30
- userEntityRef: sub,
31
- ...actor && {
32
- actor: { type: "service", subject: actor }
33
- }
34
- }
35
- },
36
- "token",
37
- {
29
+ const principal = createUserPrincipal(
30
+ sub,
31
+ actor ? createServicePrincipal(actor) : void 0
32
+ );
33
+ const result = {
34
+ $$type: "@backstage/BackstageCredentials",
35
+ version: "v1",
36
+ expiresAt,
37
+ principal
38
+ };
39
+ Object.defineProperties(result, {
40
+ token: {
38
41
  enumerable: false,
39
42
  configurable: true,
43
+ writable: true,
40
44
  value: token
45
+ },
46
+ toString: {
47
+ enumerable: false,
48
+ configurable: true,
49
+ writable: true,
50
+ value: () => `backstageCredentials{${principal}}`
41
51
  }
42
- );
52
+ });
53
+ return result;
43
54
  }
44
55
  function createCredentialsWithNonePrincipal() {
45
- return {
56
+ const principal = createNonePrincipal();
57
+ const result = {
46
58
  $$type: "@backstage/BackstageCredentials",
47
59
  version: "v1",
48
- principal: {
49
- type: "none"
50
- }
60
+ principal
51
61
  };
62
+ Object.defineProperties(result, {
63
+ toString: {
64
+ enumerable: false,
65
+ configurable: true,
66
+ writable: true,
67
+ value: () => `backstageCredentials{${principal}}`
68
+ }
69
+ });
70
+ return result;
52
71
  }
53
72
  function toInternalBackstageCredentials(credentials) {
54
73
  if (credentials.$$type !== "@backstage/BackstageCredentials") {
@@ -62,6 +81,65 @@ function toInternalBackstageCredentials(credentials) {
62
81
  }
63
82
  return internalCredentials;
64
83
  }
84
+ function createServicePrincipal(sub, accessRestrictions) {
85
+ const result = {
86
+ type: "service",
87
+ subject: sub,
88
+ accessRestrictions
89
+ };
90
+ Object.defineProperties(result, {
91
+ toString: {
92
+ enumerable: false,
93
+ configurable: true,
94
+ writable: true,
95
+ value: () => {
96
+ let parts = sub;
97
+ if (accessRestrictions) {
98
+ const hash = crypto.createHash("sha256").update(JSON.stringify(accessRestrictions)).digest("base64").replace(/=+$/, "");
99
+ parts += `,accessRestrictions=${hash}`;
100
+ }
101
+ return `servicePrincipal{${parts}}`;
102
+ }
103
+ }
104
+ });
105
+ return result;
106
+ }
107
+ function createUserPrincipal(userEntityRef, actor) {
108
+ const result = {
109
+ type: "user",
110
+ userEntityRef,
111
+ actor
112
+ };
113
+ Object.defineProperties(result, {
114
+ toString: {
115
+ enumerable: false,
116
+ configurable: true,
117
+ writable: true,
118
+ value: () => {
119
+ let parts = userEntityRef;
120
+ if (actor) {
121
+ parts += `,actor={${actor}}`;
122
+ }
123
+ return `userPrincipal{${parts}}`;
124
+ }
125
+ }
126
+ });
127
+ return result;
128
+ }
129
+ function createNonePrincipal() {
130
+ const result = {
131
+ type: "none"
132
+ };
133
+ Object.defineProperties(result, {
134
+ toString: {
135
+ enumerable: false,
136
+ configurable: true,
137
+ writable: true,
138
+ value: () => "nonePrincipal"
139
+ }
140
+ });
141
+ return result;
142
+ }
65
143
 
66
144
  exports.createCredentialsWithNonePrincipal = createCredentialsWithNonePrincipal;
67
145
  exports.createCredentialsWithServicePrincipal = createCredentialsWithServicePrincipal;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.cjs.js","sources":["../../../src/entrypoints/auth/helpers.ts"],"sourcesContent":["/*\n * Copyright 2024 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 BackstageCredentials,\n BackstageNonePrincipal,\n BackstagePrincipalAccessRestrictions,\n BackstageServicePrincipal,\n BackstageUserPrincipal,\n} from '@backstage/backend-plugin-api';\nimport { InternalBackstageCredentials } from './types';\n\nexport function createCredentialsWithServicePrincipal(\n sub: string,\n token?: string,\n accessRestrictions?: BackstagePrincipalAccessRestrictions,\n): InternalBackstageCredentials<BackstageServicePrincipal> {\n return Object.defineProperty(\n {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n principal: {\n type: 'service',\n subject: sub,\n accessRestrictions,\n },\n },\n 'token',\n {\n enumerable: false,\n configurable: true,\n value: token,\n },\n );\n}\n\nexport function createCredentialsWithUserPrincipal(\n sub: string,\n token: string,\n expiresAt?: Date,\n actor?: string,\n): InternalBackstageCredentials<BackstageUserPrincipal> {\n return Object.defineProperty(\n {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n expiresAt,\n principal: {\n type: 'user',\n userEntityRef: sub,\n ...(actor && {\n actor: { type: 'service', subject: actor },\n }),\n },\n },\n 'token',\n {\n enumerable: false,\n configurable: true,\n value: token,\n },\n );\n}\n\nexport function createCredentialsWithNonePrincipal(): InternalBackstageCredentials<BackstageNonePrincipal> {\n return {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n principal: {\n type: 'none',\n },\n };\n}\n\nexport function toInternalBackstageCredentials(\n credentials: BackstageCredentials,\n): InternalBackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal | BackstageNonePrincipal\n> {\n if (credentials.$$type !== '@backstage/BackstageCredentials') {\n throw new Error('Invalid credential type');\n }\n\n const internalCredentials = credentials as InternalBackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal | BackstageNonePrincipal\n >;\n\n if (internalCredentials.version !== 'v1') {\n throw new Error(\n `Invalid credential version ${internalCredentials.version}`,\n );\n }\n\n return internalCredentials;\n}\n"],"names":[],"mappings":";;AAyBgB,SAAA,qCAAA,CACd,GACA,EAAA,KAAA,EACA,kBACyD,EAAA;AACzD,EAAA,OAAO,MAAO,CAAA,cAAA;AAAA,IACZ;AAAA,MACE,MAAQ,EAAA,iCAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,SAAW,EAAA;AAAA,QACT,IAAM,EAAA,SAAA;AAAA,QACN,OAAS,EAAA,GAAA;AAAA,QACT;AAAA;AACF,KACF;AAAA,IACA,OAAA;AAAA,IACA;AAAA,MACE,UAAY,EAAA,KAAA;AAAA,MACZ,YAAc,EAAA,IAAA;AAAA,MACd,KAAO,EAAA;AAAA;AACT,GACF;AACF;AAEO,SAAS,kCACd,CAAA,GAAA,EACA,KACA,EAAA,SAAA,EACA,KACsD,EAAA;AACtD,EAAA,OAAO,MAAO,CAAA,cAAA;AAAA,IACZ;AAAA,MACE,MAAQ,EAAA,iCAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,SAAA;AAAA,MACA,SAAW,EAAA;AAAA,QACT,IAAM,EAAA,MAAA;AAAA,QACN,aAAe,EAAA,GAAA;AAAA,QACf,GAAI,KAAS,IAAA;AAAA,UACX,KAAO,EAAA,EAAE,IAAM,EAAA,SAAA,EAAW,SAAS,KAAM;AAAA;AAC3C;AACF,KACF;AAAA,IACA,OAAA;AAAA,IACA;AAAA,MACE,UAAY,EAAA,KAAA;AAAA,MACZ,YAAc,EAAA,IAAA;AAAA,MACd,KAAO,EAAA;AAAA;AACT,GACF;AACF;AAEO,SAAS,kCAA2F,GAAA;AACzG,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,iCAAA;AAAA,IACR,OAAS,EAAA,IAAA;AAAA,IACT,SAAW,EAAA;AAAA,MACT,IAAM,EAAA;AAAA;AACR,GACF;AACF;AAEO,SAAS,+BACd,WAGA,EAAA;AACA,EAAI,IAAA,WAAA,CAAY,WAAW,iCAAmC,EAAA;AAC5D,IAAM,MAAA,IAAI,MAAM,yBAAyB,CAAA;AAAA;AAG3C,EAAA,MAAM,mBAAsB,GAAA,WAAA;AAI5B,EAAI,IAAA,mBAAA,CAAoB,YAAY,IAAM,EAAA;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2BAAA,EAA8B,oBAAoB,OAAO,CAAA;AAAA,KAC3D;AAAA;AAGF,EAAO,OAAA,mBAAA;AACT;;;;;;;"}
1
+ {"version":3,"file":"helpers.cjs.js","sources":["../../../src/entrypoints/auth/helpers.ts"],"sourcesContent":["/*\n * Copyright 2024 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 BackstageCredentials,\n BackstageNonePrincipal,\n BackstagePrincipalAccessRestrictions,\n BackstageServicePrincipal,\n BackstageUserPrincipal,\n} from '@backstage/backend-plugin-api';\nimport { InternalBackstageCredentials } from './types';\nimport { createHash } from 'crypto';\n\nexport function createCredentialsWithServicePrincipal(\n sub: string,\n token?: string,\n accessRestrictions?: BackstagePrincipalAccessRestrictions,\n): InternalBackstageCredentials<BackstageServicePrincipal> {\n const principal = createServicePrincipal(sub, accessRestrictions);\n const result = {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n principal,\n } as const;\n Object.defineProperties(result, {\n token: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: token,\n },\n toString: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => `backstageCredentials{${principal}}`,\n },\n });\n return result;\n}\n\nexport function createCredentialsWithUserPrincipal(\n sub: string,\n token: string,\n expiresAt?: Date,\n actor?: string,\n): InternalBackstageCredentials<BackstageUserPrincipal> {\n const principal = createUserPrincipal(\n sub,\n actor ? createServicePrincipal(actor) : undefined,\n );\n const result = {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n expiresAt,\n principal,\n } as const;\n Object.defineProperties(result, {\n token: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: token,\n },\n toString: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => `backstageCredentials{${principal}}`,\n },\n });\n return result;\n}\n\nexport function createCredentialsWithNonePrincipal(): InternalBackstageCredentials<BackstageNonePrincipal> {\n const principal = createNonePrincipal();\n const result = {\n $$type: '@backstage/BackstageCredentials',\n version: 'v1',\n principal,\n } as const;\n Object.defineProperties(result, {\n toString: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => `backstageCredentials{${principal}}`,\n },\n });\n return result;\n}\n\nexport function toInternalBackstageCredentials(\n credentials: BackstageCredentials,\n): InternalBackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal | BackstageNonePrincipal\n> {\n if (credentials.$$type !== '@backstage/BackstageCredentials') {\n throw new Error('Invalid credential type');\n }\n\n const internalCredentials = credentials as InternalBackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal | BackstageNonePrincipal\n >;\n\n if (internalCredentials.version !== 'v1') {\n throw new Error(\n `Invalid credential version ${internalCredentials.version}`,\n );\n }\n\n return internalCredentials;\n}\n\nfunction createServicePrincipal(\n sub: string,\n accessRestrictions?: BackstagePrincipalAccessRestrictions,\n): BackstageServicePrincipal {\n const result = {\n type: 'service',\n subject: sub,\n accessRestrictions,\n } as const;\n Object.defineProperties(result, {\n toString: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => {\n let parts = sub;\n if (accessRestrictions) {\n const hash = createHash('sha256')\n .update(JSON.stringify(accessRestrictions))\n .digest('base64')\n .replace(/=+$/, '');\n parts += `,accessRestrictions=${hash}`;\n }\n return `servicePrincipal{${parts}}`;\n },\n },\n });\n return result;\n}\n\nfunction createUserPrincipal(\n userEntityRef: string,\n actor?: BackstageServicePrincipal,\n): BackstageUserPrincipal {\n const result = {\n type: 'user',\n userEntityRef,\n actor,\n } as const;\n Object.defineProperties(result, {\n toString: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => {\n let parts = userEntityRef;\n if (actor) {\n parts += `,actor={${actor}}`;\n }\n return `userPrincipal{${parts}}`;\n },\n },\n });\n return result;\n}\n\nfunction createNonePrincipal(): BackstageNonePrincipal {\n const result = {\n type: 'none',\n } as const;\n Object.defineProperties(result, {\n toString: {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => 'nonePrincipal',\n },\n });\n return result;\n}\n"],"names":["createHash"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ var RateLimitStoreFactory = require('../../../lib/RateLimitStoreFactory.cjs.js');
4
+ var rateLimitMiddleware = require('../../../lib/rateLimitMiddleware.cjs.js');
5
+
6
+ const createRateLimitMiddleware = (options) => {
7
+ const { pluginId, config } = options;
8
+ const configKey = `backend.rateLimit.plugin.${pluginId}`;
9
+ const enabled = config.has(configKey);
10
+ if (!enabled) {
11
+ return (_req, _res, next) => {
12
+ next();
13
+ };
14
+ }
15
+ const rateLimitOptions = config.getConfig(configKey);
16
+ return rateLimitMiddleware.rateLimitMiddleware({
17
+ store: RateLimitStoreFactory.RateLimitStoreFactory.create({ config, prefix: pluginId }),
18
+ config: rateLimitOptions
19
+ });
20
+ };
21
+
22
+ exports.createRateLimitMiddleware = createRateLimitMiddleware;
23
+ //# sourceMappingURL=createRateLimitMiddleware.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRateLimitMiddleware.cjs.js","sources":["../../../../src/entrypoints/httpRouter/http/createRateLimitMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2025 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 */\nimport { NextFunction, Request, Response } from 'express';\nimport { RateLimitStoreFactory } from '../../../lib/RateLimitStoreFactory.ts';\nimport { Config } from '@backstage/config';\nimport { rateLimitMiddleware } from '../../../lib/rateLimitMiddleware.ts';\n\nexport const createRateLimitMiddleware = (options: {\n pluginId: string;\n config: Config;\n}) => {\n const { pluginId, config } = options;\n const configKey = `backend.rateLimit.plugin.${pluginId}`;\n const enabled = config.has(configKey);\n if (!enabled) {\n return (_req: Request, _res: Response, next: NextFunction) => {\n next();\n };\n }\n\n const rateLimitOptions = config.getConfig(configKey);\n\n return rateLimitMiddleware({\n store: RateLimitStoreFactory.create({ config, prefix: pluginId }),\n config: rateLimitOptions,\n });\n};\n"],"names":["rateLimitMiddleware","RateLimitStoreFactory"],"mappings":";;;;;AAoBa,MAAA,yBAAA,GAA4B,CAAC,OAGpC,KAAA;AACJ,EAAM,MAAA,EAAE,QAAU,EAAA,MAAA,EAAW,GAAA,OAAA;AAC7B,EAAM,MAAA,SAAA,GAAY,4BAA4B,QAAQ,CAAA,CAAA;AACtD,EAAM,MAAA,OAAA,GAAU,MAAO,CAAA,GAAA,CAAI,SAAS,CAAA;AACpC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAO,OAAA,CAAC,IAAe,EAAA,IAAA,EAAgB,IAAuB,KAAA;AAC5D,MAAK,IAAA,EAAA;AAAA,KACP;AAAA;AAGF,EAAM,MAAA,gBAAA,GAAmB,MAAO,CAAA,SAAA,CAAU,SAAS,CAAA;AAEnD,EAAA,OAAOA,uCAAoB,CAAA;AAAA,IACzB,OAAOC,2CAAsB,CAAA,MAAA,CAAO,EAAE,MAAQ,EAAA,MAAA,EAAQ,UAAU,CAAA;AAAA,IAChE,MAAQ,EAAA;AAAA,GACT,CAAA;AACH;;;;"}
@@ -18,6 +18,7 @@ require('minimatch');
18
18
  require('helmet');
19
19
  require('lodash/kebabCase');
20
20
  require('../rootHttpRouter/rootHttpRouterServiceFactory.cjs.js');
21
+ var createRateLimitMiddleware = require('./http/createRateLimitMiddleware.cjs.js');
21
22
 
22
23
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
23
24
 
@@ -45,6 +46,7 @@ const httpRouterServiceFactory = backendPluginApi.createServiceFactory({
45
46
  logger
46
47
  }) {
47
48
  const router = Router__default.default();
49
+ router.use(createRateLimitMiddleware.createRateLimitMiddleware({ pluginId: plugin.getId(), config }));
48
50
  rootHttpRouter.use(`/api/${plugin.getId()}`, router);
49
51
  const credentialsBarrier = createCredentialsBarrier.createCredentialsBarrier({
50
52
  httpAuth,