diff --git a/plugins/catalog-backend/src/service/AuthorizedLocationAnalyzer.ts b/plugins/catalog-backend/src/service/AuthorizedLocationAnalyzer.ts new file mode 100644 index 0000000000..3968a0ab73 --- /dev/null +++ b/plugins/catalog-backend/src/service/AuthorizedLocationAnalyzer.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NotAllowedError } from '@backstage/errors'; +import { catalogLocationCreatePermission } from '@backstage/plugin-catalog-common/alpha'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { PermissionsService } from '@backstage/backend-plugin-api'; +import { LocationAnalyzer } from '@backstage/plugin-catalog-node'; +import { AnalyzeLocationRequest } from '@backstage/plugin-catalog-common'; +import { AnalyzeLocationResponse } from '@backstage/plugin-catalog-common'; + +export class AuthorizedLocationAnalyzer implements LocationAnalyzer { + constructor( + private readonly service: LocationAnalyzer, + private readonly permissionApi: PermissionsService, + ) {} + + async analyzeLocation( + request: AnalyzeLocationRequest, + ): Promise { + const authorizeDecision = ( + await this.permissionApi.authorize( + [ + { + permission: catalogLocationCreatePermission, + }, + ], + { credentials: request.credentials }, + ) + )[0]; + if (authorizeDecision.result !== AuthorizeResult.ALLOW) { + throw new NotAllowedError(); + } + return this.service.analyzeLocation(request); + } +} diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 67c7bf74af..8c304748e4 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -59,6 +59,7 @@ import { import { ConfigLocationEntityProvider } from '../modules/core/ConfigLocationEntityProvider'; import { DefaultLocationStore } from '../modules/core/DefaultLocationStore'; import { RepoLocationAnalyzer } from '../ingestion/LocationAnalyzer'; +import { AuthorizedLocationAnalyzer } from './AuthorizedLocationAnalyzer'; import { jsonPlaceholderResolver, textPlaceholderResolver, @@ -600,7 +601,10 @@ export class CatalogBuilder { const locationAnalyzer = this.locationAnalyzer ?? - new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers); + new AuthorizedLocationAnalyzer( + new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers), + permissionsService, + ); const locationService = new AuthorizedLocationService( new DefaultLocationService(locationStore, orchestrator, { allowedLocationTypes: this.allowedLocationType, diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index a4fd29cf76..abba18b0fe 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -301,9 +301,13 @@ export async function createRouter( location: locationInput, catalogFilename: z.string().optional(), }); + const credentials = await httpAuth.credentials(req); const parsedBody = schema.parse(body); + const analyzeLocationRequest = { ...parsedBody, credentials }; try { - const output = await locationAnalyzer.analyzeLocation(parsedBody); + const output = await locationAnalyzer.analyzeLocation( + analyzeLocationRequest, + ); res.status(200).json(output); } catch (err) { if ( diff --git a/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts b/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts index 08ae5ef0cb..8dd40a015e 100644 --- a/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts +++ b/plugins/catalog-common/src/ingestion/LocationAnalyzer.ts @@ -17,11 +17,13 @@ import { LocationSpec } from '../common'; import { Entity } from '@backstage/catalog-model'; import { RecursivePartial } from './RecursivePartial'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; /** @public */ export type AnalyzeLocationRequest = { location: LocationSpec; catalogFilename?: string; + credentials: BackstageCredentials; }; /** @public */