@backstage/plugin-catalog-backend 0.19.4 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @backstage/plugin-catalog-backend
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - cd529c4094: In order to integrate the permissions system with the refresh endpoint in catalog-backend, a new AuthorizedRefreshService was created as a thin wrapper around the existing refresh service which performs authorization and handles the case when authorization is denied. In order to instantiate AuthorizedRefreshService, a permission client is required, which was added as a new field to `CatalogEnvironment`.
8
+
9
+ The new `permissions` field in `CatalogEnvironment` should already receive the permission client from the `PluginEnvrionment`, so there should be no changes required to the catalog backend setup. See [the create-app changelog](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md) for more details.
10
+
11
+ ### Patch Changes
12
+
13
+ - 0ae759dad4: Add catalog permission rules.
14
+ - 3b4d8caff6: Allow a custom GithubCredentialsProvider to be passed to the GitHub processors.
15
+ - 6fd70f8bc8: Provide support for Bitbucket servers with custom BaseURLs.
16
+ - 5333451def: Cleaned up API exports
17
+ - 730d01ab1a: Add apply-conditions endpoint for evaluating conditional permissions in catalog backend.
18
+ - 0a6c68582a: Add authorization to catalog-backend entities GET endpoints
19
+ - Updated dependencies
20
+ - @backstage/config@0.1.12
21
+ - @backstage/integration@0.7.1
22
+ - @backstage/backend-common@0.10.3
23
+ - @backstage/plugin-permission-node@0.3.0
24
+ - @backstage/errors@0.2.0
25
+ - @backstage/catalog-client@0.5.4
26
+ - @backstage/catalog-model@0.9.9
27
+ - @backstage/plugin-permission-common@0.3.1
28
+
3
29
  ## 0.19.4
4
30
 
5
31
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -30,6 +30,9 @@ var luxon = require('luxon');
30
30
  var promClient = require('prom-client');
31
31
  var stableStringify = require('fast-json-stable-stringify');
32
32
  var catalogClient = require('@backstage/catalog-client');
33
+ var pluginCatalogCommon = require('@backstage/plugin-catalog-common');
34
+ var pluginPermissionCommon = require('@backstage/plugin-permission-common');
35
+ var pluginPermissionNode = require('@backstage/plugin-permission-node');
33
36
 
34
37
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
35
38
 
@@ -604,12 +607,13 @@ async function readBitbucketCloud(client, target) {
604
607
  }
