@backstage/plugin-catalog-backend 3.9.0 → 3.9.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @backstage/plugin-catalog-backend
2
2
 
3
+ ## 3.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 61a10f1: Improved path validation for catalog entity placeholders.
8
+ - 21424fa: Correct catalog property permission matching.
9
+ - 23774b6: Allowed location type restrictions are now applied consistently during catalog processing.
10
+ - Updated dependencies
11
+ - @backstage/integration@2.1.1
12
+
3
13
  ## 3.9.0
4
14
 
5
15
  ### Minor Changes
@@ -2,8 +2,8 @@
2
2
 
3
3
  var alpha = require('@backstage/plugin-catalog-node/alpha');
4
4
  var pluginPermissionNode = require('@backstage/plugin-permission-node');
5
- var lodash = require('lodash');
6
5
  var v3 = require('zod/v3');
6
+ var buildEntitySearch = require('../../database/operations/stitcher/buildEntitySearch.cjs.js');
7
7
 
8
8
  const createPropertyRule = (propertyType) => pluginPermissionNode.createPermissionRule({
9
9
  name: `HAS_${propertyType.toUpperCase()}`,
@@ -14,17 +14,11 @@ const createPropertyRule = (propertyType) => pluginPermissionNode.createPermissi
14
14
  value: v3.z.string().optional().describe(`Value of the given property to match on`)
15
15
  }),
16
16
  apply: (resource, { key, value }) => {
17
- const foundValue = lodash.get(resource[propertyType], key);
18
- if (Array.isArray(foundValue)) {
19
- if (value !== void 0) {
20
- return foundValue.includes(value);
21
- }
22
- return foundValue.length > 0;
23
- }
24
- if (value !== void 0) {
25
- return value === foundValue;
26
- }
27
- return !!foundValue;
17
+ const normalizedKey = `${propertyType}.${key}`.toLocaleLowerCase("en-US");
18
+ const normalizedValue = value?.toLocaleLowerCase("en-US");
19
+ return buildEntitySearch.buildEntitySearch("", resource).some(
20
+ (row) => row.key === normalizedKey && (normalizedValue === void 0 || row.value === normalizedValue)
21
+ );
28
22
  },
