diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts index 19c231884c..67d1e86248 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts @@ -27,8 +27,14 @@ const entity = { kind: 'Group', } as Entity, component: { - kind: 'component', + kind: 'Component', } as Entity, + componentWithType: { + kind: 'Component', + spec: { + type: 'service', + }, + } as unknown as Entity, location: { kind: 'Location', } as Entity, @@ -164,6 +170,9 @@ describe('DefaultCatalogRulesEnforcer', () => { expect(enforcer.isAllowed(entity.user, location.x)).toBe(false); expect(enforcer.isAllowed(entity.group, location.y)).toBe(false); expect(enforcer.isAllowed(entity.component, location.z)).toBe(true); + expect(enforcer.isAllowed(entity.componentWithType, location.z)).toBe( + true, + ); expect(enforcer.isAllowed(entity.location, location.z)).toBe(true); }); @@ -268,6 +277,33 @@ describe('DefaultCatalogRulesEnforcer', () => { }); }); + it('should only allow components with a specific type', () => { + const enforcer = DefaultCatalogRulesEnforcer.fromConfig( + new ConfigReader({ + catalog: { + rules: [ + { + allow: [{ kind: 'Component', type: 'service' }], + locations: [{ type: 'url', pattern: 'https://github.com/b/**' }], + }, + ], + }, + }), + ); + + expect(enforcer.isAllowed(entity.component, location.w)).toBe(false); + expect(enforcer.isAllowed(entity.component, location.y)).toBe(false); + expect(enforcer.isAllowed(entity.component, location.z)).toBe(false); + + expect(enforcer.isAllowed(entity.componentWithType, location.w)).toBe(true); + expect(enforcer.isAllowed(entity.componentWithType, location.y)).toBe( + false, + ); + expect(enforcer.isAllowed(entity.componentWithType, location.z)).toBe( + false, + ); + }); + it('should allow locations with a hidden folder', () => { const enforcer = DefaultCatalogRulesEnforcer.fromConfig( new ConfigReader({ diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.ts index 8fb237df30..ddb6398bf6 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.ts @@ -26,9 +26,7 @@ import { minimatch } from 'minimatch'; * An undefined list of matchers means match all, an empty list of matchers means match none. */ export type CatalogRule = { - allow: Array<{ - kind: string; - }>; + allow: CatalogRuleAllow[]; locations?: Array<{ exact?: string; type: string; @@ -36,6 +34,11 @@ export type CatalogRule = { }>; }; +type CatalogRuleAllow = { + kind: string; + type?: string; +}; + /** * Decides whether an entity from a given location is allowed to enter the * catalog, according to some rule set. @@ -78,6 +81,9 @@ export class DefaultCatalogRulesEnforcer implements CatalogRulesEnforcer { * catalog: * rules: * - allow: [Component, API] + * - allow: + * - kind: Resource + * type: database * - allow: [Template] * locations: * - type: url @@ -105,7 +111,14 @@ export class DefaultCatalogRulesEnforcer implements CatalogRulesEnforcer { const globalRules = config .getConfigArray('catalog.rules') .map(ruleConf => ({ - allow: ruleConf.getStringArray('allow').map(kind => ({ kind })), + allow: ruleConf + .get>('allow') + .map(kindOrObject => { + if (typeof kindOrObject === 'string') { + return { kind: kindOrObject }; + } + return kindOrObject; + }), locations: ruleConf .getOptionalConfigArray('locations') ?.map(locationConfig => { @@ -199,13 +212,17 @@ export class DefaultCatalogRulesEnforcer implements CatalogRulesEnforcer { return false; } - private matchEntity(entity: Entity, matchers?: { kind: string }[]): boolean { + private matchEntity(entity: Entity, matchers?: CatalogRuleAllow[]): boolean { if (!matchers) { return true; } for (const matcher of matchers) { - if (entity?.kind?.toLowerCase() !== matcher.kind.toLowerCase()) { + if (entity.kind?.toLowerCase() !== matcher.kind.toLowerCase()) { + continue; + } + + if (matcher.type && matcher.type !== entity.spec?.type) { continue; }