diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index d1f62d833b..3e47b1a523 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -24,7 +24,10 @@ import { UrlReader, } from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; -import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { + PermissionAuthorizer, + PermissionEvaluator, +} from '@backstage/plugin-permission-common'; export type PluginEnvironment = { logger: Logger; @@ -34,6 +37,6 @@ export type PluginEnvironment = { reader: UrlReader; discovery: PluginEndpointDiscovery; tokenManager: TokenManager; - permissions: PermissionEvaluator; + permissions: PermissionEvaluator | PermissionAuthorizer; scheduler: PluginTaskScheduler; }; diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index e9135393ba..90ffc467c2 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -79,7 +79,11 @@ import { CatalogPermissionRule, permissionRules as catalogPermissionRules, } from '../permissions/rules'; -import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { + PermissionAuthorizer, + PermissionEvaluator, + toPermissionEvaluator, +} from '@backstage/plugin-permission-common'; import { createConditionTransformer, createPermissionIntegrationRouter, @@ -95,7 +99,7 @@ export type CatalogEnvironment = { database: PluginDatabaseManager; config: Config; reader: UrlReader; - permissions: PermissionEvaluator; + permissions: PermissionEvaluator | PermissionAuthorizer; }; /** @@ -376,9 +380,20 @@ export class CatalogBuilder { policy, }); const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog(dbClient); + + let permissionEvaluator: PermissionEvaluator; + if (!permissions.hasOwnProperty('query')) { + logger.warn( + 'PermissionAuthorizer is deprecated. Please use PermissionEvaluator instead of PermissionAuthorizer in catalog.ts', + ); + permissionEvaluator = toPermissionEvaluator(permissions); + } else { + permissionEvaluator = permissions as PermissionEvaluator; + } + const entitiesCatalog = new AuthorizedEntitiesCatalog( unauthorizedEntitiesCatalog, - permissions, + permissionEvaluator, createConditionTransformer(this.permissionRules), ); const permissionIntegrationRouter = createPermissionIntegrationRouter({ @@ -428,11 +443,11 @@ export class CatalogBuilder { this.locationAnalyzer ?? new RepoLocationAnalyzer(logger, integrations); const locationService = new AuthorizedLocationService( new DefaultLocationService(locationStore, orchestrator), - permissions, + permissionEvaluator, ); const refreshService = new AuthorizedRefreshService( new DefaultRefreshService({ database: processingDatabase }), - permissions, + permissionEvaluator, ); const router = await createRouter({ entitiesCatalog, diff --git a/plugins/jenkins-backend/src/service/router.ts b/plugins/jenkins-backend/src/service/router.ts index 1ad8f22b25..8787be70df 100644 --- a/plugins/jenkins-backend/src/service/router.ts +++ b/plugins/jenkins-backend/src/service/router.ts @@ -20,22 +20,38 @@ import Router from 'express-promise-router'; import { Logger } from 'winston'; import { JenkinsInfoProvider } from './jenkinsInfoProvider'; import { JenkinsApiImpl } from './jenkinsApi'; -import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { + PermissionAuthorizer, + PermissionEvaluator, + toPermissionEvaluator, +} from '@backstage/plugin-permission-common'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { stringifyEntityRef } from '@backstage/catalog-model'; export interface RouterOptions { logger: Logger; jenkinsInfoProvider: JenkinsInfoProvider; - permissions?: PermissionEvaluator; + permissions?: PermissionEvaluator | PermissionAuthorizer; } export async function createRouter( options: RouterOptions, ): Promise { - const { jenkinsInfoProvider } = options; + const { jenkinsInfoProvider, permissions, logger } = options; - const jenkinsApi = new JenkinsApiImpl(options.permissions); + let permissionEvaluator: PermissionEvaluator | undefined; + if (permissions?.hasOwnProperty('query')) { + permissionEvaluator = permissions as PermissionEvaluator; + } else { + logger.warn( + 'PermissionAuthorizer is deprecated. Please use PermissionEvaluator instead of PermissionAuthorizer in your jenkins.ts', + ); + permissionEvaluator = permissions + ? toPermissionEvaluator(permissions) + : undefined; + } + + const jenkinsApi = new JenkinsApiImpl(permissionEvaluator); const router = Router(); router.use(express.json()); diff --git a/plugins/permission-common/src/permissions/util.ts b/plugins/permission-common/src/permissions/util.ts index 1a5ed434a7..b40b582149 100644 --- a/plugins/permission-common/src/permissions/util.ts +++ b/plugins/permission-common/src/permissions/util.ts @@ -14,7 +14,18 @@ * limitations under the License. */ -import { Permission, ResourcePermission } from '../types'; +import { + AuthorizePermissionRequest, + AuthorizePermissionResponse, + DefinitivePolicyDecision, + EvaluatorRequestOptions, + Permission, + PermissionAuthorizer, + PermissionEvaluator, + QueryPermissionRequest, + QueryPermissionResponse, + ResourcePermission, +} from '../types'; /** * Check if the two parameters are equivalent permissions. @@ -75,3 +86,26 @@ export function isUpdatePermission(permission: Permission) { export function isDeletePermission(permission: Permission) { return permission.attributes.action === 'delete'; } + +export function toPermissionEvaluator( + permissionAuthorizer: PermissionAuthorizer, +): PermissionEvaluator { + return { + authorize: async ( + requests: AuthorizePermissionRequest[], + options?: EvaluatorRequestOptions, + ): Promise => { + const response = await permissionAuthorizer.authorize(requests, options); + + return response as DefinitivePolicyDecision[]; + }, + query( + requests: QueryPermissionRequest[], + options?: EvaluatorRequestOptions, + ): Promise { + // @ts-expect-error + const parsedRequests: AuthorizePermissionRequest[] = requests; + return permissionAuthorizer.authorize(parsedRequests, options); + }, + }; +} diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index 6867c382df..bd956a9ff8 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -23,7 +23,11 @@ import { InputError } from '@backstage/errors'; import { Config } from '@backstage/config'; import { JsonObject, JsonValue } from '@backstage/types'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; -import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { + PermissionAuthorizer, + PermissionEvaluator, + toPermissionEvaluator, +} from '@backstage/plugin-permission-common'; import { DocumentTypeInfo, IndexableResultSet, @@ -50,7 +54,7 @@ const jsonObjectSchema: z.ZodSchema = z.lazy(() => { export type RouterOptions = { engine: SearchEngine; types: Record; - permissions: PermissionEvaluator; + permissions: PermissionEvaluator | PermissionAuthorizer; config: Config; logger: Logger; }; @@ -71,8 +75,23 @@ export async function createRouter( pageCursor: z.string().optional(), }); + let permissionEvaluator: PermissionEvaluator; + if (!permissions.hasOwnProperty('query')) { + logger.warn( + 'PermissionAuthorizer is deprecated. Please use PermissionEvaluator instead of PermissionAuthorizer in search.ts', + ); + permissionEvaluator = toPermissionEvaluator(permissions); + } else { + permissionEvaluator = permissions as PermissionEvaluator; + } + const engine = config.getOptionalBoolean('permission.enabled') - ? new AuthorizedSearchEngine(inputEngine, types, permissions, config) + ? new AuthorizedSearchEngine( + inputEngine, + types, + permissionEvaluator, + config, + ) : inputEngine; const filterResultSet = ({ results, ...resultSet }: SearchResultSet) => ({