29
23
  toQuery: ({ key, value }) => ({
30
24
  key: `${propertyType}.${key}`,
@@ -1 +1 @@
1
- {"version":3,"file":"createPropertyRule.cjs.js","sources":["../../../src/permissions/rules/createPropertyRule.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 { catalogEntityPermissionResourceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { createPermissionRule } from '@backstage/plugin-permission-node';\nimport { get } from 'lodash';\nimport { z } from 'zod/v3';\n\nexport const createPropertyRule = (propertyType: 'metadata' | 'spec') =>\n createPermissionRule({\n name: `HAS_${propertyType.toUpperCase()}`,\n description: `Allow entities with the specified ${propertyType} subfield`,\n resourceRef: catalogEntityPermissionResourceRef,\n paramsSchema: z.object({\n key: z\n .string()\n .describe(`Property within the entities ${propertyType} to match on`),\n value: z\n .string()\n .optional()\n .describe(`Value of the given property to match on`),\n }),\n apply: (resource, { key, value }) => {\n const foundValue = get(resource[propertyType], key);\n\n if (Array.isArray(foundValue)) {\n if (value !== undefined) {\n return foundValue.includes(value);\n }\n return foundValue.length > 0;\n }\n if (value !== undefined) {\n return value === foundValue;\n }\n return !!foundValue;\n },\n toQuery: ({ key, value }) => ({\n key: `${propertyType}.${key}`,\n ...(value !== undefined && { values: [value] }),\n }),\n });\n"],"names":["createPermissionRule","catalogEntityPermissionResourceRef","z","get"],"mappings":";;;;;;;AAqBO,MAAM,kBAAA,GAAqB,CAAC,YAAA,KACjCA,yCAAA,CAAqB;AAAA,EACnB,IAAA,EAAM,CAAA,IAAA,EAAO,YAAA,CAAa,WAAA,EAAa,CAAA,CAAA;AAAA,EACvC,WAAA,EAAa,qCAAqC,YAAY,CAAA,SAAA,CAAA;AAAA,EAC9D,WAAA,EAAaC,wCAAA;AAAA,EACb,YAAA,EAAcC,KAAE,MAAA,CAAO;AAAA,IACrB,KAAKA,IAAA,CACF,MAAA,GACA,QAAA,CAAS,CAAA,6BAAA,EAAgC,YAAY,CAAA,YAAA,CAAc,CAAA;AAAA,IACtE,OAAOA,IAAA,CACJ,MAAA,GACA,QAAA,EAAS,CACT,SAAS,CAAA,uCAAA,CAAyC;AAAA,GACtD,CAAA;AAAA,EACD,OAAO,CAAC,QAAA,EAAU,EAAE,GAAA,EAAK,OAAM,KAAM;AACnC,IAAA,MAAM,UAAA,GAAaC,UAAA,CAAI,QAAA,CAAS,YAAY,GAAG,GAAG,CAAA;AAElD,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC7B,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,OAAO,UAAA,CAAW,SAAS,KAAK,CAAA;AAAA,MAClC;AACA,MAAA,OAAO,WAAW,MAAA,GAAS,CAAA;AAAA,IAC7B;AACA,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,OAAO,KAAA,KAAU,UAAA;AAAA,IACnB;AACA,IAAA,OAAO,CAAC,CAAC,UAAA;AAAA,EACX,CAAA;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,GAAA,EAAK,OAAM,MAAO;AAAA,IAC5B,GAAA,EAAK,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAAA,IAC3B,GAAI,KAAA,KAAU,MAAA,IAAa,EAAE,MAAA,EAAQ,CAAC,KAAK,CAAA;AAAE,GAC/C;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"createPropertyRule.cjs.js","sources":["../../../src/permissions/rules/createPropertyRule.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 { catalogEntityPermissionResourceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { createPermissionRule } from '@backstage/plugin-permission-node';\nimport { z } from 'zod/v3';\nimport { buildEntitySearch } from '../../database/operations/stitcher/buildEntitySearch';\n\nexport const createPropertyRule = (propertyType: 'metadata' | 'spec') =>\n createPermissionRule({\n name: `HAS_${propertyType.toUpperCase()}`,\n description: `Allow entities with the specified ${propertyType} subfield`,\n resourceRef: catalogEntityPermissionResourceRef,\n paramsSchema: z.object({\n key: z\n .string()\n .describe(`Property within the entities ${propertyType} to match on`),\n value: z\n .string()\n .optional()\n .describe(`Value of the given property to match on`),\n }),\n apply: (resource, { key, value }) => {\n const normalizedKey = `${propertyType}.${key}`.toLocaleLowerCase('en-US');\n const normalizedValue = value?.toLocaleLowerCase('en-US');\n\n return buildEntitySearch('', resource).some(\n row =>\n row.key === normalizedKey &&\n (normalizedValue === undefined || row.value === normalizedValue),\n );\n },\n toQuery: ({ key, value }) => ({\n key: `${propertyType}.${key}`,\n ...(value !== undefined && { values: [value] }),\n }),\n });\n"],"names":["createPermissionRule","catalogEntityPermissionResourceRef","z","buildEntitySearch"],"mappings":";;;;;;;AAqBO,MAAM,kBAAA,GAAqB,CAAC,YAAA,KACjCA,yCAAA,CAAqB;AAAA,EACnB,IAAA,EAAM,CAAA,IAAA,EAAO,YAAA,CAAa,WAAA,EAAa,CAAA,CAAA;AAAA,EACvC,WAAA,EAAa,qCAAqC,YAAY,CAAA,SAAA,CAAA;AAAA,EAC9D,WAAA,EAAaC,wCAAA;AAAA,EACb,YAAA,EAAcC,KAAE,MAAA,CAAO;AAAA,IACrB,KAAKA,IAAA,CACF,MAAA,GACA,QAAA,CAAS,CAAA,6BAAA,EAAgC,YAAY,CAAA,YAAA,CAAc,CAAA;AAAA,IACtE,OAAOA,IAAA,CACJ,MAAA,GACA,QAAA,EAAS,CACT,SAAS,CAAA,uCAAA,CAAyC;AAAA,GACtD,CAAA;AAAA,EACD,OAAO,CAAC,QAAA,EAAU,EAAE,GAAA,EAAK,OAAM,KAAM;AACnC,IAAA,MAAM,gBAAgB,CAAA,EAAG,YAAY,IAAI,GAAG,CAAA,CAAA,CAAG,kBAAkB,OAAO,CAAA;AACxE,IAAA,MAAM,eAAA,GAAkB,KAAA,EAAO,iBAAA,CAAkB,OAAO,CAAA;AAExD,IAAA,OAAOC,mCAAA,CAAkB,EAAA,EAAI,QAAQ,CAAA,CAAE,IAAA;AAAA,MACrC,SACE,GAAA,CAAI,GAAA,KAAQ,kBACX,eAAA,KAAoB,MAAA,IAAa,IAAI,KAAA,KAAU,eAAA;AAAA,KACpD;AAAA,EACF,CAAA;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,GAAA,EAAK,OAAM,MAAO;AAAA,IAC5B,GAAA,EAAK,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAAA,IAC3B,GAAI,KAAA,KAAU,MAAA,IAAa,EAAE,MAAA,EAAQ,CAAC,KAAK,CAAA;AAAE,GAC/C;AACF,CAAC;;;;"}
@@ -218,6 +218,18 @@ class DefaultCatalogProcessingOrchestrator {
218
218
  "readLocation"
219
219
  );
220
220
  const { type = context.location.type, presence = "required" } = entity.spec;
221
+ const { allowedLocationTypes } = this.options;
222
+ if (allowedLocationTypes && type !== context.location.type && !allowedLocationTypes.includes(type)) {
223
+ context.collector.generic()(
224
+ pluginCatalogNode.processingResult.inputError(
225
+ context.location,
226
+ `Registered locations must be of an allowed type ${JSON.stringify(
227
+ allowedLocationTypes
228
+ )}`
229
+ )
230
+ );
231
+ return;
232
+ }
221
233
  const targets = new Array();
222
234
  if (entity.spec.target) {
223
235
  targets.push(entity.spec.target);
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultCatalogProcessingOrchestrator.cjs.js","sources":["../../src/processing/DefaultCatalogProcessingOrchestrator.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 { Span, trace } from '@opentelemetry/api';\nimport {\n Entity,\n EntityPolicy,\n LocationEntity,\n parseLocationRef,\n stringifyEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n toError,\n} from '@backstage/errors';\nimport { JsonValue } from '@backstage/types';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport path from 'node:path';\nimport { LocationSpec } from '@backstage/plugin-catalog-common';\nimport {\n CatalogProcessor,\n CatalogProcessorParser,\n processingResult,\n} from '@backstage/plugin-catalog-node';\nimport {\n CatalogProcessingOrchestrator,\n EntityProcessingRequest,\n EntityProcessingResult,\n} from './types';\nimport { ProcessorOutputCollector } from './ProcessorOutputCollector';\nimport {\n getEntityLocationRef,\n getEntityOriginLocationRef,\n isLocationEntity,\n isObject,\n toAbsoluteUrl,\n validateEntity,\n validateEntityEnvelope,\n} from './util';\nimport { CatalogRulesEnforcer } from '../ingestion/CatalogRules';\nimport { ProcessorCacheManager } from './ProcessorCacheManager';\nimport {\n addEntityAttributes,\n TRACER_ID,\n withActiveSpan,\n} from '../util/opentelemetry';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst tracer = trace.getTracer(TRACER_ID);\n\ntype Context = {\n entityRef: string;\n location: LocationSpec;\n originLocation: LocationSpec;\n collector: ProcessorOutputCollector;\n cache: ProcessorCacheManager;\n};\n\nfunction addProcessorAttributes(\n span: Span,\n stage: string,\n processor: CatalogProcessor,\n) {\n span.setAttribute('backstage.catalog.processor.stage', stage);\n span.setAttribute(\n 'backstage.catalog.processor.name',\n processor.getProcessorName(),\n );\n}\n\nexport class DefaultCatalogProcessingOrchestrator\n implements CatalogProcessingOrchestrator\n{\n private readonly options: {\n processors: CatalogProcessor[];\n integrations: ScmIntegrationRegistry;\n logger: LoggerService;\n parser: CatalogProcessorParser;\n policy: EntityPolicy;\n rulesEnforcer: CatalogRulesEnforcer;\n };\n\n constructor(options: {\n processors: CatalogProcessor[];\n integrations: ScmIntegrationRegistry;\n logger: LoggerService;\n parser: CatalogProcessorParser;\n policy: EntityPolicy;\n rulesEnforcer: CatalogRulesEnforcer;\n }) {\n this.options = options;\n }\n\n async process(\n request: EntityProcessingRequest,\n ): Promise<EntityProcessingResult> {\n return this.processSingleEntity(request.entity, request.state);\n }\n\n private async processSingleEntity(\n unprocessedEntity: Entity,\n state: JsonValue | undefined,\n ): Promise<EntityProcessingResult> {\n const collector = new ProcessorOutputCollector(\n this.options.logger,\n unprocessedEntity,\n );\n\n // Cache that is scoped to the entity and processor\n const cache = new ProcessorCacheManager(\n isObject(state) && isObject(state.cache) ? state.cache : {},\n );\n\n try {\n // This will be checked and mutated step by step below\n let entity: Entity = unprocessedEntity;\n\n // NOTE: At this early point, we can only rely on the envelope having to\n // be valid; full entity + kind validation happens after the (potentially\n // mutative) pre-steps. This means that the code below can't make a lot\n // of assumptions about the data despite it using the Entity type.\n try {\n validateEntityEnvelope(entity);\n } catch (e) {\n throw new InputError(\n `Entity envelope failed validation before processing`,\n e,\n );\n }\n\n // TODO: which one do we actually use for the location?\n // source-location? - maybe probably doesn't exist yet?\n const context: Context = {\n entityRef: stringifyEntityRef(entity),\n location: parseLocationRef(getEntityLocationRef(entity)),\n originLocation: parseLocationRef(getEntityOriginLocationRef(entity)),\n cache,\n collector,\n };\n\n // Run the steps\n entity = await this.runPreProcessStep(entity, context);\n entity = await this.runPolicyStep(entity);\n await this.runValidateStep(entity, context);\n if (isLocationEntity(entity)) {\n await this.runSpecialLocationStep(entity, context);\n }\n entity = await this.runPostProcessStep(entity, context);\n\n // Check that any emitted entities are permitted to originate from that\n // particular location according to the catalog rules\n const collectorResults = context.collector.results();\n for (const deferredEntity of collectorResults.deferredEntities) {\n if (\n !this.options.rulesEnforcer.isAllowed(\n deferredEntity.entity,\n context.originLocation,\n )\n ) {\n throw new NotAllowedError(\n `Entity ${stringifyEntityRef(\n deferredEntity.entity,\n )} at ${stringifyLocationRef(\n context.location,\n )}, originated at ${stringifyLocationRef(\n context.originLocation,\n )}, is not of an allowed kind for that location`,\n );\n }\n }\n\n return {\n ...collectorResults,\n completedEntity: entity,\n state: { cache: cache.collect() },\n ok: collectorResults.errors.length === 0,\n };\n } catch (error) {\n const err = toError(error);\n return {\n ok: false,\n errors: collector.results().errors.concat(err),\n };\n }\n }\n\n // Pre-process phase, used to populate entities with data that is required\n // during the main processing step\n private async runPreProcessStep(\n entity: Entity,\n context: Context,\n ): Promise<Entity> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute('backstage.catalog.processor.stage', 'preProcess');\n let res = entity;\n\n for (const processor of this.options.processors) {\n if (processor.preProcessEntity) {\n let innerRes = res;\n res = await withActiveSpan(tracer, 'ProcessingStep', async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'preProcessEntity', processor);\n try {\n innerRes = await processor.preProcessEntity!(\n innerRes,\n context.location,\n context.collector.forProcessor(processor),\n context.originLocation,\n context.cache.forProcessor(processor),\n );\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while preprocessing`,\n e,\n );\n }\n return innerRes;\n });\n }\n }\n\n return res;\n });\n }\n\n /**\n * Enforce entity policies making sure that entities conform to a general schema\n */\n private async runPolicyStep(entity: Entity): Promise<Entity> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute(\n 'backstage.catalog.processor.stage',\n 'enforcePolicy',\n );\n let policyEnforcedEntity: Entity | undefined;\n\n try {\n policyEnforcedEntity = await this.options.policy.enforce(entity);\n } catch (e) {\n throw new InputError(\n `Policy check failed for ${stringifyEntityRef(entity)}`,\n e,\n );\n }\n\n if (!policyEnforcedEntity) {\n throw new Error(\n `Policy unexpectedly returned no data for ${stringifyEntityRef(\n entity,\n )}`,\n );\n }\n\n return policyEnforcedEntity;\n });\n }\n\n /**\n * Validate the given entity\n */\n private async runValidateStep(\n entity: Entity,\n context: Context,\n ): Promise<void> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute('backstage.catalog.processor.stage', 'validate');\n // Double check that none of the previous steps tried to change something\n // related to the entity ref, which would break downstream\n if (stringifyEntityRef(entity) !== context.entityRef) {\n throw new ConflictError(\n 'Fatal: The entity kind, namespace, or name changed during processing',\n );\n }\n\n // Validate that the end result is a valid Entity at all\n try {\n validateEntity(entity);\n } catch (e) {\n throw new ConflictError(\n `Entity envelope for ${context.entityRef} failed validation after preprocessing`,\n e,\n );\n }\n\n let valid = false;\n\n for (const processor of this.options.processors) {\n if (processor.validateEntityKind) {\n try {\n const thisValid = await withActiveSpan(\n tracer,\n 'ProcessingStep',\n async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'validateEntityKind', processor);\n return await processor.validateEntityKind!(entity);\n },\n );\n if (thisValid) {\n valid = true;\n }\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while validating the entity ${context.entityRef}`,\n e,\n );\n }\n }\n }\n\n if (!valid) {\n throw new InputError(\n `No processor recognized the entity ${context.entityRef} as valid, possibly caused by a foreign kind or apiVersion`,\n );\n }\n });\n }\n\n /**\n * Backwards compatible processing of location entities\n */\n private async runSpecialLocationStep(\n entity: LocationEntity,\n context: Context,\n ): Promise<void> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute(\n 'backstage.catalog.processor.stage',\n 'readLocation',\n );\n const { type = context.location.type, presence = 'required' } =\n entity.spec;\n const targets = new Array<string>();\n if (entity.spec.target) {\n targets.push(entity.spec.target);\n }\n if (entity.spec.targets) {\n targets.push(...entity.spec.targets);\n }\n\n for (const maybeRelativeTarget of targets) {\n if (type === 'file' && maybeRelativeTarget.endsWith(path.sep)) {\n context.collector.generic()(\n processingResult.inputError(\n context.location,\n `LocationEntityProcessor cannot handle ${type} type location with target ${context.location.target} that ends with a path separator`,\n ),\n );\n continue;\n }\n const target = toAbsoluteUrl(\n this.options.integrations,\n context.location,\n type,\n maybeRelativeTarget,\n );\n\n let didRead = false;\n for (const processor of this.options.processors) {\n if (processor.readLocation) {\n try {\n const read = await withActiveSpan(\n tracer,\n 'ProcessingStep',\n async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'readLocation', processor);\n return await processor.readLocation!(\n {\n type,\n target,\n presence,\n },\n presence === 'optional',\n context.collector.forProcessor(processor),\n this.options.parser,\n context.cache.forProcessor(processor, target),\n );\n },\n );\n if (read) {\n didRead = true;\n break;\n }\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while reading ${type}:${target}`,\n e,\n );\n }\n }\n }\n if (!didRead) {\n throw new InputError(\n `No processor was able to handle reading of ${type}:${target}`,\n );\n }\n }\n });\n }\n\n /**\n * Main processing step of the entity\n */\n private async runPostProcessStep(\n entity: Entity,\n context: Context,\n ): Promise<Entity> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute(\n 'backstage.catalog.processor.stage',\n 'postProcessEntity',\n );\n let res = entity;\n\n for (const processor of this.options.processors) {\n if (processor.postProcessEntity) {\n let innerRes = res;\n res = await withActiveSpan(tracer, 'ProcessingStep', async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'postProcessEntity', processor);\n try {\n innerRes = await processor.postProcessEntity!(\n innerRes,\n context.location,\n context.collector.forProcessor(processor),\n context.cache.forProcessor(processor),\n );\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while postprocessing`,\n e,\n );\n }\n return innerRes;\n });\n }\n }\n\n return res;\n });\n }\n}\n"],"names":["trace","TRACER_ID","ProcessorOutputCollector","ProcessorCacheManager","isObject","validateEntityEnvelope","InputError","stringifyEntityRef","parseLocationRef","getEntityLocationRef","getEntityOriginLocationRef","isLocationEntity","NotAllowedError","stringifyLocationRef","toError","withActiveSpan","addEntityAttributes","ConflictError","validateEntity","path","processingResult","toAbsoluteUrl"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultCatalogProcessingOrchestrator.cjs.js","sources":["../../src/processing/DefaultCatalogProcessingOrchestrator.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 { Span, trace } from '@opentelemetry/api';\nimport {\n Entity,\n EntityPolicy,\n LocationEntity,\n parseLocationRef,\n stringifyEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n toError,\n} from '@backstage/errors';\nimport { JsonValue } from '@backstage/types';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport path from 'node:path';\nimport { LocationSpec } from '@backstage/plugin-catalog-common';\nimport {\n CatalogProcessor,\n CatalogProcessorParser,\n processingResult,\n} from '@backstage/plugin-catalog-node';\nimport {\n CatalogProcessingOrchestrator,\n EntityProcessingRequest,\n EntityProcessingResult,\n} from './types';\nimport { ProcessorOutputCollector } from './ProcessorOutputCollector';\nimport {\n getEntityLocationRef,\n getEntityOriginLocationRef,\n isLocationEntity,\n isObject,\n toAbsoluteUrl,\n validateEntity,\n validateEntityEnvelope,\n} from './util';\nimport { CatalogRulesEnforcer } from '../ingestion/CatalogRules';\nimport { ProcessorCacheManager } from './ProcessorCacheManager';\nimport {\n addEntityAttributes,\n TRACER_ID,\n withActiveSpan,\n} from '../util/opentelemetry';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst tracer = trace.getTracer(TRACER_ID);\n\ntype Context = {\n entityRef: string;\n location: LocationSpec;\n originLocation: LocationSpec;\n collector: ProcessorOutputCollector;\n cache: ProcessorCacheManager;\n};\n\nfunction addProcessorAttributes(\n span: Span,\n stage: string,\n processor: CatalogProcessor,\n) {\n span.setAttribute('backstage.catalog.processor.stage', stage);\n span.setAttribute(\n 'backstage.catalog.processor.name',\n processor.getProcessorName(),\n );\n}\n\nexport class DefaultCatalogProcessingOrchestrator\n implements CatalogProcessingOrchestrator\n{\n private readonly options: {\n processors: CatalogProcessor[];\n integrations: ScmIntegrationRegistry;\n logger: LoggerService;\n parser: CatalogProcessorParser;\n policy: EntityPolicy;\n rulesEnforcer: CatalogRulesEnforcer;\n allowedLocationTypes?: string[];\n };\n\n constructor(options: {\n processors: CatalogProcessor[];\n integrations: ScmIntegrationRegistry;\n logger: LoggerService;\n parser: CatalogProcessorParser;\n policy: EntityPolicy;\n rulesEnforcer: CatalogRulesEnforcer;\n allowedLocationTypes?: string[];\n }) {\n this.options = options;\n }\n\n async process(\n request: EntityProcessingRequest,\n ): Promise<EntityProcessingResult> {\n return this.processSingleEntity(request.entity, request.state);\n }\n\n private async processSingleEntity(\n unprocessedEntity: Entity,\n state: JsonValue | undefined,\n ): Promise<EntityProcessingResult> {\n const collector = new ProcessorOutputCollector(\n this.options.logger,\n unprocessedEntity,\n );\n\n // Cache that is scoped to the entity and processor\n const cache = new ProcessorCacheManager(\n isObject(state) && isObject(state.cache) ? state.cache : {},\n );\n\n try {\n // This will be checked and mutated step by step below\n let entity: Entity = unprocessedEntity;\n\n // NOTE: At this early point, we can only rely on the envelope having to\n // be valid; full entity + kind validation happens after the (potentially\n // mutative) pre-steps. This means that the code below can't make a lot\n // of assumptions about the data despite it using the Entity type.\n try {\n validateEntityEnvelope(entity);\n } catch (e) {\n throw new InputError(\n `Entity envelope failed validation before processing`,\n e,\n );\n }\n\n // TODO: which one do we actually use for the location?\n // source-location? - maybe probably doesn't exist yet?\n const context: Context = {\n entityRef: stringifyEntityRef(entity),\n location: parseLocationRef(getEntityLocationRef(entity)),\n originLocation: parseLocationRef(getEntityOriginLocationRef(entity)),\n cache,\n collector,\n };\n\n // Run the steps\n entity = await this.runPreProcessStep(entity, context);\n entity = await this.runPolicyStep(entity);\n await this.runValidateStep(entity, context);\n if (isLocationEntity(entity)) {\n await this.runSpecialLocationStep(entity, context);\n }\n entity = await this.runPostProcessStep(entity, context);\n\n // Check that any emitted entities are permitted to originate from that\n // particular location according to the catalog rules\n const collectorResults = context.collector.results();\n for (const deferredEntity of collectorResults.deferredEntities) {\n if (\n !this.options.rulesEnforcer.isAllowed(\n deferredEntity.entity,\n context.originLocation,\n )\n ) {\n throw new NotAllowedError(\n `Entity ${stringifyEntityRef(\n deferredEntity.entity,\n )} at ${stringifyLocationRef(\n context.location,\n )}, originated at ${stringifyLocationRef(\n context.originLocation,\n )}, is not of an allowed kind for that location`,\n );\n }\n }\n\n return {\n ...collectorResults,\n completedEntity: entity,\n state: { cache: cache.collect() },\n ok: collectorResults.errors.length === 0,\n };\n } catch (error) {\n const err = toError(error);\n return {\n ok: false,\n errors: collector.results().errors.concat(err),\n };\n }\n }\n\n // Pre-process phase, used to populate entities with data that is required\n // during the main processing step\n private async runPreProcessStep(\n entity: Entity,\n context: Context,\n ): Promise<Entity> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute('backstage.catalog.processor.stage', 'preProcess');\n let res = entity;\n\n for (const processor of this.options.processors) {\n if (processor.preProcessEntity) {\n let innerRes = res;\n res = await withActiveSpan(tracer, 'ProcessingStep', async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'preProcessEntity', processor);\n try {\n innerRes = await processor.preProcessEntity!(\n innerRes,\n context.location,\n context.collector.forProcessor(processor),\n context.originLocation,\n context.cache.forProcessor(processor),\n );\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while preprocessing`,\n e,\n );\n }\n return innerRes;\n });\n }\n }\n\n return res;\n });\n }\n\n /**\n * Enforce entity policies making sure that entities conform to a general schema\n */\n private async runPolicyStep(entity: Entity): Promise<Entity> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute(\n 'backstage.catalog.processor.stage',\n 'enforcePolicy',\n );\n let policyEnforcedEntity: Entity | undefined;\n\n try {\n policyEnforcedEntity = await this.options.policy.enforce(entity);\n } catch (e) {\n throw new InputError(\n `Policy check failed for ${stringifyEntityRef(entity)}`,\n e,\n );\n }\n\n if (!policyEnforcedEntity) {\n throw new Error(\n `Policy unexpectedly returned no data for ${stringifyEntityRef(\n entity,\n )}`,\n );\n }\n\n return policyEnforcedEntity;\n });\n }\n\n /**\n * Validate the given entity\n */\n private async runValidateStep(\n entity: Entity,\n context: Context,\n ): Promise<void> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute('backstage.catalog.processor.stage', 'validate');\n // Double check that none of the previous steps tried to change something\n // related to the entity ref, which would break downstream\n if (stringifyEntityRef(entity) !== context.entityRef) {\n throw new ConflictError(\n 'Fatal: The entity kind, namespace, or name changed during processing',\n );\n }\n\n // Validate that the end result is a valid Entity at all\n try {\n validateEntity(entity);\n } catch (e) {\n throw new ConflictError(\n `Entity envelope for ${context.entityRef} failed validation after preprocessing`,\n e,\n );\n }\n\n let valid = false;\n\n for (const processor of this.options.processors) {\n if (processor.validateEntityKind) {\n try {\n const thisValid = await withActiveSpan(\n tracer,\n 'ProcessingStep',\n async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'validateEntityKind', processor);\n return await processor.validateEntityKind!(entity);\n },\n );\n if (thisValid) {\n valid = true;\n }\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while validating the entity ${context.entityRef}`,\n e,\n );\n }\n }\n }\n\n if (!valid) {\n throw new InputError(\n `No processor recognized the entity ${context.entityRef} as valid, possibly caused by a foreign kind or apiVersion`,\n );\n }\n });\n }\n\n /**\n * Backwards compatible processing of location entities\n */\n private async runSpecialLocationStep(\n entity: LocationEntity,\n context: Context,\n ): Promise<void> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute(\n 'backstage.catalog.processor.stage',\n 'readLocation',\n );\n const { type = context.location.type, presence = 'required' } =\n entity.spec;\n\n const { allowedLocationTypes } = this.options;\n if (\n allowedLocationTypes &&\n type !== context.location.type &&\n !allowedLocationTypes.includes(type)\n ) {\n context.collector.generic()(\n processingResult.inputError(\n context.location,\n `Registered locations must be of an allowed type ${JSON.stringify(\n allowedLocationTypes,\n )}`,\n ),\n );\n return;\n }\n\n const targets = new Array<string>();\n if (entity.spec.target) {\n targets.push(entity.spec.target);\n }\n if (entity.spec.targets) {\n targets.push(...entity.spec.targets);\n }\n\n for (const maybeRelativeTarget of targets) {\n if (type === 'file' && maybeRelativeTarget.endsWith(path.sep)) {\n context.collector.generic()(\n processingResult.inputError(\n context.location,\n `LocationEntityProcessor cannot handle ${type} type location with target ${context.location.target} that ends with a path separator`,\n ),\n );\n continue;\n }\n const target = toAbsoluteUrl(\n this.options.integrations,\n context.location,\n type,\n maybeRelativeTarget,\n );\n\n let didRead = false;\n for (const processor of this.options.processors) {\n if (processor.readLocation) {\n try {\n const read = await withActiveSpan(\n tracer,\n 'ProcessingStep',\n async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'readLocation', processor);\n return await processor.readLocation!(\n {\n type,\n target,\n presence,\n },\n presence === 'optional',\n context.collector.forProcessor(processor),\n this.options.parser,\n context.cache.forProcessor(processor, target),\n );\n },\n );\n if (read) {\n didRead = true;\n break;\n }\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while reading ${type}:${target}`,\n e,\n );\n }\n }\n }\n if (!didRead) {\n throw new InputError(\n `No processor was able to handle reading of ${type}:${target}`,\n );\n }\n }\n });\n }\n\n /**\n * Main processing step of the entity\n */\n private async runPostProcessStep(\n entity: Entity,\n context: Context,\n ): Promise<Entity> {\n return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => {\n addEntityAttributes(stageSpan, entity);\n stageSpan.setAttribute(\n 'backstage.catalog.processor.stage',\n 'postProcessEntity',\n );\n let res = entity;\n\n for (const processor of this.options.processors) {\n if (processor.postProcessEntity) {\n let innerRes = res;\n res = await withActiveSpan(tracer, 'ProcessingStep', async span => {\n addEntityAttributes(span, entity);\n addProcessorAttributes(span, 'postProcessEntity', processor);\n try {\n innerRes = await processor.postProcessEntity!(\n innerRes,\n context.location,\n context.collector.forProcessor(processor),\n context.cache.forProcessor(processor),\n );\n } catch (e) {\n throw new InputError(\n `Processor ${processor.constructor.name} threw an error while postprocessing`,\n e,\n );\n }\n return innerRes;\n });\n }\n }\n\n return res;\n });\n }\n}\n"],"names":["trace","TRACER_ID","ProcessorOutputCollector","ProcessorCacheManager","isObject","validateEntityEnvelope","InputError","stringifyEntityRef","parseLocationRef","getEntityLocationRef","getEntityOriginLocationRef","isLocationEntity","NotAllowedError","stringifyLocationRef","toError","withActiveSpan","addEntityAttributes","ConflictError","validateEntity","processingResult","path","toAbsoluteUrl"],"mappings":"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"}
@@ -1,10 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ var parseGitUrl = require('git-url-parse');
3
4
  var yaml = require('yaml');
4
5
  var pluginCatalogNode = require('@backstage/plugin-catalog-node');
5
6
 
6
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
8
 
9
+ var parseGitUrl__default = /*#__PURE__*/_interopDefaultCompat(parseGitUrl);
8
10
  var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
9
11
 
10
12
  class PlaceholderProcessor {
@@ -119,6 +121,24 @@ async function readTextLocation(params) {
119
121
  );
120
122
  }
121
123
  }
124
+ function assertSameRepository(resolvedUrl, baseUrl) {
125
+ let resolved;
126
+ let base;
127
+ try {
128
+ resolved = parseGitUrl__default.default(resolvedUrl);
129
+ base = parseGitUrl__default.default(baseUrl);
130
+ } catch {
131
+ return;
132
+ }
133
+ if (!resolved.owner || !resolved.name || !resolved.filepath || !base.owner || !base.name || !base.filepath) {
134
+ return;
135
+ }
136
+ if (resolved.resource !== base.resource || resolved.full_name !== base.full_name) {
137
+ throw new Error(
138
+ `Placeholder may only reference files from the same repository as the entity`
139
+ );
140
+ }
141
+ }
122
142
  function relativeUrl({
123
143
  key,
124
144
  value,
@@ -131,7 +151,9 @@ function relativeUrl({
131
151
  );
132
152
  }
133
153
  try {
134
- return resolveUrl(value, baseUrl);
154
+ const resolved = resolveUrl(value, baseUrl);
155
+ assertSameRepository(resolved, baseUrl);
156
+ return resolved;
135
157
  } catch (e) {
136
158
  throw new Error(
137
159
  `Placeholder $${key} could not form a URL out of ${baseUrl} and ${value}, ${e}`
@@ -1 +1 @@
1
- {"version":3,"file":"PlaceholderProcessor.cjs.js","sources":["../../src/processors/PlaceholderProcessor.ts"],"sourcesContent":["/*\n * Copyright 2020 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 { Entity } from '@backstage/catalog-model';\nimport { JsonValue } from '@backstage/types';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport yaml from 'yaml';\nimport { LocationSpec } from '@backstage/plugin-catalog-common';\nimport {\n CatalogProcessor,\n CatalogProcessorEmit,\n PlaceholderResolver,\n PlaceholderResolverParams,\n processingResult,\n} from '@backstage/plugin-catalog-node';\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\n\n/** @public */\nexport type PlaceholderProcessorOptions = {\n resolvers: Record<string, PlaceholderResolver>;\n reader: UrlReaderService;\n integrations: ScmIntegrationRegistry;\n};\n\n/**\n * Traverses raw entity JSON looking for occurrences of $-prefixed placeholders\n * that it then fills in with actual data.\n * @public\n */\nexport class PlaceholderProcessor implements CatalogProcessor {\n private readonly options: PlaceholderProcessorOptions;\n\n constructor(options: PlaceholderProcessorOptions) {\n this.options = options;\n }\n\n getProcessorName(): string {\n return 'PlaceholderProcessor';\n }\n\n async preProcessEntity(\n entity: Entity,\n location: LocationSpec,\n emit: CatalogProcessorEmit,\n ): Promise<Entity> {\n const process = async (data: any): Promise<[any, boolean]> => {\n if (!data || !(data instanceof Object)) {\n // Scalars can't have placeholders\n return [data, false];\n }\n\n if (Array.isArray(data)) {\n // We're an array - process all entries recursively\n const items = await Promise.all(data.map(item => process(item)));\n return items.every(([, changed]) => !changed)\n ? [data, false]\n : [items.map(([item]) => item), true];\n }\n\n const keys = Object.keys(data);\n if (!keys.some(k => k.startsWith('$'))) {\n // We're an object but no placeholders at this level - process all\n // entries recursively\n const entries = await Promise.all(\n Object.entries(data).map(([k, v]) =>\n process(v).then(vp => [k, vp] as const),\n ),\n );\n return entries.every(([, [, changed]]) => !changed)\n ? [data, false]\n : [Object.fromEntries(entries.map(([k, [v]]) => [k, v])), true];\n } else if (keys.length !== 1) {\n // This was an object that had more than one key, some of which were\n // dollar prefixed. We only handle the case where there is exactly one\n // such key; anything else is left alone.\n return [data, false];\n }\n\n const resolverKey = keys[0].substring(1);\n const resolverValue = data[keys[0]];\n\n const resolver = this.options.resolvers[resolverKey];\n if (!resolver) {\n // If there was no such placeholder resolver, we err on the side of safety\n // and assume that this is something that's best left alone. For example, if\n // the input contains JSONSchema, there may be \"$ref\": \"#/definitions/node\"\n // nodes in the document.\n return [data, false];\n }\n\n const read = async (url: string): Promise<Buffer> => {\n const response = await this.options.reader.readUrl(url);\n const buffer = await response.buffer();\n return buffer;\n };\n\n const resolveUrl = (url: string, base: string): string =>\n this.options.integrations.resolveUrl({\n url,\n base,\n });\n\n return [\n await resolver({\n key: resolverKey,\n value: resolverValue,\n baseUrl: location.target,\n read,\n resolveUrl,\n emit,\n }),\n true,\n ];\n };\n\n const [result] = await process(entity);\n return result;\n }\n}\n\n/*\n * Resolvers\n */\n\nexport async function yamlPlaceholderResolver(\n params: PlaceholderResolverParams,\n): Promise<JsonValue> {\n const { content, url } = await readTextLocation(params);\n\n params.emit(processingResult.refresh(`url:${url}`));\n\n // YAML merge support enabled by default\n const enableYamlMerge = false;\n const parseOptions = { merge: enableYamlMerge };\n\n let documents: yaml.Document.Parsed[];\n try {\n documents = yaml.parseAllDocuments(content, parseOptions).filter(d => d);\n } catch (e) {\n throw new Error(\n `Placeholder \\$${params.key} failed to parse YAML data at ${params.value}, ${e}`,\n );\n }\n\n if (documents.length !== 1) {\n throw new Error(\n `Placeholder \\$${params.key} expected to find exactly one document of data at ${params.value}, found ${documents.length}`,\n );\n }\n\n const document = documents[0];\n\n if (document.errors?.length) {\n throw new Error(\n `Placeholder \\$${params.key} found an error in the data at ${params.value}, ${document.errors[0]}`,\n );\n }\n\n return document.toJSON();\n}\n\nexport async function jsonPlaceholderResolver(\n params: PlaceholderResolverParams,\n): Promise<JsonValue> {\n const { content, url } = await readTextLocation(params);\n\n params.emit(processingResult.refresh(`url:${url}`));\n\n try {\n return JSON.parse(content);\n } catch (e) {\n throw new Error(\n `Placeholder \\$${params.key} failed to parse JSON data at ${params.value}, ${e}`,\n );\n }\n}\n\nexport async function textPlaceholderResolver(\n params: PlaceholderResolverParams,\n): Promise<JsonValue> {\n const { content, url } = await readTextLocation(params);\n\n params.emit(processingResult.refresh(`url:${url}`));\n\n return content;\n}\n\n/*\n * Helpers\n */\n\nasync function readTextLocation(\n params: PlaceholderResolverParams,\n): Promise<{ content: string; url: string }> {\n const newUrl = relativeUrl(params);\n\n try {\n const data = await params.read(newUrl);\n return { content: data.toString('utf-8'), url: newUrl };\n } catch (e) {\n throw new Error(\n `Placeholder \\$${params.key} could not read location ${params.value}, ${e}`,\n );\n }\n}\n\nfunction relativeUrl({\n key,\n value,\n baseUrl,\n resolveUrl,\n}: PlaceholderResolverParams): string {\n if (typeof value !== 'string') {\n throw new Error(\n `Placeholder \\$${key} expected a string value parameter, in the form of an absolute URL or a relative path`,\n );\n }\n\n try {\n return resolveUrl(value, baseUrl);\n } catch (e) {\n // The only remaining case that isn't support is a relative file path that should be\n // resolved using a relative file location. Accessing local file paths can lead to\n // path traversal attacks and access to any file on the host system. Implementing this\n // would require additional security measures.\n throw new Error(\n `Placeholder \\$${key} could not form a URL out of ${baseUrl} and ${value}, ${e}`,\n );\n }\n}\n"],"names":["processingResult","yaml"],"mappings":"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"}
1
+ {"version":3,"file":"PlaceholderProcessor.cjs.js","sources":["../../src/processors/PlaceholderProcessor.ts"],"sourcesContent":["/*\n * Copyright 2020 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 { Entity } from '@backstage/catalog-model';\nimport { JsonValue } from '@backstage/types';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport parseGitUrl from 'git-url-parse';\nimport yaml from 'yaml';\nimport { LocationSpec } from '@backstage/plugin-catalog-common';\nimport {\n CatalogProcessor,\n CatalogProcessorEmit,\n PlaceholderResolver,\n PlaceholderResolverParams,\n processingResult,\n} from '@backstage/plugin-catalog-node';\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\n\n/** @public */\nexport type PlaceholderProcessorOptions = {\n resolvers: Record<string, PlaceholderResolver>;\n reader: UrlReaderService;\n integrations: ScmIntegrationRegistry;\n};\n\n/**\n * Traverses raw entity JSON looking for occurrences of $-prefixed placeholders\n * that it then fills in with actual data.\n * @public\n */\nexport class PlaceholderProcessor implements CatalogProcessor {\n private readonly options: PlaceholderProcessorOptions;\n\n constructor(options: PlaceholderProcessorOptions) {\n this.options = options;\n }\n\n getProcessorName(): string {\n return 'PlaceholderProcessor';\n }\n\n async preProcessEntity(\n entity: Entity,\n location: LocationSpec,\n emit: CatalogProcessorEmit,\n ): Promise<Entity> {\n const process = async (data: any): Promise<[any, boolean]> => {\n if (!data || !(data instanceof Object)) {\n // Scalars can't have placeholders\n return [data, false];\n }\n\n if (Array.isArray(data)) {\n // We're an array - process all entries recursively\n const items = await Promise.all(data.map(item => process(item)));\n return items.every(([, changed]) => !changed)\n ? [data, false]\n : [items.map(([item]) => item), true];\n }\n\n const keys = Object.keys(data);\n if (!keys.some(k => k.startsWith('$'))) {\n // We're an object but no placeholders at this level - process all\n // entries recursively\n const entries = await Promise.all(\n Object.entries(data).map(([k, v]) =>\n process(v).then(vp => [k, vp] as const),\n ),\n );\n return entries.every(([, [, changed]]) => !changed)\n ? [data, false]\n : [Object.fromEntries(entries.map(([k, [v]]) => [k, v])), true];\n } else if (keys.length !== 1) {\n // This was an object that had more than one key, some of which were\n // dollar prefixed. We only handle the case where there is exactly one\n // such key; anything else is left alone.\n return [data, false];\n }\n\n const resolverKey = keys[0].substring(1);\n const resolverValue = data[keys[0]];\n\n const resolver = this.options.resolvers[resolverKey];\n if (!resolver) {\n // If there was no such placeholder resolver, we err on the side of safety\n // and assume that this is something that's best left alone. For example, if\n // the input contains JSONSchema, there may be \"$ref\": \"#/definitions/node\"\n // nodes in the document.\n return [data, false];\n }\n\n const read = async (url: string): Promise<Buffer> => {\n const response = await this.options.reader.readUrl(url);\n const buffer = await response.buffer();\n return buffer;\n };\n\n const resolveUrl = (url: string, base: string): string =>\n this.options.integrations.resolveUrl({\n url,\n base,\n });\n\n return [\n await resolver({\n key: resolverKey,\n value: resolverValue,\n baseUrl: location.target,\n read,\n resolveUrl,\n emit,\n }),\n true,\n ];\n };\n\n const [result] = await process(entity);\n return result;\n }\n}\n\n/*\n * Resolvers\n */\n\nexport async function yamlPlaceholderResolver(\n params: PlaceholderResolverParams,\n): Promise<JsonValue> {\n const { content, url } = await readTextLocation(params);\n\n params.emit(processingResult.refresh(`url:${url}`));\n\n // YAML merge support enabled by default\n const enableYamlMerge = false;\n const parseOptions = { merge: enableYamlMerge };\n\n let documents: yaml.Document.Parsed[];\n try {\n documents = yaml.parseAllDocuments(content, parseOptions).filter(d => d);\n } catch (e) {\n throw new Error(\n `Placeholder \\$${params.key} failed to parse YAML data at ${params.value}, ${e}`,\n );\n }\n\n if (documents.length !== 1) {\n throw new Error(\n `Placeholder \\$${params.key} expected to find exactly one document of data at ${params.value}, found ${documents.length}`,\n );\n }\n\n const document = documents[0];\n\n if (document.errors?.length) {\n throw new Error(\n `Placeholder \\$${params.key} found an error in the data at ${params.value}, ${document.errors[0]}`,\n );\n }\n\n return document.toJSON();\n}\n\nexport async function jsonPlaceholderResolver(\n params: PlaceholderResolverParams,\n): Promise<JsonValue> {\n const { content, url } = await readTextLocation(params);\n\n params.emit(processingResult.refresh(`url:${url}`));\n\n try {\n return JSON.parse(content);\n } catch (e) {\n throw new Error(\n `Placeholder \\$${params.key} failed to parse JSON data at ${params.value}, ${e}`,\n );\n }\n}\n\nexport async function textPlaceholderResolver(\n params: PlaceholderResolverParams,\n): Promise<JsonValue> {\n const { content, url } = await readTextLocation(params);\n\n params.emit(processingResult.refresh(`url:${url}`));\n\n return content;\n}\n\n/*\n * Helpers\n */\n\nasync function readTextLocation(\n params: PlaceholderResolverParams,\n): Promise<{ content: string; url: string }> {\n const newUrl = relativeUrl(params);\n\n try {\n const data = await params.read(newUrl);\n return { content: data.toString('utf-8'), url: newUrl };\n } catch (e) {\n throw new Error(\n `Placeholder \\$${params.key} could not read location ${params.value}, ${e}`,\n );\n }\n}\n\nfunction assertSameRepository(resolvedUrl: string, baseUrl: string): void {\n let resolved;\n let base;\n try {\n resolved = parseGitUrl(resolvedUrl);\n base = parseGitUrl(baseUrl);\n } catch {\n return;\n }\n\n if (\n !resolved.owner ||\n !resolved.name ||\n !resolved.filepath ||\n !base.owner ||\n !base.name ||\n !base.filepath\n ) {\n return;\n }\n\n if (\n resolved.resource !== base.resource ||\n resolved.full_name !== base.full_name\n ) {\n throw new Error(\n `Placeholder may only reference files from the same repository as the entity`,\n );\n }\n}\n\nfunction relativeUrl({\n key,\n value,\n baseUrl,\n resolveUrl,\n}: PlaceholderResolverParams): string {\n if (typeof value !== 'string') {\n throw new Error(\n `Placeholder \\$${key} expected a string value parameter, in the form of an absolute URL or a relative path`,\n );\n }\n\n try {\n const resolved = resolveUrl(value, baseUrl);\n assertSameRepository(resolved, baseUrl);\n return resolved;\n } catch (e) {\n // The only remaining case that isn't support is a relative file path that should be\n // resolved using a relative file location. Accessing local file paths can lead to\n // path traversal attacks and access to any file on the host system. Implementing this\n // would require additional security measures.\n throw new Error(\n `Placeholder \\$${key} could not form a URL out of ${baseUrl} and ${value}, ${e}`,\n );\n }\n}\n"],"names":["processingResult","yaml","parseGitUrl"],"mappings":"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"}
@@ -304,7 +304,8 @@ class CatalogBuilder {
304
304
  rulesEnforcer,
305
305
  logger,
306
306
  parser,
307
- policy
307
+ policy,
308
+ allowedLocationTypes: this.allowedLocationType
308
309
  });
309
310
  const entitiesCatalog = new AuthorizedEntitiesCatalog.AuthorizedEntitiesCatalog(
310
311
  unauthorizedEntitiesCatalog,
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogBuilder.cjs.js","sources":["../../src/service/CatalogBuilder.ts"],"sourcesContent":["/*\n * Copyright 2020 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 DefaultNamespaceEntityPolicy,\n Entity,\n EntityPolicies,\n EntityPolicy,\n FieldFormatEntityPolicy,\n makeValidator,\n NoForeignRootFieldsEntityPolicy,\n SchemaValidEntityPolicy,\n Validators,\n} from '@backstage/catalog-model';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { createHash } from 'node:crypto';\nimport { Router } from 'express';\nimport lodash from 'lodash';\n\nimport {\n AuditorService,\n AuthService,\n DatabaseService,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n RootConfigService,\n SchedulerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { catalogPermissions } from '@backstage/plugin-catalog-common/alpha';\nimport {\n CatalogProcessor,\n CatalogProcessorParser,\n LocationAnalyzer,\n PlaceholderResolver,\n ScmLocationAnalyzer,\n} from '@backstage/plugin-catalog-node';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { createConditionTransformer } from '@backstage/plugin-permission-node';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { DefaultCatalogDatabase } from '../database/DefaultCatalogDatabase';\nimport { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase';\nimport { DefaultProviderDatabase } from '../database/DefaultProviderDatabase';\nimport { applyDatabaseMigrations } from '../database/migrations';\nimport { DefaultCatalogRulesEnforcer } from '../ingestion/CatalogRules';\nimport { RepoLocationAnalyzer } from '../ingestion/LocationAnalyzer';\nimport { permissionRules as catalogPermissionRules } from '../permissions/rules';\nimport { CatalogProcessingEngine } from '../processing/types';\nimport {\n createRandomProcessingInterval,\n ProcessingIntervalFunction,\n} from '../processing/refresh';\nimport {\n connectEntityProviders,\n EntityProviderEntry,\n} from '../processing/connectEntityProviders';\nimport { evictEntitiesFromOrphanedProviders } from '../processing/evictEntitiesFromOrphanedProviders';\nimport { DefaultCatalogProcessingEngine } from '../processing/DefaultCatalogProcessingEngine';\nimport { DefaultCatalogProcessingOrchestrator } from '../processing/DefaultCatalogProcessingOrchestrator';\nimport {\n AnnotateLocationEntityProcessor,\n BuiltinKindsEntityProcessor,\n FileReaderProcessor,\n PlaceholderProcessor,\n UrlReaderProcessor,\n} from '../processors';\nimport {\n jsonPlaceholderResolver,\n textPlaceholderResolver,\n yamlPlaceholderResolver,\n} from '../processors/PlaceholderProcessor';\nimport { ConfigLocationEntityProvider } from '../providers/ConfigLocationEntityProvider';\nimport { DefaultLocationStore } from '../providers/DefaultLocationStore';\nimport { DefaultStitcher } from '../stitching/DefaultStitcher';\nimport { defaultEntityDataParser } from '../util/parse';\nimport { AuthorizedEntitiesCatalog } from './AuthorizedEntitiesCatalog';\nimport { AuthorizedLocationAnalyzer } from './AuthorizedLocationAnalyzer';\nimport { AuthorizedLocationService } from './AuthorizedLocationService';\nimport { AuthorizedRefreshService } from './AuthorizedRefreshService';\nimport { createRouter } from './createRouter';\nimport { DefaultEntitiesCatalog } from './DefaultEntitiesCatalog';\nimport { DefaultLocationService } from './DefaultLocationService';\nimport { DefaultRefreshService } from './DefaultRefreshService';\nimport { entitiesResponseToObjects } from './response';\nimport {\n catalogEntityPermissionResourceRef,\n CatalogScmEventsService,\n} from '@backstage/plugin-catalog-node/alpha';\nimport { filterAndSortProcessors, filterProviders } from './util';\nimport { GenericScmEventRefreshProvider } from '../providers/GenericScmEventRefreshProvider';\nimport { readScmEventHandlingConfig } from '../util/readScmEventHandlingConfig';\nimport { MetricsService } from '@backstage/backend-plugin-api/alpha';\nimport { ModelProcessor } from '../processors/ModelProcessor';\nimport { ModelHolder } from '../model/ModelHolder';\n\nexport type CatalogEnvironment = {\n logger: LoggerService;\n modelHolder?: ModelHolder;\n database: DatabaseService;\n config: RootConfigService;\n reader: UrlReaderService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n scheduler: SchedulerService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n events: EventsService;\n catalogScmEvents: CatalogScmEventsService;\n metrics: MetricsService;\n};\n\n/**\n * A builder that helps wire up all of the component parts of the catalog.\n *\n * The touch points where you can replace or extend behavior are as follows:\n *\n * - Entity policies can be added or replaced. These are automatically run\n * after the processors' pre-processing steps. All policies are given the\n * chance to inspect the entity, and all of them have to pass in order for\n * the entity to be considered valid from an overall point of view.\n * - Location analyzers can be added. These are responsible for analyzing\n * repositories when onboarding them into the catalog, by finding\n * catalog-info.yaml files and other artifacts that can help automatically\n * register or create catalog data on the user's behalf.\n * - Placeholder resolvers can be replaced or added. These run on the raw\n * structured data between the parsing and pre-processing steps, to replace\n * dollar-prefixed entries with their actual values (like $file).\n * - Field format validators can be replaced. These check the format of\n * individual core fields such as metadata.name, to ensure that they adhere\n * to certain rules.\n * - Processors can be added or replaced. These implement the functionality of\n * reading, parsing, validating, and processing the entity data before it is\n * persisted in the catalog.\n *\n * @internal\n */\nexport class CatalogBuilder {\n private readonly env: CatalogEnvironment;\n private entityPolicies: EntityPolicy[];\n private entityPoliciesReplace: boolean;\n private placeholderResolvers: Record<string, PlaceholderResolver>;\n private fieldFormatValidators: Partial<Validators>;\n private entityProviders: EntityProviderEntry[];\n private processors: CatalogProcessor[];\n private locationAnalyzers: ScmLocationAnalyzer[];\n private processorsReplace: boolean;\n private parser: CatalogProcessorParser | undefined;\n private onProcessingError?: (event: {\n unprocessedEntity: Entity;\n errors: Error[];\n }) => Promise<void> | void;\n private processingInterval: ProcessingIntervalFunction;\n private locationAnalyzer: LocationAnalyzer | undefined = undefined;\n private allowedLocationType: string[];\n\n /**\n * Creates a catalog builder.\n */\n static create(env: CatalogEnvironment): CatalogBuilder {\n return new CatalogBuilder(env);\n }\n\n private constructor(env: CatalogEnvironment) {\n this.env = env;\n this.entityPolicies = [];\n this.entityPoliciesReplace = false;\n this.placeholderResolvers = {};\n this.fieldFormatValidators = {};\n this.entityProviders = [];\n this.processors = [];\n this.locationAnalyzers = [];\n this.processorsReplace = false;\n this.parser = undefined;\n this.allowedLocationType = ['url'];\n\n this.processingInterval = CatalogBuilder.getDefaultProcessingInterval(\n env.config,\n );\n }\n\n /**\n * Adds policies that are used to validate entities between the pre-\n * processing and post-processing stages. All such policies must pass for the\n * entity to be considered valid.\n *\n * If what you want to do is to replace the rules for what format is allowed\n * in various core entity fields (such as metadata.name), you may want to use\n * {@link CatalogBuilder#setFieldFormatValidators} instead.\n *\n * @param policies - One or more policies\n */\n addEntityPolicy(\n ...policies: Array<EntityPolicy | Array<EntityPolicy>>\n ): CatalogBuilder {\n this.entityPolicies.push(...policies.flat());\n return this;\n }\n\n /**\n * Overwrites the default location analyzer.\n */\n setLocationAnalyzer(locationAnalyzer: LocationAnalyzer): CatalogBuilder {\n this.locationAnalyzer = locationAnalyzer;\n return this;\n }\n\n /**\n * Sets what policies to use for validation of entities between the pre-\n * processing and post-processing stages. All such policies must pass for the\n * entity to be considered valid.\n *\n * If what you want to do is to replace the rules for what format is allowed\n * in various core entity fields (such as metadata.name), you may want to use\n * {@link CatalogBuilder#setFieldFormatValidators} instead.\n *\n * This function replaces the default set of policies; use with care.\n *\n * @param policies - One or more policies\n */\n replaceEntityPolicies(policies: EntityPolicy[]): CatalogBuilder {\n this.entityPolicies = [...policies];\n this.entityPoliciesReplace = true;\n return this;\n }\n\n /**\n * Adds, or overwrites, a handler for placeholders (e.g. $file) in entity\n * definition files.\n *\n * @param key - The key that identifies the placeholder, e.g. \"file\"\n * @param resolver - The resolver that gets values for this placeholder\n */\n setPlaceholderResolver(\n key: string,\n resolver: PlaceholderResolver,\n ): CatalogBuilder {\n this.placeholderResolvers[key] = resolver;\n return this;\n }\n\n /**\n * Sets the validator function to use for one or more special fields of an\n * entity. This is useful if the default rules for formatting of fields are\n * not sufficient.\n *\n * This function has no effect if used together with\n * {@link CatalogBuilder#replaceEntityPolicies}.\n *\n * @param validators - The (subset of) validators to set\n */\n setFieldFormatValidators(validators: Partial<Validators>): CatalogBuilder {\n lodash.merge(this.fieldFormatValidators, validators);\n return this;\n }\n\n /**\n * Adds or replaces entity providers. These are responsible for bootstrapping\n * the list of entities out of original data sources. For example, there is\n * one entity source for the config locations, and one for the database\n * stored locations. If you ingest entities out of a third party system, you\n * may want to implement that in terms of an entity provider as well.\n *\n * @param providers - One or more entity providers\n */\n addEntityProvider(\n ...providers: Array<EntityProviderEntry | Array<EntityProviderEntry>>\n ): CatalogBuilder {\n this.entityProviders.push(...providers.flat());\n return this;\n }\n\n /**\n * Adds entity processors. These are responsible for reading, parsing, and\n * processing entities before they are persisted in the catalog.\n *\n * @param processors - One or more processors\n */\n addProcessor(\n ...processors: Array<CatalogProcessor | Array<CatalogProcessor>>\n ): CatalogBuilder {\n this.processors.push(...processors.flat());\n return this;\n }\n\n /**\n * Sets what entity processors to use. These are responsible for reading,\n * parsing, and processing entities before they are persisted in the catalog.\n *\n * This function replaces the default set of processors, consider using with\n * {@link CatalogBuilder#getDefaultProcessors}; use with care.\n *\n * @param processors - One or more processors\n */\n replaceProcessors(processors: CatalogProcessor[]): CatalogBuilder {\n this.processors = [...processors];\n this.processorsReplace = true;\n return this;\n }\n\n /**\n * Returns the default list of entity processors. These are responsible for reading,\n * parsing, and processing entities before they are persisted in the catalog. Changing\n * the order of processing can give more control to custom processors.\n *\n * Consider using with {@link CatalogBuilder#replaceProcessors}\n *\n */\n getDefaultProcessors(): CatalogProcessor[] {\n const { config, logger, reader } = this.env;\n const integrations = ScmIntegrations.fromConfig(config);\n\n return [\n new FileReaderProcessor(),\n new UrlReaderProcessor({ reader, logger }),\n new AnnotateLocationEntityProcessor({ integrations }),\n ];\n }\n\n /**\n * Adds Location Analyzers. These are responsible for analyzing\n * repositories when onboarding them into the catalog, by finding\n * catalog-info.yaml files and other artifacts that can help automatically\n * register or create catalog data on the user's behalf.\n *\n * @param locationAnalyzers - One or more location analyzers\n */\n addLocationAnalyzers(\n ...analyzers: Array<ScmLocationAnalyzer | Array<ScmLocationAnalyzer>>\n ): CatalogBuilder {\n this.locationAnalyzers.push(...analyzers.flat());\n return this;\n }\n\n /**\n * Sets up the catalog to use a custom parser for entity data.\n *\n * This is the function that gets called immediately after some raw entity\n * specification data has been read from a remote source, and needs to be\n * parsed and emitted as structured data.\n *\n * @param parser - The custom parser\n */\n setEntityDataParser(parser: CatalogProcessorParser): CatalogBuilder {\n this.parser = parser;\n return this;\n }\n\n /**\n * Sets up the allowed location types from being registered via the location service.\n *\n * @param allowedLocationTypes - the allowed location types\n */\n setAllowedLocationTypes(allowedLocationTypes: string[]): CatalogBuilder {\n this.allowedLocationType = allowedLocationTypes;\n return this;\n }\n\n /**\n * Wires up and returns all of the component parts of the catalog\n */\n async build(): Promise<{\n processingEngine: CatalogProcessingEngine;\n router: Router;\n }> {\n const {\n config,\n database,\n logger,\n permissions,\n scheduler,\n permissionsRegistry,\n auditor,\n auth,\n httpAuth,\n events,\n catalogScmEvents,\n metrics,\n } = this.env;\n\n const enableRelationsCompatibility = Boolean(\n config.getOptionalBoolean('catalog.enableRelationsCompatibility'),\n );\n\n const policy = this.buildEntityPolicy();\n const processors = this.buildProcessors();\n const parser = this.parser || defaultEntityDataParser;\n\n const dbClient = await database.getClient();\n if (!database.migrations?.skip) {\n logger.info('Performing database migration');\n await applyDatabaseMigrations(dbClient);\n }\n\n const stitcher = DefaultStitcher.fromConfig(config, {\n knex: dbClient,\n logger,\n metrics,\n });\n\n const processingDatabase = new DefaultProcessingDatabase({\n database: dbClient,\n logger,\n events,\n refreshInterval: this.processingInterval,\n metrics,\n });\n const providerDatabase = new DefaultProviderDatabase({\n database: dbClient,\n logger,\n });\n const catalogDatabase = new DefaultCatalogDatabase({\n database: dbClient,\n logger,\n });\n const integrations = ScmIntegrations.fromConfig(config);\n const rulesEnforcer = DefaultCatalogRulesEnforcer.fromConfig(config);\n\n const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog({\n database: dbClient,\n logger,\n enableRelationsCompatibility,\n });\n\n const orchestrator = new DefaultCatalogProcessingOrchestrator({\n processors,\n integrations,\n rulesEnforcer,\n logger,\n parser,\n policy,\n });\n\n const entitiesCatalog = new AuthorizedEntitiesCatalog(\n unauthorizedEntitiesCatalog,\n permissions,\n createConditionTransformer(\n permissionsRegistry.getPermissionRuleset(\n catalogEntityPermissionResourceRef,\n ),\n ),\n );\n\n const getResources = async (resourceRefs: string[]) => {\n const { items } = await unauthorizedEntitiesCatalog.entitiesBatch({\n credentials: await auth.getOwnServiceCredentials(),\n entityRefs: resourceRefs,\n });\n\n return entitiesResponseToObjects(items).map(e => e || undefined);\n };\n\n permissionsRegistry.addResourceType({\n resourceRef: catalogEntityPermissionResourceRef,\n getResources,\n permissions: [...catalogPermissions],\n rules: Object.values(catalogPermissionRules),\n });\n\n const scmEventHandlingConfig = readScmEventHandlingConfig(config);\n const locationStore = new DefaultLocationStore(\n dbClient,\n catalogScmEvents,\n scmEventHandlingConfig,\n );\n const configLocationProvider = new ConfigLocationEntityProvider(config);\n const scmEvents = new GenericScmEventRefreshProvider(\n dbClient,\n catalogScmEvents,\n scmEventHandlingConfig,\n );\n\n const entityProviderEntries = lodash.uniqBy(\n [\n ...this.entityProviders,\n { provider: locationStore },\n { provider: configLocationProvider },\n { provider: scmEvents },\n ],\n entry => entry.provider.getProviderName(),\n );\n const enabledProviderEntries = filterProviders(\n entityProviderEntries,\n config,\n );\n const enabledProviders = enabledProviderEntries.map(\n entry => entry.provider,\n );\n\n const processingEngine = new DefaultCatalogProcessingEngine({\n config,\n scheduler,\n logger,\n knex: dbClient,\n processingDatabase,\n orchestrator,\n createHash: () => createHash('sha1'),\n pollingIntervalMs: 1000,\n onProcessingError: event => {\n this.onProcessingError?.(event);\n },\n events,\n metrics,\n });\n\n const locationAnalyzer =\n this.locationAnalyzer ??\n new AuthorizedLocationAnalyzer(\n new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers),\n permissions,\n );\n const locationService = new AuthorizedLocationService(\n new DefaultLocationService(locationStore, orchestrator, {\n allowedLocationTypes: this.allowedLocationType,\n defaultLocationConflictStrategy:\n (config.getOptionalString(\n 'catalog.defaultLocationConflictStrategy',\n ) as 'refresh' | 'reject') || 'reject',\n }),\n permissions,\n );\n const refreshService = new AuthorizedRefreshService(\n new DefaultRefreshService({ database: catalogDatabase }),\n permissions,\n );\n\n const router = await createRouter({\n entitiesCatalog,\n locationAnalyzer,\n locationService,\n orchestrator,\n refreshService,\n logger,\n config,\n auth,\n httpAuth,\n permissionsService: permissions,\n auditor,\n enableRelationsCompatibility,\n });\n\n await connectEntityProviders(providerDatabase, enabledProviderEntries);\n\n return {\n processingEngine: {\n async start() {\n if (\n config.getOptionalString('catalog.orphanProviderStrategy') !==\n 'keep'\n ) {\n await evictEntitiesFromOrphanedProviders({\n db: providerDatabase,\n providers: enabledProviders,\n logger,\n });\n }\n await processingEngine.start();\n await stitcher.start();\n },\n async stop() {\n await processingEngine.stop();\n await stitcher.stop();\n },\n },\n router,\n };\n }\n\n subscribe(options: {\n onProcessingError: (event: {\n unprocessedEntity: Entity;\n errors: Error[];\n }) => Promise<void> | void;\n }) {\n this.onProcessingError = options.onProcessingError;\n }\n\n private buildEntityPolicy(): EntityPolicy {\n const entityPolicies: EntityPolicy[] = this.entityPoliciesReplace\n ? [new SchemaValidEntityPolicy(), ...this.entityPolicies]\n : [\n new SchemaValidEntityPolicy(),\n new DefaultNamespaceEntityPolicy(),\n new NoForeignRootFieldsEntityPolicy(),\n new FieldFormatEntityPolicy(\n makeValidator(this.fieldFormatValidators),\n ),\n ...this.entityPolicies,\n ];\n\n return EntityPolicies.allOf(entityPolicies);\n }\n\n private buildProcessors(): CatalogProcessor[] {\n const { config, reader } = this.env;\n const integrations = ScmIntegrations.fromConfig(config);\n\n this.checkDeprecatedReaderProcessors();\n\n const placeholderResolvers: Record<string, PlaceholderResolver> = {\n json: jsonPlaceholderResolver,\n yaml: yamlPlaceholderResolver,\n text: textPlaceholderResolver,\n ...this.placeholderResolvers,\n };\n\n // The placeholder is always there no matter what\n const processors: CatalogProcessor[] = [\n new PlaceholderProcessor({\n resolvers: placeholderResolvers,\n reader,\n integrations,\n }),\n ];\n\n const builtinKindsEntityProcessor = new BuiltinKindsEntityProcessor();\n // If the user adds a processor named 'BuiltinKindsEntityProcessor', skip\n // inclusion of the catalog-backend version. Same if there's a model\n // registered - then we are using the new model flow.\n if (\n !this.env.modelHolder &&\n !this.processors.some(\n processor =>\n processor.getProcessorName() ===\n builtinKindsEntityProcessor.getProcessorName(),\n )\n ) {\n processors.push(builtinKindsEntityProcessor);\n }\n if (this.env.modelHolder) {\n processors.push(new ModelProcessor(this.env.modelHolder));\n }\n\n const disableDefaultProcessors = config.getOptionalBoolean(\n 'catalog.disableDefaultProcessors',\n );\n\n // Add default processors if:\n // - processors have NOT been explicitly replaced\n // - and default processors are NOT disabled via config\n if (!this.processorsReplace && !disableDefaultProcessors) {\n processors.push(...this.getDefaultProcessors());\n }\n\n // Add the ones (if any) that the user added\n processors.push(...this.processors);\n\n this.checkMissingExternalProcessors(processors);\n\n return filterAndSortProcessors(processors, config);\n }\n\n // TODO(Rugvip): These old processors are removed, for a while we'll be throwing\n // errors here to make sure people know where to move the config\n private checkDeprecatedReaderProcessors() {\n const pc = this.env.config.getOptionalConfig('catalog.processors');\n if (pc?.has('github')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.github, move to using integrations.github instead`,\n );\n }\n if (pc?.has('gitlabApi')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.gitlabApi, move to using integrations.gitlab instead`,\n );\n }\n if (pc?.has('bitbucketApi')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.bitbucketApi, move to using integrations.bitbucket instead`,\n );\n }\n if (pc?.has('azureApi')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.azureApi, move to using integrations.azure instead`,\n );\n }\n }\n\n // TODO(freben): This can be removed no sooner than June 2022, after adopters have had some time to adapt to the new package structure\n private checkMissingExternalProcessors(processors: CatalogProcessor[]) {\n const skipCheckVarName = 'BACKSTAGE_CATALOG_SKIP_MISSING_PROCESSORS_CHECK';\n if (process.env[skipCheckVarName]) {\n return;\n }\n\n const locationTypes = new Set(\n this.env.config\n .getOptionalConfigArray('catalog.locations')\n ?.map(l => l.getString('type')) ?? [],\n );\n const processorNames = new Set(processors.map(p => p.getProcessorName()));\n\n function check(\n locationType: string,\n processorName: string,\n installationUrl: string,\n ) {\n if (\n locationTypes.has(locationType) &&\n !processorNames.has(processorName)\n ) {\n throw new Error(\n [\n `Your config contains a \"catalog.locations\" entry of type ${locationType},`,\n `but does not have the corresponding catalog processor ${processorName} installed.`,\n `This processor used to be built into the catalog itself, but is now moved to an`,\n `external module that has to be installed manually. Please follow the installation`,\n `instructions at ${installationUrl} if you are using this ability, or remove the`,\n `location from your app config if you do not. You can also silence this check entirely`,\n `by setting the environment variable ${skipCheckVarName} to 'true'.`,\n ].join(' '),\n );\n }\n }\n\n check(\n 'aws-cloud-accounts',\n 'AwsOrganizationCloudAccountProcessor',\n 'https://backstage.io/docs/integrations',\n );\n check(\n 's3-discovery',\n 'AwsS3DiscoveryProcessor',\n 'https://backstage.io/docs/integrations/aws-s3/discovery',\n );\n check(\n 'azure-discovery',\n 'AzureDevOpsDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/azure/discovery',\n );\n check(\n 'bitbucket-discovery',\n 'BitbucketDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/bitbucket/discovery',\n );\n check(\n 'github-discovery',\n 'GithubDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/github/discovery',\n );\n check(\n 'github-org',\n 'GithubOrgReaderProcessor',\n 'https://backstage.io/docs/integrations/github/org',\n );\n check(\n 'gitlab-discovery',\n 'GitLabDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/gitlab/discovery',\n );\n check(\n 'ldap-org',\n 'LdapOrgReaderProcessor',\n 'https://backstage.io/docs/integrations/ldap/org',\n );\n check(\n 'microsoft-graph-org',\n 'MicrosoftGraphOrgReaderProcessor',\n 'https://backstage.io/docs/integrations/azure/org',\n );\n }\n\n private static getDefaultProcessingInterval(\n config: Config,\n ): ProcessingIntervalFunction {\n const processingIntervalKey = 'catalog.processingInterval';\n\n if (!config.has(processingIntervalKey)) {\n return createRandomProcessingInterval({\n minSeconds: 100,\n maxSeconds: 150,\n });\n }\n\n if (!Boolean(config.get('catalog.processingInterval'))) {\n return () => {\n throw new Error(\n 'catalog.processingInterval is set to false, processing is disabled.',\n );\n };\n }\n\n const duration = readDurationFromConfig(config, {\n key: processingIntervalKey,\n });\n\n const seconds = Math.max(\n 1,\n Math.round(durationToMilliseconds(duration) / 1000),\n );\n\n return createRandomProcessingInterval({\n minSeconds: seconds,\n maxSeconds: seconds * 1.5,\n });\n }\n}\n"],"names":["lodash","ScmIntegrations","FileReaderProcessor","UrlReaderProcessor","AnnotateLocationEntityProcessor","defaultEntityDataParser","applyDatabaseMigrations","DefaultStitcher","DefaultProcessingDatabase","DefaultProviderDatabase","DefaultCatalogDatabase","DefaultCatalogRulesEnforcer","DefaultEntitiesCatalog","DefaultCatalogProcessingOrchestrator","AuthorizedEntitiesCatalog","createConditionTransformer","catalogEntityPermissionResourceRef","entitiesResponseToObjects","catalogPermissions","catalogPermissionRules","readScmEventHandlingConfig","DefaultLocationStore","ConfigLocationEntityProvider","GenericScmEventRefreshProvider","filterProviders","DefaultCatalogProcessingEngine","createHash","AuthorizedLocationAnalyzer","RepoLocationAnalyzer","AuthorizedLocationService","DefaultLocationService","AuthorizedRefreshService","DefaultRefreshService","createRouter","connectEntityProviders","evictEntitiesFromOrphanedProviders","SchemaValidEntityPolicy","DefaultNamespaceEntityPolicy","NoForeignRootFieldsEntityPolicy","FieldFormatEntityPolicy","makeValidator","EntityPolicies","jsonPlaceholderResolver","yamlPlaceholderResolver","textPlaceholderResolver","PlaceholderProcessor","BuiltinKindsEntityProcessor","ModelProcessor","filterAndSortProcessors","config","createRandomProcessingInterval","readDurationFromConfig","durationToMilliseconds"],"mappings":"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"}
1
+ {"version":3,"file":"CatalogBuilder.cjs.js","sources":["../../src/service/CatalogBuilder.ts"],"sourcesContent":["/*\n * Copyright 2020 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 DefaultNamespaceEntityPolicy,\n Entity,\n EntityPolicies,\n EntityPolicy,\n FieldFormatEntityPolicy,\n makeValidator,\n NoForeignRootFieldsEntityPolicy,\n SchemaValidEntityPolicy,\n Validators,\n} from '@backstage/catalog-model';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { createHash } from 'node:crypto';\nimport { Router } from 'express';\nimport lodash from 'lodash';\n\nimport {\n AuditorService,\n AuthService,\n DatabaseService,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n RootConfigService,\n SchedulerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { catalogPermissions } from '@backstage/plugin-catalog-common/alpha';\nimport {\n CatalogProcessor,\n CatalogProcessorParser,\n LocationAnalyzer,\n PlaceholderResolver,\n ScmLocationAnalyzer,\n} from '@backstage/plugin-catalog-node';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { createConditionTransformer } from '@backstage/plugin-permission-node';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { DefaultCatalogDatabase } from '../database/DefaultCatalogDatabase';\nimport { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase';\nimport { DefaultProviderDatabase } from '../database/DefaultProviderDatabase';\nimport { applyDatabaseMigrations } from '../database/migrations';\nimport { DefaultCatalogRulesEnforcer } from '../ingestion/CatalogRules';\nimport { RepoLocationAnalyzer } from '../ingestion/LocationAnalyzer';\nimport { permissionRules as catalogPermissionRules } from '../permissions/rules';\nimport { CatalogProcessingEngine } from '../processing/types';\nimport {\n createRandomProcessingInterval,\n ProcessingIntervalFunction,\n} from '../processing/refresh';\nimport {\n connectEntityProviders,\n EntityProviderEntry,\n} from '../processing/connectEntityProviders';\nimport { evictEntitiesFromOrphanedProviders } from '../processing/evictEntitiesFromOrphanedProviders';\nimport { DefaultCatalogProcessingEngine } from '../processing/DefaultCatalogProcessingEngine';\nimport { DefaultCatalogProcessingOrchestrator } from '../processing/DefaultCatalogProcessingOrchestrator';\nimport {\n AnnotateLocationEntityProcessor,\n BuiltinKindsEntityProcessor,\n FileReaderProcessor,\n PlaceholderProcessor,\n UrlReaderProcessor,\n} from '../processors';\nimport {\n jsonPlaceholderResolver,\n textPlaceholderResolver,\n yamlPlaceholderResolver,\n} from '../processors/PlaceholderProcessor';\nimport { ConfigLocationEntityProvider } from '../providers/ConfigLocationEntityProvider';\nimport { DefaultLocationStore } from '../providers/DefaultLocationStore';\nimport { DefaultStitcher } from '../stitching/DefaultStitcher';\nimport { defaultEntityDataParser } from '../util/parse';\nimport { AuthorizedEntitiesCatalog } from './AuthorizedEntitiesCatalog';\nimport { AuthorizedLocationAnalyzer } from './AuthorizedLocationAnalyzer';\nimport { AuthorizedLocationService } from './AuthorizedLocationService';\nimport { AuthorizedRefreshService } from './AuthorizedRefreshService';\nimport { createRouter } from './createRouter';\nimport { DefaultEntitiesCatalog } from './DefaultEntitiesCatalog';\nimport { DefaultLocationService } from './DefaultLocationService';\nimport { DefaultRefreshService } from './DefaultRefreshService';\nimport { entitiesResponseToObjects } from './response';\nimport {\n catalogEntityPermissionResourceRef,\n CatalogScmEventsService,\n} from '@backstage/plugin-catalog-node/alpha';\nimport { filterAndSortProcessors, filterProviders } from './util';\nimport { GenericScmEventRefreshProvider } from '../providers/GenericScmEventRefreshProvider';\nimport { readScmEventHandlingConfig } from '../util/readScmEventHandlingConfig';\nimport { MetricsService } from '@backstage/backend-plugin-api/alpha';\nimport { ModelProcessor } from '../processors/ModelProcessor';\nimport { ModelHolder } from '../model/ModelHolder';\n\nexport type CatalogEnvironment = {\n logger: LoggerService;\n modelHolder?: ModelHolder;\n database: DatabaseService;\n config: RootConfigService;\n reader: UrlReaderService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n scheduler: SchedulerService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n events: EventsService;\n catalogScmEvents: CatalogScmEventsService;\n metrics: MetricsService;\n};\n\n/**\n * A builder that helps wire up all of the component parts of the catalog.\n *\n * The touch points where you can replace or extend behavior are as follows:\n *\n * - Entity policies can be added or replaced. These are automatically run\n * after the processors' pre-processing steps. All policies are given the\n * chance to inspect the entity, and all of them have to pass in order for\n * the entity to be considered valid from an overall point of view.\n * - Location analyzers can be added. These are responsible for analyzing\n * repositories when onboarding them into the catalog, by finding\n * catalog-info.yaml files and other artifacts that can help automatically\n * register or create catalog data on the user's behalf.\n * - Placeholder resolvers can be replaced or added. These run on the raw\n * structured data between the parsing and pre-processing steps, to replace\n * dollar-prefixed entries with their actual values (like $file).\n * - Field format validators can be replaced. These check the format of\n * individual core fields such as metadata.name, to ensure that they adhere\n * to certain rules.\n * - Processors can be added or replaced. These implement the functionality of\n * reading, parsing, validating, and processing the entity data before it is\n * persisted in the catalog.\n *\n * @internal\n */\nexport class CatalogBuilder {\n private readonly env: CatalogEnvironment;\n private entityPolicies: EntityPolicy[];\n private entityPoliciesReplace: boolean;\n private placeholderResolvers: Record<string, PlaceholderResolver>;\n private fieldFormatValidators: Partial<Validators>;\n private entityProviders: EntityProviderEntry[];\n private processors: CatalogProcessor[];\n private locationAnalyzers: ScmLocationAnalyzer[];\n private processorsReplace: boolean;\n private parser: CatalogProcessorParser | undefined;\n private onProcessingError?: (event: {\n unprocessedEntity: Entity;\n errors: Error[];\n }) => Promise<void> | void;\n private processingInterval: ProcessingIntervalFunction;\n private locationAnalyzer: LocationAnalyzer | undefined = undefined;\n private allowedLocationType: string[];\n\n /**\n * Creates a catalog builder.\n */\n static create(env: CatalogEnvironment): CatalogBuilder {\n return new CatalogBuilder(env);\n }\n\n private constructor(env: CatalogEnvironment) {\n this.env = env;\n this.entityPolicies = [];\n this.entityPoliciesReplace = false;\n this.placeholderResolvers = {};\n this.fieldFormatValidators = {};\n this.entityProviders = [];\n this.processors = [];\n this.locationAnalyzers = [];\n this.processorsReplace = false;\n this.parser = undefined;\n this.allowedLocationType = ['url'];\n\n this.processingInterval = CatalogBuilder.getDefaultProcessingInterval(\n env.config,\n );\n }\n\n /**\n * Adds policies that are used to validate entities between the pre-\n * processing and post-processing stages. All such policies must pass for the\n * entity to be considered valid.\n *\n * If what you want to do is to replace the rules for what format is allowed\n * in various core entity fields (such as metadata.name), you may want to use\n * {@link CatalogBuilder#setFieldFormatValidators} instead.\n *\n * @param policies - One or more policies\n */\n addEntityPolicy(\n ...policies: Array<EntityPolicy | Array<EntityPolicy>>\n ): CatalogBuilder {\n this.entityPolicies.push(...policies.flat());\n return this;\n }\n\n /**\n * Overwrites the default location analyzer.\n */\n setLocationAnalyzer(locationAnalyzer: LocationAnalyzer): CatalogBuilder {\n this.locationAnalyzer = locationAnalyzer;\n return this;\n }\n\n /**\n * Sets what policies to use for validation of entities between the pre-\n * processing and post-processing stages. All such policies must pass for the\n * entity to be considered valid.\n *\n * If what you want to do is to replace the rules for what format is allowed\n * in various core entity fields (such as metadata.name), you may want to use\n * {@link CatalogBuilder#setFieldFormatValidators} instead.\n *\n * This function replaces the default set of policies; use with care.\n *\n * @param policies - One or more policies\n */\n replaceEntityPolicies(policies: EntityPolicy[]): CatalogBuilder {\n this.entityPolicies = [...policies];\n this.entityPoliciesReplace = true;\n return this;\n }\n\n /**\n * Adds, or overwrites, a handler for placeholders (e.g. $file) in entity\n * definition files.\n *\n * @param key - The key that identifies the placeholder, e.g. \"file\"\n * @param resolver - The resolver that gets values for this placeholder\n */\n setPlaceholderResolver(\n key: string,\n resolver: PlaceholderResolver,\n ): CatalogBuilder {\n this.placeholderResolvers[key] = resolver;\n return this;\n }\n\n /**\n * Sets the validator function to use for one or more special fields of an\n * entity. This is useful if the default rules for formatting of fields are\n * not sufficient.\n *\n * This function has no effect if used together with\n * {@link CatalogBuilder#replaceEntityPolicies}.\n *\n * @param validators - The (subset of) validators to set\n */\n setFieldFormatValidators(validators: Partial<Validators>): CatalogBuilder {\n lodash.merge(this.fieldFormatValidators, validators);\n return this;\n }\n\n /**\n * Adds or replaces entity providers. These are responsible for bootstrapping\n * the list of entities out of original data sources. For example, there is\n * one entity source for the config locations, and one for the database\n * stored locations. If you ingest entities out of a third party system, you\n * may want to implement that in terms of an entity provider as well.\n *\n * @param providers - One or more entity providers\n */\n addEntityProvider(\n ...providers: Array<EntityProviderEntry | Array<EntityProviderEntry>>\n ): CatalogBuilder {\n this.entityProviders.push(...providers.flat());\n return this;\n }\n\n /**\n * Adds entity processors. These are responsible for reading, parsing, and\n * processing entities before they are persisted in the catalog.\n *\n * @param processors - One or more processors\n */\n addProcessor(\n ...processors: Array<CatalogProcessor | Array<CatalogProcessor>>\n ): CatalogBuilder {\n this.processors.push(...processors.flat());\n return this;\n }\n\n /**\n * Sets what entity processors to use. These are responsible for reading,\n * parsing, and processing entities before they are persisted in the catalog.\n *\n * This function replaces the default set of processors, consider using with\n * {@link CatalogBuilder#getDefaultProcessors}; use with care.\n *\n * @param processors - One or more processors\n */\n replaceProcessors(processors: CatalogProcessor[]): CatalogBuilder {\n this.processors = [...processors];\n this.processorsReplace = true;\n return this;\n }\n\n /**\n * Returns the default list of entity processors. These are responsible for reading,\n * parsing, and processing entities before they are persisted in the catalog. Changing\n * the order of processing can give more control to custom processors.\n *\n * Consider using with {@link CatalogBuilder#replaceProcessors}\n *\n */\n getDefaultProcessors(): CatalogProcessor[] {\n const { config, logger, reader } = this.env;\n const integrations = ScmIntegrations.fromConfig(config);\n\n return [\n new FileReaderProcessor(),\n new UrlReaderProcessor({ reader, logger }),\n new AnnotateLocationEntityProcessor({ integrations }),\n ];\n }\n\n /**\n * Adds Location Analyzers. These are responsible for analyzing\n * repositories when onboarding them into the catalog, by finding\n * catalog-info.yaml files and other artifacts that can help automatically\n * register or create catalog data on the user's behalf.\n *\n * @param locationAnalyzers - One or more location analyzers\n */\n addLocationAnalyzers(\n ...analyzers: Array<ScmLocationAnalyzer | Array<ScmLocationAnalyzer>>\n ): CatalogBuilder {\n this.locationAnalyzers.push(...analyzers.flat());\n return this;\n }\n\n /**\n * Sets up the catalog to use a custom parser for entity data.\n *\n * This is the function that gets called immediately after some raw entity\n * specification data has been read from a remote source, and needs to be\n * parsed and emitted as structured data.\n *\n * @param parser - The custom parser\n */\n setEntityDataParser(parser: CatalogProcessorParser): CatalogBuilder {\n this.parser = parser;\n return this;\n }\n\n /**\n * Sets up the allowed location types from being registered via the location service.\n *\n * @param allowedLocationTypes - the allowed location types\n */\n setAllowedLocationTypes(allowedLocationTypes: string[]): CatalogBuilder {\n this.allowedLocationType = allowedLocationTypes;\n return this;\n }\n\n /**\n * Wires up and returns all of the component parts of the catalog\n */\n async build(): Promise<{\n processingEngine: CatalogProcessingEngine;\n router: Router;\n }> {\n const {\n config,\n database,\n logger,\n permissions,\n scheduler,\n permissionsRegistry,\n auditor,\n auth,\n httpAuth,\n events,\n catalogScmEvents,\n metrics,\n } = this.env;\n\n const enableRelationsCompatibility = Boolean(\n config.getOptionalBoolean('catalog.enableRelationsCompatibility'),\n );\n\n const policy = this.buildEntityPolicy();\n const processors = this.buildProcessors();\n const parser = this.parser || defaultEntityDataParser;\n\n const dbClient = await database.getClient();\n if (!database.migrations?.skip) {\n logger.info('Performing database migration');\n await applyDatabaseMigrations(dbClient);\n }\n\n const stitcher = DefaultStitcher.fromConfig(config, {\n knex: dbClient,\n logger,\n metrics,\n });\n\n const processingDatabase = new DefaultProcessingDatabase({\n database: dbClient,\n logger,\n events,\n refreshInterval: this.processingInterval,\n metrics,\n });\n const providerDatabase = new DefaultProviderDatabase({\n database: dbClient,\n logger,\n });\n const catalogDatabase = new DefaultCatalogDatabase({\n database: dbClient,\n logger,\n });\n const integrations = ScmIntegrations.fromConfig(config);\n const rulesEnforcer = DefaultCatalogRulesEnforcer.fromConfig(config);\n\n const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog({\n database: dbClient,\n logger,\n enableRelationsCompatibility,\n });\n\n const orchestrator = new DefaultCatalogProcessingOrchestrator({\n processors,\n integrations,\n rulesEnforcer,\n logger,\n parser,\n policy,\n allowedLocationTypes: this.allowedLocationType,\n });\n\n const entitiesCatalog = new AuthorizedEntitiesCatalog(\n unauthorizedEntitiesCatalog,\n permissions,\n createConditionTransformer(\n permissionsRegistry.getPermissionRuleset(\n catalogEntityPermissionResourceRef,\n ),\n ),\n );\n\n const getResources = async (resourceRefs: string[]) => {\n const { items } = await unauthorizedEntitiesCatalog.entitiesBatch({\n credentials: await auth.getOwnServiceCredentials(),\n entityRefs: resourceRefs,\n });\n\n return entitiesResponseToObjects(items).map(e => e || undefined);\n };\n\n permissionsRegistry.addResourceType({\n resourceRef: catalogEntityPermissionResourceRef,\n getResources,\n permissions: [...catalogPermissions],\n rules: Object.values(catalogPermissionRules),\n });\n\n const scmEventHandlingConfig = readScmEventHandlingConfig(config);\n const locationStore = new DefaultLocationStore(\n dbClient,\n catalogScmEvents,\n scmEventHandlingConfig,\n );\n const configLocationProvider = new ConfigLocationEntityProvider(config);\n const scmEvents = new GenericScmEventRefreshProvider(\n dbClient,\n catalogScmEvents,\n scmEventHandlingConfig,\n );\n\n const entityProviderEntries = lodash.uniqBy(\n [\n ...this.entityProviders,\n { provider: locationStore },\n { provider: configLocationProvider },\n { provider: scmEvents },\n ],\n entry => entry.provider.getProviderName(),\n );\n const enabledProviderEntries = filterProviders(\n entityProviderEntries,\n config,\n );\n const enabledProviders = enabledProviderEntries.map(\n entry => entry.provider,\n );\n\n const processingEngine = new DefaultCatalogProcessingEngine({\n config,\n scheduler,\n logger,\n knex: dbClient,\n processingDatabase,\n orchestrator,\n createHash: () => createHash('sha1'),\n pollingIntervalMs: 1000,\n onProcessingError: event => {\n this.onProcessingError?.(event);\n },\n events,\n metrics,\n });\n\n const locationAnalyzer =\n this.locationAnalyzer ??\n new AuthorizedLocationAnalyzer(\n new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers),\n permissions,\n );\n const locationService = new AuthorizedLocationService(\n new DefaultLocationService(locationStore, orchestrator, {\n allowedLocationTypes: this.allowedLocationType,\n defaultLocationConflictStrategy:\n (config.getOptionalString(\n 'catalog.defaultLocationConflictStrategy',\n ) as 'refresh' | 'reject') || 'reject',\n }),\n permissions,\n );\n const refreshService = new AuthorizedRefreshService(\n new DefaultRefreshService({ database: catalogDatabase }),\n permissions,\n );\n\n const router = await createRouter({\n entitiesCatalog,\n locationAnalyzer,\n locationService,\n orchestrator,\n refreshService,\n logger,\n config,\n auth,\n httpAuth,\n permissionsService: permissions,\n auditor,\n enableRelationsCompatibility,\n });\n\n await connectEntityProviders(providerDatabase, enabledProviderEntries);\n\n return {\n processingEngine: {\n async start() {\n if (\n config.getOptionalString('catalog.orphanProviderStrategy') !==\n 'keep'\n ) {\n await evictEntitiesFromOrphanedProviders({\n db: providerDatabase,\n providers: enabledProviders,\n logger,\n });\n }\n await processingEngine.start();\n await stitcher.start();\n },\n async stop() {\n await processingEngine.stop();\n await stitcher.stop();\n },\n },\n router,\n };\n }\n\n subscribe(options: {\n onProcessingError: (event: {\n unprocessedEntity: Entity;\n errors: Error[];\n }) => Promise<void> | void;\n }) {\n this.onProcessingError = options.onProcessingError;\n }\n\n private buildEntityPolicy(): EntityPolicy {\n const entityPolicies: EntityPolicy[] = this.entityPoliciesReplace\n ? [new SchemaValidEntityPolicy(), ...this.entityPolicies]\n : [\n new SchemaValidEntityPolicy(),\n new DefaultNamespaceEntityPolicy(),\n new NoForeignRootFieldsEntityPolicy(),\n new FieldFormatEntityPolicy(\n makeValidator(this.fieldFormatValidators),\n ),\n ...this.entityPolicies,\n ];\n\n return EntityPolicies.allOf(entityPolicies);\n }\n\n private buildProcessors(): CatalogProcessor[] {\n const { config, reader } = this.env;\n const integrations = ScmIntegrations.fromConfig(config);\n\n this.checkDeprecatedReaderProcessors();\n\n const placeholderResolvers: Record<string, PlaceholderResolver> = {\n json: jsonPlaceholderResolver,\n yaml: yamlPlaceholderResolver,\n text: textPlaceholderResolver,\n ...this.placeholderResolvers,\n };\n\n // The placeholder is always there no matter what\n const processors: CatalogProcessor[] = [\n new PlaceholderProcessor({\n resolvers: placeholderResolvers,\n reader,\n integrations,\n }),\n ];\n\n const builtinKindsEntityProcessor = new BuiltinKindsEntityProcessor();\n // If the user adds a processor named 'BuiltinKindsEntityProcessor', skip\n // inclusion of the catalog-backend version. Same if there's a model\n // registered - then we are using the new model flow.\n if (\n !this.env.modelHolder &&\n !this.processors.some(\n processor =>\n processor.getProcessorName() ===\n builtinKindsEntityProcessor.getProcessorName(),\n )\n ) {\n processors.push(builtinKindsEntityProcessor);\n }\n if (this.env.modelHolder) {\n processors.push(new ModelProcessor(this.env.modelHolder));\n }\n\n const disableDefaultProcessors = config.getOptionalBoolean(\n 'catalog.disableDefaultProcessors',\n );\n\n // Add default processors if:\n // - processors have NOT been explicitly replaced\n // - and default processors are NOT disabled via config\n if (!this.processorsReplace && !disableDefaultProcessors) {\n processors.push(...this.getDefaultProcessors());\n }\n\n // Add the ones (if any) that the user added\n processors.push(...this.processors);\n\n this.checkMissingExternalProcessors(processors);\n\n return filterAndSortProcessors(processors, config);\n }\n\n // TODO(Rugvip): These old processors are removed, for a while we'll be throwing\n // errors here to make sure people know where to move the config\n private checkDeprecatedReaderProcessors() {\n const pc = this.env.config.getOptionalConfig('catalog.processors');\n if (pc?.has('github')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.github, move to using integrations.github instead`,\n );\n }\n if (pc?.has('gitlabApi')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.gitlabApi, move to using integrations.gitlab instead`,\n );\n }\n if (pc?.has('bitbucketApi')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.bitbucketApi, move to using integrations.bitbucket instead`,\n );\n }\n if (pc?.has('azureApi')) {\n throw new Error(\n `Using deprecated configuration for catalog.processors.azureApi, move to using integrations.azure instead`,\n );\n }\n }\n\n // TODO(freben): This can be removed no sooner than June 2022, after adopters have had some time to adapt to the new package structure\n private checkMissingExternalProcessors(processors: CatalogProcessor[]) {\n const skipCheckVarName = 'BACKSTAGE_CATALOG_SKIP_MISSING_PROCESSORS_CHECK';\n if (process.env[skipCheckVarName]) {\n return;\n }\n\n const locationTypes = new Set(\n this.env.config\n .getOptionalConfigArray('catalog.locations')\n ?.map(l => l.getString('type')) ?? [],\n );\n const processorNames = new Set(processors.map(p => p.getProcessorName()));\n\n function check(\n locationType: string,\n processorName: string,\n installationUrl: string,\n ) {\n if (\n locationTypes.has(locationType) &&\n !processorNames.has(processorName)\n ) {\n throw new Error(\n [\n `Your config contains a \"catalog.locations\" entry of type ${locationType},`,\n `but does not have the corresponding catalog processor ${processorName} installed.`,\n `This processor used to be built into the catalog itself, but is now moved to an`,\n `external module that has to be installed manually. Please follow the installation`,\n `instructions at ${installationUrl} if you are using this ability, or remove the`,\n `location from your app config if you do not. You can also silence this check entirely`,\n `by setting the environment variable ${skipCheckVarName} to 'true'.`,\n ].join(' '),\n );\n }\n }\n\n check(\n 'aws-cloud-accounts',\n 'AwsOrganizationCloudAccountProcessor',\n 'https://backstage.io/docs/integrations',\n );\n check(\n 's3-discovery',\n 'AwsS3DiscoveryProcessor',\n 'https://backstage.io/docs/integrations/aws-s3/discovery',\n );\n check(\n 'azure-discovery',\n 'AzureDevOpsDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/azure/discovery',\n );\n check(\n 'bitbucket-discovery',\n 'BitbucketDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/bitbucket/discovery',\n );\n check(\n 'github-discovery',\n 'GithubDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/github/discovery',\n );\n check(\n 'github-org',\n 'GithubOrgReaderProcessor',\n 'https://backstage.io/docs/integrations/github/org',\n );\n check(\n 'gitlab-discovery',\n 'GitLabDiscoveryProcessor',\n 'https://backstage.io/docs/integrations/gitlab/discovery',\n );\n check(\n 'ldap-org',\n 'LdapOrgReaderProcessor',\n 'https://backstage.io/docs/integrations/ldap/org',\n );\n check(\n 'microsoft-graph-org',\n 'MicrosoftGraphOrgReaderProcessor',\n 'https://backstage.io/docs/integrations/azure/org',\n );\n }\n\n private static getDefaultProcessingInterval(\n config: Config,\n ): ProcessingIntervalFunction {\n const processingIntervalKey = 'catalog.processingInterval';\n\n if (!config.has(processingIntervalKey)) {\n return createRandomProcessingInterval({\n minSeconds: 100,\n maxSeconds: 150,\n });\n }\n\n if (!Boolean(config.get('catalog.processingInterval'))) {\n return () => {\n throw new Error(\n 'catalog.processingInterval is set to false, processing is disabled.',\n );\n };\n }\n\n const duration = readDurationFromConfig(config, {\n key: processingIntervalKey,\n });\n\n const seconds = Math.max(\n 1,\n Math.round(durationToMilliseconds(duration) / 1000),\n );\n\n return createRandomProcessingInterval({\n minSeconds: seconds,\n maxSeconds: seconds * 1.5,\n });\n }\n}\n"],"names":["lodash","ScmIntegrations","FileReaderProcessor","UrlReaderProcessor","AnnotateLocationEntityProcessor","defaultEntityDataParser","applyDatabaseMigrations","DefaultStitcher","DefaultProcessingDatabase","DefaultProviderDatabase","DefaultCatalogDatabase","DefaultCatalogRulesEnforcer","DefaultEntitiesCatalog","DefaultCatalogProcessingOrchestrator","AuthorizedEntitiesCatalog","createConditionTransformer","catalogEntityPermissionResourceRef","entitiesResponseToObjects","catalogPermissions","catalogPermissionRules","readScmEventHandlingConfig","DefaultLocationStore","ConfigLocationEntityProvider","GenericScmEventRefreshProvider","filterProviders","DefaultCatalogProcessingEngine","createHash","AuthorizedLocationAnalyzer","RepoLocationAnalyzer","AuthorizedLocationService","DefaultLocationService","AuthorizedRefreshService","DefaultRefreshService","createRouter","connectEntityProviders","evictEntitiesFromOrphanedProviders","SchemaValidEntityPolicy","DefaultNamespaceEntityPolicy","NoForeignRootFieldsEntityPolicy","FieldFormatEntityPolicy","makeValidator","EntityPolicies","jsonPlaceholderResolver","yamlPlaceholderResolver","textPlaceholderResolver","PlaceholderProcessor","BuiltinKindsEntityProcessor","ModelProcessor","filterAndSortProcessors","config","createRandomProcessingInterval","readDurationFromConfig","durationToMilliseconds"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-backend",
3
- "version": "3.9.0",
3
+ "version": "3.9.1",
4
4
  "description": "The Backstage backend plugin that provides the Backstage catalog",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",
@@ -82,7 +82,7 @@
82
82
  "@backstage/config": "^1.3.8",
83
83
  "@backstage/errors": "^1.3.1",
84
84
  "@backstage/filter-predicates": "^0.1.4",
85
- "@backstage/integration": "^2.1.0",
85
+ "@backstage/integration": "^2.1.1",
86
86
  "@backstage/plugin-catalog-common": "^1.1.10",
87
87
  "@backstage/plugin-catalog-node": "^2.2.4",
88
88
  "@backstage/plugin-events-node": "^0.4.25",
@@ -111,11 +111,11 @@
111
111
  "zod-validation-error": "^5.0.0"
112
112
  },
113
113
  "devDependencies": {
114
- "@backstage/backend-defaults": "^0.17.7",
114
+ "@backstage/backend-defaults": "^0.17.8",
115
115
  "@backstage/backend-test-utils": "^1.11.6",
116
116
  "@backstage/cli": "^0.36.5",
117
117
  "@backstage/plugin-catalog-backend-module-logs": "^0.1.25",
118
- "@backstage/plugin-scaffolder-common": "^2.2.2",
118
+ "@backstage/plugin-scaffolder-common": "^2.2.3",
119
119
  "@backstage/repo-tools": "^0.19.0",
120
120
  "@types/core-js": "^2.5.4",
121
121
  "@types/express": "^4.17.6",