Use PermissionEvaluator

Signed-off-by: Vincenzo Scamporlino <me@vinzscam.dev>
This commit is contained in:
Vincenzo Scamporlino
2022-03-28 12:16:27 +02:00
parent 3c8cfaaa80
commit dc8037213c
8 changed files with 29 additions and 27 deletions
+2 -2
View File
@@ -19,9 +19,9 @@ import { JsonValue } from '@backstage/types';
import { LocationEntityV1alpha1 } from '@backstage/catalog-model';
import { Logger } from 'winston';
import { Permission } from '@backstage/plugin-permission-common';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionCondition } from '@backstage/plugin-permission-common';
import { PermissionCriteria } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { PermissionRule } from '@backstage/plugin-permission-node';
import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
@@ -181,7 +181,7 @@ export type CatalogEnvironment = {
database: PluginDatabaseManager;
config: Config;
reader: UrlReader;
permissions: PermissionAuthorizer;
permissions: PermissionEvaluator;
};
// @alpha
@@ -30,7 +30,7 @@ describe('AuthorizedEntitiesCatalog', () => {
};
const fakePermissionApi = {
authorize: jest.fn(),
policyDecision: jest.fn(),
query: jest.fn(),
};
const createCatalog = (...rules: CatalogPermissionRule[]) =>
@@ -46,7 +46,7 @@ describe('AuthorizedEntitiesCatalog', () => {
describe('entities', () => {
it('returns empty response on DENY', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{ result: AuthorizeResult.DENY },
]);
const catalog = createCatalog();
@@ -62,7 +62,7 @@ describe('AuthorizedEntitiesCatalog', () => {
});
it('calls underlying catalog method with correct filter on CONDITIONAL', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{
result: AuthorizeResult.CONDITIONAL,
conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] },
@@ -79,7 +79,7 @@ describe('AuthorizedEntitiesCatalog', () => {
});
it('calls underlying catalog method on ALLOW', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{ result: AuthorizeResult.ALLOW },
]);
const catalog = createCatalog();
@@ -99,7 +99,7 @@ describe('AuthorizedEntitiesCatalog', () => {
{ kind: 'component', namespace: 'default', name: 'my-component' },
],
});
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{ result: AuthorizeResult.DENY },
]);
const catalog = new AuthorizedEntitiesCatalog(
@@ -114,7 +114,7 @@ describe('AuthorizedEntitiesCatalog', () => {
});
it('throws error on CONDITIONAL authorization that evaluates to 0 entities', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{
result: AuthorizeResult.CONDITIONAL,
conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] },
@@ -133,7 +133,7 @@ describe('AuthorizedEntitiesCatalog', () => {
});
it('calls underlying catalog method on CONDITIONAL authorization that evaluates to nonzero entities', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{
result: AuthorizeResult.CONDITIONAL,
conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] },
@@ -159,7 +159,7 @@ describe('AuthorizedEntitiesCatalog', () => {
{ kind: 'component', namespace: 'default', name: 'my-component' },
],
});
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{ result: AuthorizeResult.ALLOW },
]);
const catalog = new AuthorizedEntitiesCatalog(
@@ -253,7 +253,7 @@ describe('AuthorizedEntitiesCatalog', () => {
describe('facets', () => {
it('returns empty response on DENY', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{ result: AuthorizeResult.DENY },
]);
const catalog = createCatalog();
@@ -269,7 +269,7 @@ describe('AuthorizedEntitiesCatalog', () => {
});
it('calls underlying catalog method with correct filter on CONDITIONAL', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{
result: AuthorizeResult.CONDITIONAL,
conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] },
@@ -287,7 +287,7 @@ describe('AuthorizedEntitiesCatalog', () => {
});
it('calls underlying catalog method on ALLOW', async () => {
fakePermissionApi.policyDecision.mockResolvedValue([
fakePermissionApi.query.mockResolvedValue([
{ result: AuthorizeResult.ALLOW },
]);
const catalog = createCatalog();
@@ -22,7 +22,7 @@ import {
import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
import {
AuthorizeResult,
PermissionAuthorizer,
PermissionEvaluator,
} from '@backstage/plugin-permission-common';
import { ConditionTransformer } from '@backstage/plugin-permission-node';
import {
@@ -39,13 +39,13 @@ import { basicEntityFilter } from './request/basicEntityFilter';
export class AuthorizedEntitiesCatalog implements EntitiesCatalog {
constructor(
private readonly entitiesCatalog: EntitiesCatalog,
private readonly permissionApi: PermissionAuthorizer,
private readonly permissionApi: PermissionEvaluator,
private readonly transformConditions: ConditionTransformer<EntityFilter>,
) {}
async entities(request?: EntitiesRequest): Promise<EntitiesResponse> {
const authorizeDecision = (
await this.permissionApi.policyDecision(
await this.permissionApi.query(
[{ permission: catalogEntityReadPermission }],
{ token: request?.authorizationToken },
)
@@ -78,7 +78,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog {
options?: { authorizationToken?: string },
): Promise<void> {
const authorizeResponse = (
await this.permissionApi.policyDecision(
await this.permissionApi.query(
[{ permission: catalogEntityDeletePermission }],
{ token: options?.authorizationToken },
)
@@ -155,7 +155,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog {
async facets(request: EntityFacetsRequest): Promise<EntityFacetsResponse> {
const authorizeDecision = (
await this.permissionApi.policyDecision(
await this.permissionApi.query(
[{ permission: catalogEntityReadPermission }],
{ token: request?.authorizationToken },
)
@@ -79,7 +79,7 @@ import {
CatalogPermissionRule,
permissionRules as catalogPermissionRules,
} from '../permissions/rules';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import {
createConditionTransformer,
createPermissionIntegrationRouter,
@@ -95,7 +95,7 @@ export type CatalogEnvironment = {
database: PluginDatabaseManager;
config: Config;
reader: UrlReader;
permissions: PermissionAuthorizer;
permissions: PermissionEvaluator;
};
/**
@@ -225,6 +225,7 @@ describe('PermissionClient', () => {
resourceType: 'test-resource',
result: AuthorizeResult.CONDITIONAL,
conditions: {
resourceType: 'test-resource',
rule: 'FOO',
params: ['bar'],
},
@@ -271,6 +272,7 @@ describe('PermissionClient', () => {
result: AuthorizeResult.CONDITIONAL,
conditions: {
rule: 'FOO',
resourceType: 'test-resource',
params: ['bar'],
},
}),
+2 -2
View File
@@ -7,7 +7,7 @@ import { Config } from '@backstage/config';
import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import express from 'express';
import { Logger } from 'winston';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
// Warning: (ae-missing-release-tag) "createRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -21,7 +21,7 @@ export function createRouter(options: RouterOptions): Promise<express.Router>;
export type RouterOptions = {
engine: SearchEngine;
types: Record<string, DocumentTypeInfo>;
permissions: PermissionAuthorizer;
permissions: PermissionEvaluator;
config: Config;
logger: Logger;
};
@@ -16,7 +16,7 @@
import { getVoidLogger } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import {
IndexBuilder,
SearchEngine,
@@ -26,11 +26,11 @@ import request from 'supertest';
import { createRouter } from './router';
const mockPermissionAuthorizer: PermissionAuthorizer = {
const mockPermissionAuthorizer: PermissionEvaluator = {
authorize: () => {
throw new Error('Not implemented');
},
policyDecision: () => {
query: () => {
throw new Error('Not implemented');
},
};
+2 -2
View File
@@ -23,7 +23,7 @@ import { InputError } from '@backstage/errors';
import { Config } from '@backstage/config';
import { JsonObject, JsonValue } from '@backstage/types';
import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import {
DocumentTypeInfo,
IndexableResultSet,
@@ -50,7 +50,7 @@ const jsonObjectSchema: z.ZodSchema<JsonObject> = z.lazy(() => {
export type RouterOptions = {
engine: SearchEngine;
types: Record<string, DocumentTypeInfo>;
permissions: PermissionAuthorizer;
permissions: PermissionEvaluator;
config: Config;
logger: Logger;
};