605
608
  function parseUrl$3(urlString) {
606
609
  const url = new URL(urlString);
607
- const path = url.pathname.substr(1).split("/");
610
+ const indexOfProjectSegment = url.pathname.toLowerCase().indexOf("/projects/") + 1;
611
+ const path = url.pathname.substr(indexOfProjectSegment).split("/");
608
612
  if (path.length > 3 && path[1].length && path[3].length) {
609
613
  return {
610
614
  projectSearchPath: escapeRegExp$1(decodeURIComponent(path[1])),
611
615
  repoSearchPath: escapeRegExp$1(decodeURIComponent(path[3])),
612
- catalogPath: `/${decodeURIComponent(path.slice(4).join("/"))}`
616
+ catalogPath: `/${decodeURIComponent(path.slice(4).join("/") + url.search)}`
613
617
  };
614
618
  }
615
619
  throw new Error(`Failed to parse ${urlString}`);
@@ -1104,6 +1108,7 @@ class GithubDiscoveryProcessor {
1104
1108
  constructor(options) {
1105
1109
  this.integrations = options.integrations;
1106
1110
  this.logger = options.logger;
1111
+ this.githubCredentialsProvider = options.githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(this.integrations);
1107
1112
  }
1108
1113
  async readLocation(location$1, _optional, emit) {
1109
1114
  var _a, _b;
@@ -1116,7 +1121,9 @@ class GithubDiscoveryProcessor {
1116
1121
  }
1117
1122
  const { org, repoSearchPath, catalogPath, branch, host } = parseUrl$2(location$1.target);
1118
1123
  const orgUrl = `https://${host}/${org}`;
1119
- const { headers } = await integration.SingleInstanceGithubCredentialsProvider.create(gitHubConfig).getCredentials({ url: orgUrl });
1124
+ const { headers } = await this.githubCredentialsProvider.getCredentials({
1125
+ url: orgUrl
1126
+ });
1120
1127
  const client = graphql.graphql.defaults({
1121
1128
  baseUrl: gitHubConfig.apiBaseUrl,
1122
1129
  headers
@@ -1301,6 +1308,7 @@ class GithubOrgReaderProcessor {
1301
1308
  }
1302
1309
  constructor(options) {
1303
1310
  this.integrations = options.integrations;
1311
+ this.githubCredentialsProvider = options.githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(this.integrations);
1304
1312
  this.logger = options.logger;
1305
1313
  }
1306
1314
  async readLocation(location, _optional, emit) {
@@ -1331,8 +1339,7 @@ class GithubOrgReaderProcessor {
1331
1339
  if (!gitHubConfig) {
1332
1340
  throw new Error(`There is no GitHub Org provider that matches ${orgUrl}. Please add a configuration for an integration.`);
1333
1341
  }
1334
- const credentialsProvider = integration.SingleInstanceGithubCredentialsProvider.create(gitHubConfig);
1335
- const { headers, type: tokenType } = await credentialsProvider.getCredentials({
1342
+ const { headers, type: tokenType } = await this.githubCredentialsProvider.getCredentials({
1336
1343
  url: orgUrl
1337
1344
  });
1338
1345
  const client = graphql.graphql.defaults({
@@ -1357,6 +1364,7 @@ class GithubMultiOrgReaderProcessor {
1357
1364
  this.integrations = options.integrations;
1358
1365
  this.logger = options.logger;
1359
1366
  this.orgs = options.orgs;
1367
+ this.githubCredentialsProvider = options.githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(this.integrations);
1360
1368
  }
1361
1369
  async readLocation(location, _optional, emit) {
1362
1370
  var _a, _b;
@@ -1369,11 +1377,10 @@ class GithubMultiOrgReaderProcessor {
1369
1377
  }
1370
1378
  const allUsersMap = /* @__PURE__ */ new Map();
1371
1379
  const baseUrl = new URL(location.target).origin;
1372
- const credentialsProvider = integration.SingleInstanceGithubCredentialsProvider.create(gitHubConfig);
1373
1380
  const orgsToProcess = this.orgs.length ? this.orgs : await this.getAllOrgs(gitHubConfig);
1374
1381
  for (const orgConfig of orgsToProcess) {
1375
1382
  try {
1376
- const { headers, type: tokenType } = await credentialsProvider.getCredentials({
1383
+ const { headers, type: tokenType } = await this.githubCredentialsProvider.getCredentials({
1377
1384
  url: `${baseUrl}/${orgConfig.name}`
1378
1385
  });
1379
1386
  const client = graphql.graphql.defaults({
@@ -1839,7 +1846,7 @@ const defaultEntityDataParser = async function* defaultEntityDataParser2({ data,
1839
1846
  class GitHubOrgEntityProvider {
1840
1847
  constructor(options) {
1841
1848
  this.options = options;
1842
- this.credentialsProvider = integration.SingleInstanceGithubCredentialsProvider.create(options.gitHubConfig);
1849
+ this.githubCredentialsProvider = options.githubCredentialsProvider || integration.SingleInstanceGithubCredentialsProvider.create(options.gitHubConfig);
1843
1850
  }
1844
1851
  static fromConfig(config, options) {
1845
1852
  var _a;
@@ -1855,7 +1862,8 @@ class GitHubOrgEntityProvider {
1855
1862
  id: options.id,
1856
1863
  orgUrl: options.orgUrl,
1857
1864
  logger,
1858
- gitHubConfig
1865
+ gitHubConfig,
1866
+ githubCredentialsProvider: options.githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations)
1859
1867
  });
1860
1868
  }
1861
1869
  getProviderName() {
@@ -1869,7 +1877,7 @@ class GitHubOrgEntityProvider {
1869
1877
  throw new Error("Not initialized");
1870
1878
  }
1871
1879
  const { markReadComplete } = trackProgress(this.options.logger);
1872
- const { headers, type: tokenType } = await this.credentialsProvider.getCredentials({
1880
+ const { headers, type: tokenType } = await this.githubCredentialsProvider.getCredentials({
1873
1881
  url: this.options.orgUrl
1874
1882
  });
1875
1883
  const client = graphql.graphql.defaults({
@@ -3102,7 +3110,8 @@ async function createNextRouter(options) {
3102
3110
  locationService,
3103
3111
  refreshService,
3104
3112
  config,
3105
- logger
3113
+ logger,
3114
+ permissionIntegrationRouter
3106
3115
  } = options;
3107
3116
  const router = Router__default["default"]();
3108
3117
  router.use(express__default["default"].json());
@@ -3113,16 +3122,21 @@ async function createNextRouter(options) {
3113
3122
  if (refreshService) {
3114
3123
  router.post("/refresh", async (req, res) => {
3115
3124
  const refreshOptions = req.body;
3125
+ refreshOptions.authorizationToken = getBearerToken(req.header("authorization"));
3116
3126
  await refreshService.refresh(refreshOptions);
3117
3127
  res.status(200).send();
3118
3128
  });
3119
3129
  }
3130
+ if (permissionIntegrationRouter) {
3131
+ router.use(permissionIntegrationRouter);
3132
+ }
3120
3133
  if (entitiesCatalog) {
3121
3134
  router.get("/entities", async (req, res) => {
3122
3135
  const { entities, pageInfo } = await entitiesCatalog.entities({
3123
3136
  filter: parseEntityFilterParams(req.query),
3124
3137
  fields: parseEntityTransformParams(req.query),
3125
- pagination: parseEntityPaginationParams(req.query)
3138
+ pagination: parseEntityPaginationParams(req.query),
3139
+ authorizationToken: getBearerToken(req.header("authorization"))
3126
3140
  });
3127
3141
  if (pageInfo.hasNextPage) {
3128
3142
  const url = new URL(`http://ignored${req.url}`);
@@ -3134,7 +3148,8 @@ async function createNextRouter(options) {
3134
3148
  }).get("/entities/by-uid/:uid", async (req, res) => {
3135
3149
  const { uid } = req.params;
3136
3150
  const { entities } = await entitiesCatalog.entities({
3137
- filter: basicEntityFilter({ "metadata.uid": uid })
3151
+ filter: basicEntityFilter({ "metadata.uid": uid }),
3152
+ authorizationToken: getBearerToken(req.header("authorization"))
3138
3153
  });
3139
3154
  if (!entities.length) {
3140
3155
  throw new errors.NotFoundError(`No entity with uid ${uid}`);
@@ -3151,7 +3166,8 @@ async function createNextRouter(options) {
3151
3166
  kind,
3152
3167
  "metadata.namespace": namespace,
3153
3168
  "metadata.name": name
3154
- })
3169
+ }),
3170
+ authorizationToken: getBearerToken(req.header("authorization"))
3155
3171
  });
3156
3172
  if (!entities.length) {
3157
3173
  throw new errors.NotFoundError(`No entity named '${name}' found, with kind '${kind}' in namespace '${namespace}'`);
@@ -3197,6 +3213,13 @@ async function createNextRouter(options) {
3197
3213
  router.use(backendCommon.errorHandler());
3198
3214
  return router;
3199
3215
  }
3216
+ function getBearerToken(authorizationHeader) {
3217
+ if (typeof authorizationHeader !== "string") {
3218
+ return void 0;
3219
+ }
3220
+ const matches = authorizationHeader.match(/Bearer\s+(\S+)/i);
3221
+ return matches == null ? void 0 : matches[1];
3222
+ }
3200
3223
 
3201
3224
  function isLocationEntity(entity) {
3202
3225
  return entity.kind === "Location";
@@ -4858,6 +4881,25 @@ class DefaultRefreshService {
4858
4881
  }
4859
4882
  }
4860
4883
 
4884
+ class AuthorizedRefreshService {
4885
+ constructor(service, permissionApi) {
4886
+ this.service = service;
4887
+ this.permissionApi = permissionApi;
4888
+ }
4889
+ async refresh(options) {
4890
+ const authorizeResponse = (await this.permissionApi.authorize([
4891
+ {
4892
+ permission: pluginCatalogCommon.catalogEntityRefreshPermission,
4893
+ resourceRef: options.entityRef
4894
+ }
4895
+ ], { token: options.authorizationToken }))[0];
4896
+ if (authorizeResponse.result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
4897
+ throw new errors.NotAllowedError();
4898
+ }
4899
+ await this.service.refresh(options);
4900
+ }
4901
+ }
4902
+
4861
4903
  class Connection {
4862
4904
  constructor(config) {
4863
4905
  this.config = config;
@@ -4907,6 +4949,122 @@ async function connectEntityProviders(db, providers) {
4907
4949
  }));
4908
4950
  }
4909
4951
 
4952
+ const createCatalogPermissionRule = pluginPermissionNode.makeCreatePermissionRule();
4953
+
4954
+ const hasAnnotation = createCatalogPermissionRule({
4955
+ name: "HAS_ANNOTATION",
4956
+ description: "Allow entities which are annotated with the specified annotation",
4957
+ apply: (resource, annotation) => {
4958
+ var _a;
4959
+ return !!((_a = resource.metadata.annotations) == null ? void 0 : _a.hasOwnProperty(annotation));
4960
+ },
4961
+ toQuery: (annotation) => ({
4962
+ key: `metadata.annotations.${annotation}`
4963
+ })
4964
+ });
4965
+
4966
+ const isEntityKind = createCatalogPermissionRule({
4967
+ name: "IS_ENTITY_KIND",
4968
+ description: "Allow entities with the specified kind",
4969
+ apply(resource, kinds) {
4970
+ const resourceKind = resource.kind.toLocaleLowerCase("en-US");
4971
+ return kinds.some((kind) => kind.toLocaleLowerCase("en-US") === resourceKind);
4972
+ },
4973
+ toQuery(kinds) {
4974
+ return {
4975
+ key: "kind",
4976
+ values: kinds.map((kind) => kind.toLocaleLowerCase("en-US"))
4977
+ };
4978
+ }
4979
+ });
4980
+
4981
+ const isEntityOwner = createCatalogPermissionRule({
4982
+ name: "IS_ENTITY_OWNER",
4983
+ description: "Allow entities owned by the current user",
4984
+ apply: (resource, claims) => {
4985
+ if (!resource.relations) {
4986
+ return false;
4987
+ }
4988
+ return resource.relations.filter((relation) => relation.type === catalogModel.RELATION_OWNED_BY).some((relation) => claims.includes(catalogModel.stringifyEntityRef(relation.target)));
4989
+ },
4990
+ toQuery: (claims) => ({
4991
+ key: "relations.ownedBy",
4992
+ values: claims
4993
+ })
4994
+ });
4995
+
4996
+ const hasLabel = createCatalogPermissionRule({
4997
+ name: "HAS_LABEL",
4998
+ description: "Allow entities which have the specified label metadata.",
4999
+ apply: (resource, label) => {
5000
+ var _a;
5001
+ return !!((_a = resource.metadata.labels) == null ? void 0 : _a.hasOwnProperty(label));
5002
+ },
5003
+ toQuery: (label) => ({
5004
+ key: `metadata.labels.${label}`
5005
+ })
5006
+ });
5007
+
5008
+ const createPropertyRule = (propertyType) => createCatalogPermissionRule({
5009
+ name: `HAS_${propertyType.toUpperCase()}`,
5010
+ description: `Allow entities which have the specified ${propertyType} subfield.`,
5011
+ apply: (resource, key, value) => {
5012
+ const foundValue = lodash.get(resource[propertyType], key);
5013
+ if (value !== void 0) {
5014
+ return value === foundValue;
5015
+ }
5016
+ return !!foundValue;
5017
+ },
5018
+ toQuery: (key, value) => ({
5019
+ key: `${propertyType}.${key}`,
5020
+ ...value !== void 0 && { values: [value] }
5021
+ })
5022
+ });
5023
+
5024
+ const hasMetadata = createPropertyRule("metadata");
5025
+
5026
+ const hasSpec = createPropertyRule("spec");
5027
+
5028
+ const permissionRules = {
5029
+ hasAnnotation,
5030
+ hasLabel,
5031
+ hasMetadata,
5032
+ hasSpec,
5033
+ isEntityKind,
5034
+ isEntityOwner
5035
+ };
5036
+
5037
+ class AuthorizedEntitiesCatalog {
5038
+ constructor(entitiesCatalog, permissionApi, transformConditions) {
5039
+ this.entitiesCatalog = entitiesCatalog;
5040
+ this.permissionApi = permissionApi;
5041
+ this.transformConditions = transformConditions;
5042
+ }
5043
+ async entities(request) {
5044
+ const authorizeResponse = (await this.permissionApi.authorize([{ permission: pluginCatalogCommon.catalogEntityReadPermission }], { token: request == null ? void 0 : request.authorizationToken }))[0];
5045
+ if (authorizeResponse.result === pluginPermissionCommon.AuthorizeResult.DENY) {
5046
+ return {
5047
+ entities: [],
5048
+ pageInfo: { hasNextPage: false }
5049
+ };
5050
+ }
5051
+ if (authorizeResponse.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
5052
+ const permissionFilter = this.transformConditions(authorizeResponse.conditions);
5053
+ return this.entitiesCatalog.entities({
5054
+ ...request,
5055
+ filter: (request == null ? void 0 : request.filter) ? { allOf: [permissionFilter, request.filter] } : permissionFilter
5056
+ });
5057
+ }
5058
+ return this.entitiesCatalog.entities(request);
5059
+ }
5060
+ removeEntityByUid(uid) {
5061
+ return this.entitiesCatalog.removeEntityByUid(uid);
5062
+ }
5063
+ entityAncestry(entityRef) {
5064
+ return this.entitiesCatalog.entityAncestry(entityRef);
5065
+ }
5066
+ }
5067
+
4910
5068
  class NextCatalogBuilder {
4911
5069
  constructor(env) {
4912
5070
  this.refreshInterval = createRandomRefreshInterval({
@@ -4923,6 +5081,7 @@ class NextCatalogBuilder {
4923
5081
  this.processors = [];
4924
5082
  this.processorsReplace = false;
4925
5083
  this.parser = void 0;
5084
+ this.permissionRules = Object.values(permissionRules);
4926
5085
  }
4927
5086
  addEntityPolicy(...policies) {
4928
5087
  this.entityPolicies.push(...policies);
@@ -4972,12 +5131,19 @@ class NextCatalogBuilder {
4972
5131
  getDefaultProcessors() {
4973
5132
  const { config, logger, reader } = this.env;
4974
5133
  const integrations = integration.ScmIntegrations.fromConfig(config);
5134
+ const githubCredentialsProvider = integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations);
4975
5135
  return [
4976
5136
  new FileReaderProcessor(),
4977
5137
  BitbucketDiscoveryProcessor.fromConfig(config, { logger }),
4978
5138
  AzureDevOpsDiscoveryProcessor.fromConfig(config, { logger }),
4979
- GithubDiscoveryProcessor.fromConfig(config, { logger }),
4980
- GithubOrgReaderProcessor.fromConfig(config, { logger }),
5139
+ GithubDiscoveryProcessor.fromConfig(config, {
5140
+ logger,
5141
+ githubCredentialsProvider
5142
+ }),
5143
+ GithubOrgReaderProcessor.fromConfig(config, {
5144
+ logger,
5145
+ githubCredentialsProvider
5146
+ }),
4981
5147
  GitLabDiscoveryProcessor.fromConfig(config, { logger }),
4982
5148
  new UrlReaderProcessor({ reader, logger }),
4983
5149
  CodeOwnersProcessor.fromConfig(config, { logger, reader }),
@@ -4988,9 +5154,12 @@ class NextCatalogBuilder {
4988
5154
  this.parser = parser;
4989
5155
  return this;
4990
5156
  }
5157
+ addPermissionRules(...permissionRules) {
5158
+ this.permissionRules.push(...permissionRules);
5159
+ }
4991
5160
  async build() {
4992
5161
  var _a, _b;
4993
- const { config, database, logger } = this.env;
5162
+ const { config, database, logger, permissions } = this.env;
4994
5163
  const policy = this.buildEntityPolicy();
4995
5164
  const processors = this.buildProcessors();
4996
5165
  const parser = this.parser || defaultEntityDataParser;
@@ -5015,7 +5184,28 @@ class NextCatalogBuilder {
5015
5184
  parser,
5016
5185
  policy
5017
5186
  });
5018
- const entitiesCatalog = new NextEntitiesCatalog(dbClient);
5187
+ const unauthorizedEntitiesCatalog = new NextEntitiesCatalog(dbClient);
5188
+ const entitiesCatalog = new AuthorizedEntitiesCatalog(unauthorizedEntitiesCatalog, permissions, pluginPermissionNode.createConditionTransformer(this.permissionRules));
5189
+ const permissionIntegrationRouter = pluginPermissionNode.createPermissionIntegrationRouter({
5190
+ resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
5191
+ getResources: async (resourceRefs) => {
5192
+ const { entities } = await entitiesCatalog.entities({
5193
+ filter: {
5194
+ anyOf: resourceRefs.map((resourceRef) => {
5195
+ const { kind, namespace, name } = catalogModel.parseEntityRef(resourceRef);
5196
+ return basicEntityFilter({
5197
+ kind,
5198
+ "metadata.namespace": namespace,
5199
+ "metadata.name": name
5200
+ });
5201
+ })
5202
+ }
5203
+ });
5204
+ const entitiesByRef = lodash.keyBy(entities, catalogModel.stringifyEntityRef);
5205
+ return resourceRefs.map((resourceRef) => entitiesByRef[catalogModel.stringifyEntityRef(catalogModel.parseEntityRef(resourceRef))]);
5206
+ },
5207
+ rules: this.permissionRules
5208
+ });
5019
5209
  const stitcher = new Stitcher(dbClient, logger);
5020
5210
  const locationStore = new DefaultLocationStore(dbClient);
5021
5211
  const configLocationProvider = new ConfigLocationEntityProvider(config);
@@ -5024,16 +5214,15 @@ class NextCatalogBuilder {
5024
5214
  const locationsCatalog = new DatabaseLocationsCatalog(db);
5025
5215
  const locationAnalyzer = (_b = this.locationAnalyzer) != null ? _b : new RepoLocationAnalyzer(logger, integrations);
5026
5216
  const locationService = new DefaultLocationService(locationStore, orchestrator);
5027
- const refreshService = new DefaultRefreshService({
5028
- database: processingDatabase
5029
- });
5217
+ const refreshService = new AuthorizedRefreshService(new DefaultRefreshService({ database: processingDatabase }), permissions);
5030
5218
  const router = await createNextRouter({
5031
5219
  entitiesCatalog,
5032
5220
  locationAnalyzer,
5033
5221
  locationService,
5034
5222
  refreshService,
5035
5223
  logger,
5036
- config
5224
+ config,
5225
+ permissionIntegrationRouter
5037
5226
  });
5038
5227
  await connectEntityProviders(processingDatabase, entityProviders);
5039
5228
  return {
@@ -5180,6 +5369,7 @@ class CatalogBuilder {
5180
5369
  buildProcessors() {
5181
5370
  const { config, logger, reader } = this.env;
5182
5371
  const integrations = integration.ScmIntegrations.fromConfig(config);
5372
+ const githubCredentialsProvider = integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations);
5183
5373
  this.checkDeprecatedReaderProcessors();
5184
5374
  const placeholderResolvers = {
5185
5375
  json: jsonPlaceholderResolver,
@@ -5197,7 +5387,13 @@ class CatalogBuilder {
5197
5387
  new BuiltinKindsEntityProcessor()
5198
5388
  ];
5199
5389
  if (!this.processorsReplace) {
5200
- processors.push(new FileReaderProcessor(), BitbucketDiscoveryProcessor.fromConfig(config, { logger }), GithubDiscoveryProcessor.fromConfig(config, { logger }), AzureDevOpsDiscoveryProcessor.fromConfig(config, { logger }), GithubOrgReaderProcessor.fromConfig(config, { logger }), GitLabDiscoveryProcessor.fromConfig(config, { logger }), new UrlReaderProcessor({ reader, logger }), CodeOwnersProcessor.fromConfig(config, { logger, reader }), new LocationEntityProcessor({ integrations }), new AnnotateLocationEntityProcessor({ integrations }));
5390
+ processors.push(new FileReaderProcessor(), BitbucketDiscoveryProcessor.fromConfig(config, { logger }), GithubDiscoveryProcessor.fromConfig(config, {
5391
+ logger,
5392
+ githubCredentialsProvider
5393
+ }), AzureDevOpsDiscoveryProcessor.fromConfig(config, { logger }), GithubOrgReaderProcessor.fromConfig(config, {
5394
+ logger,
5395
+ githubCredentialsProvider
5396
+ }), GitLabDiscoveryProcessor.fromConfig(config, { logger }), new UrlReaderProcessor({ reader, logger }), CodeOwnersProcessor.fromConfig(config, { logger, reader }), new LocationEntityProcessor({ integrations }), new AnnotateLocationEntityProcessor({ integrations }));
5201
5397
  }
5202
5398
  processors.push(...this.processors);
5203
5399
  return processors;
@@ -5451,11 +5647,13 @@ exports.NextCatalogBuilder = NextCatalogBuilder;
5451
5647
  exports.PlaceholderProcessor = PlaceholderProcessor;
5452
5648
  exports.StaticLocationProcessor = StaticLocationProcessor;
5453
5649
  exports.UrlReaderProcessor = UrlReaderProcessor;
5650
+ exports.createCatalogPermissionRule = createCatalogPermissionRule;
5454
5651
  exports.createNextRouter = createNextRouter;
5455
5652
  exports.createRandomRefreshInterval = createRandomRefreshInterval;
5456
5653
  exports.createRouter = createRouter;
5457
5654
  exports.durationText = durationText;
5458
5655
  exports.parseEntityYaml = parseEntityYaml;
5656
+ exports.permissionRules = permissionRules;
5459
5657
  exports.results = results;
5460
5658
  exports.runPeriodically = runPeriodically;
5461
5659
  //# sourceMappingURL=index.cjs.js.map