Skip to content

Commit

Permalink
fix(rbac): display resource typed permissions by name too (#1197)
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksandr Andriienko <[email protected]>
  • Loading branch information
AndrienkoAleksandr authored Feb 13, 2024
1 parent a4b9cf0 commit bc4e8e7
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 8 deletions.
106 changes: 106 additions & 0 deletions plugins/rbac-backend/src/service/plugin-endpoint.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getVoidLogger, ReadUrlResponse } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { NotFoundError } from '@backstage/errors';

import { PluginPermissionMetadataCollector } from './plugin-endpoints';

Expand Down Expand Up @@ -50,6 +51,10 @@ describe('plugin-endpoint', () => {
}),
};

beforeEach(() => {
(mockUrlReaderService.readUrl as jest.Mock).mockReset();
});

describe('Test list plugin policies', () => {
it('should return empty plugin policies list', async () => {
const collector = new PluginPermissionMetadataCollector(
Expand Down Expand Up @@ -86,7 +91,108 @@ describe('plugin-endpoint', () => {
permission: 'policy-entity',
policy: 'read',
},
{
permission: 'policy.entity.read',
policy: 'read',
},
]);
});

it('should return plugin policies list without resource type permissions', async () => {
backendPluginIDsProviderMock.getPluginIds.mockReturnValue(['permission']);

mockUrlReaderService.readUrl.mockReturnValue(mockReadUrlResponse);
bufferMock.toString.mockReturnValueOnce(
'{"permissions":[{"type":"resource","name":"policy.entity.read","attributes":{"action":"read"}}]}',
);

const collector = new PluginPermissionMetadataCollector(
mockPluginEndpointDiscovery,
backendPluginIDsProviderMock,
config,
logger,
);
const policiesMetadata = await collector.getPluginPolicies();

expect(policiesMetadata.length).toEqual(1);
expect(policiesMetadata[0].pluginId).toEqual('permission');
expect(policiesMetadata[0].policies).toEqual([
{
permission: 'policy.entity.read',
policy: 'read',
},
]);
});

it('should skip not found error for not found endpoint', async () => {
backendPluginIDsProviderMock.getPluginIds.mockReturnValue([
'permission',
'unknown-plugin-id',
]);

mockUrlReaderService.readUrl = jest
.fn()
.mockImplementation(async (wellKnownURL: string) => {
if (
wellKnownURL ===
'https://localhost:7007/api/permission/.well-known/backstage/permissions/metadata'
) {
return mockReadUrlResponse;
}
throw new NotFoundError();
});
bufferMock.toString.mockReturnValueOnce(
'{"permissions":[{"type":"resource","name":"policy.entity.read","attributes":{"action":"read"}}]}',
);

const collector = new PluginPermissionMetadataCollector(
mockPluginEndpointDiscovery,
backendPluginIDsProviderMock,
config,
logger,
);
const policiesMetadata = await collector.getPluginPolicies();

expect(policiesMetadata.length).toEqual(1);
expect(policiesMetadata[0].pluginId).toEqual('permission');
expect(policiesMetadata[0].policies).toEqual([
{
permission: 'policy.entity.read',
policy: 'read',
},
]);
});

it('should throw error when it is not possible to retrieve permission metadata for known endpoint', async () => {
backendPluginIDsProviderMock.getPluginIds.mockReturnValue([
'permission',
'catalog',
]);

mockUrlReaderService.readUrl = jest
.fn()
.mockImplementation(async (wellKnownURL: string) => {
if (
wellKnownURL ===
'https://localhost:7007/api/permission/.well-known/backstage/permissions/metadata'
) {
return mockReadUrlResponse;
}
throw new Error('Unexpected error');
});
bufferMock.toString.mockReturnValueOnce(
'{"permissions":[{"type":"resource","name":"policy.entity.read","attributes":{"action":"read"}}]}',
);

const collector = new PluginPermissionMetadataCollector(
mockPluginEndpointDiscovery,
backendPluginIDsProviderMock,
config,
logger,
);
await expect(collector.getPluginPolicies()).rejects.toThrow(
'Unexpected error',
);
});
});

Expand Down
21 changes: 13 additions & 8 deletions plugins/rbac-backend/src/service/plugin-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,18 @@ export class PluginPermissionMetadataCollector {
}

function permissionsToCasbinPolicies(permissions: Permission[]): Policy[] {
return permissions.map(permission => {
const policy: Policy = {
permission: isResourcePermission(permission)
? permission.resourceType
: permission.name,
const policies = [];
for (const permission of permissions) {
if (isResourcePermission(permission)) {
policies.push({
permission: permission.resourceType,
policy: permission.attributes.action || 'use',
});
}
policies.push({
permission: permission.name,
policy: permission.attributes.action || 'use',
};
return policy;
});
});
}
return policies;
}

0 comments on commit bc4e8e7

Please sign in to comment.