scaffolder: add tests for permission actions

Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com>
This commit is contained in:
Vincenzo Scamporlino
2023-04-04 11:56:57 +02:00
parent 507aa63c34
commit 8d271343e7
@@ -31,6 +31,11 @@ import {
} from '@backstage/plugin-scaffolder-node';
import { UserEntity } from '@backstage/catalog-model';
import { z } from 'zod';
import {
AuthorizeResult,
PermissionEvaluator,
} from '@backstage/plugin-permission-common';
import { RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-common/alpha';
// The Stream module is lazy loaded, so make sure it's in the module cache before mocking fs
void winston.transports.Stream;
@@ -51,6 +56,10 @@ describe('DefaultWorkflowRunner', () => {
let runner: NunjucksWorkflowRunner;
let fakeActionHandler: jest.Mock;
const mockedPermissionApi: jest.Mocked<PermissionEvaluator> = {
authorizeConditional: jest.fn(),
} as unknown as jest.Mocked<PermissionEvaluator>;
const integrations = ScmIntegrations.fromConfig(
new ConfigReader({
integrations: {
@@ -132,11 +141,16 @@ describe('DefaultWorkflowRunner', () => {
},
});
mockedPermissionApi.authorizeConditional.mockResolvedValue([
{ result: AuthorizeResult.ALLOW },
]);
runner = new NunjucksWorkflowRunner({
actionRegistry,
integrations,
workingDirectory: '/tmp',
logger,
permissionApi: mockedPermissionApi,
});
});
@@ -809,4 +823,83 @@ describe('DefaultWorkflowRunner', () => {
expect(fakeActionHandler.mock.calls[0][0].isDryRun).toEqual(true);
});
});
describe('permissions', () => {
it('should throw an error if an actions is not authorized', async () => {
mockedPermissionApi.authorizeConditional.mockResolvedValueOnce([
{ result: AuthorizeResult.DENY },
]);
const task = createMockTaskWithSpec({
apiVersion: 'scaffolder.backstage.io/v1beta3',
parameters: {},
output: {},
steps: [
{
id: 'test',
name: 'name',
action: 'jest-validated-action',
input: { foo: 1 },
},
],
});
await expect(runner.execute(task)).rejects.toThrow(
/Unauthorized action: jest-validated-action. The action is not allowed/,
);
expect(fakeActionHandler).not.toHaveBeenCalled();
});
it(`shouldn't execute actions who aren't authorized`, async () => {
mockedPermissionApi.authorizeConditional.mockResolvedValueOnce([
{
result: AuthorizeResult.CONDITIONAL,
pluginId: 'scaffolder',
resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,
conditions: {
anyOf: [
{
resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,
rule: 'HAS_NUMBER_PROPERTY',
params: {
key: 'foo',
value: 1,
},
},
],
},
},
]);
const task = createMockTaskWithSpec({
apiVersion: 'scaffolder.backstage.io/v1beta3',
parameters: {},
output: {},
steps: [
{
id: 'test1',
name: 'valid action',
action: 'jest-validated-action',
input: { foo: 1 },
},
{
id: 'test2',
name: 'invalid action',
action: 'jest-validated-action',
input: { foo: 2 },
},
],
});
await expect(runner.execute(task)).rejects.toThrow(
`Unauthorized action: jest-validated-action. The action is not allowed. Input: ${JSON.stringify(
{ foo: 2 },
null,
2,
)}`,
);
expect(fakeActionHandler).toHaveBeenCalled();
expect(mockedPermissionApi.authorizeConditional).toHaveBeenCalledTimes(1);
});
});
});