docs/permissions: update to use new integrations service
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -139,7 +139,13 @@ class CustomPermissionPolicy implements PermissionPolicy {
|
||||
|
||||
Now that we have a custom rule defined and added to our policy, we need provide it to the catalog plugin. This step is important because the catalog plugin will use the rule's `toQuery` and `apply` methods while evaluating conditional authorize results. There's no guarantee that the catalog and permission backends are running on the same server, so we must explicitly link the rule to ensure that it's available at runtime.
|
||||
|
||||
The api for providing custom rules may differ between plugins, but there should typically be an [extension point](../backend-system/architecture/05-extension-points.md) that you can use in your created module to add your rule. For the catalog, this extension point is exposed via `catalogPermissionExtensionPoint`. Here's the steps you'll need to take to add the `isInSystemRule` we created above to the catalog:
|
||||
:::warning Warning
|
||||
|
||||
The `PermissionIntegrationsService` is a fairly new addition and not yet supported by all plugins as they might still be using the old `createPermissionIntegrationRouter` that cannot be extended. If you encounter errors when installing custom rules for a plugin, the plugin may need to be switched to using the `PermissionIntegrationsService` first.
|
||||
|
||||
:::
|
||||
|
||||
To install custom rules in a plugin, we need to use the [`PermissionIntegrationsService`](../backend-system/core-services/permissionIntegrations.md). Here's the steps you'll need to take to add the `isInSystemRule` we created above to the catalog:
|
||||
|
||||
1. We will be using the `@backstage/plugin-catalog-node` package as it contains the extension point we need. Run this to add it:
|
||||
|
||||
@@ -147,10 +153,10 @@ The api for providing custom rules may differ between plugins, but there should
|
||||
yarn --cwd packages/backend add @backstage/plugin-catalog-node
|
||||
```
|
||||
|
||||
2. Next create a `catalogPermissionRules.ts` file in the `packages/backend/src/extensions` folder.
|
||||
2. Next create a `catalogPermissionRules.ts` file in the `packages/backend/src/modules` folder.
|
||||
3. Then add this as the contents of the new `catalogPermissionRules.ts` file:
|
||||
|
||||
```typescript title="packages/backend/src/extensions/catalogPermissionRules.ts"
|
||||
```typescript title="packages/backend/src/modules/catalogPermissionRules.ts"
|
||||
import { createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import { catalogPermissionExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { isInSystemRule } from './permissionPolicyExtension';
|
||||
@@ -160,9 +166,9 @@ The api for providing custom rules may differ between plugins, but there should
|
||||
moduleId: 'permission-rules',
|
||||
register(reg) {
|
||||
reg.registerInit({
|
||||
deps: { catalog: catalogPermissionExtensionPoint },
|
||||
async init({ catalog }) {
|
||||
catalog.addPermissionRules(isInSystemRule);
|
||||
deps: { permissionIntegrations: coreServices.permissionIntegrations },
|
||||
async init({ permissionIntegrations }) {
|
||||
permissionIntegrations.addPermissionRules([isInSystemRule]);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -67,8 +67,6 @@ import { LoggerService, HttpAuthService } from '@backstage/backend-plugin-api';
|
||||
import { InputError, NotAllowedError } from '@backstage/errors';
|
||||
import { LoggerService, HttpAuthService, PermissionsService } from '@backstage/backend-plugin-api';
|
||||
import { AuthorizeResult } from '@backstage/plugin-permission-common';
|
||||
import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';
|
||||
import { todoListCreatePermission } from '@internal/plugin-todo-list-common';
|
||||
/* highlight-add-end */
|
||||
|
||||
export interface RouterOptions {
|
||||
@@ -86,12 +84,6 @@ export async function createRouter(
|
||||
/* highlight-add-next-line */
|
||||
const { logger, httpAuth, permissions } = options;
|
||||
|
||||
/* highlight-add-start */
|
||||
const permissionIntegrationRouter = createPermissionIntegrationRouter({
|
||||
permissions: [todoListCreatePermission],
|
||||
});
|
||||
/* highlight-add-end */
|
||||
|
||||
const router = Router();
|
||||
router.use(express.json());
|
||||
|
||||
@@ -100,9 +92,6 @@ export async function createRouter(
|
||||
response.json({ status: 'ok' });
|
||||
});
|
||||
|
||||
/* highlight-add-next-line */
|
||||
router.use(permissionIntegrationRouter);
|
||||
|
||||
router.get('/todos', async (_req, res) => {
|
||||
res.json(getAll());
|
||||
});
|
||||
@@ -137,11 +126,13 @@ export async function createRouter(
|
||||
// ...
|
||||
```
|
||||
|
||||
Pass the `permissions` object to the plugin in `plugins/todo-list-backend/src/plugin.ts`:
|
||||
Pass the `permissions` service and register the new permission to the plugin in `plugins/todo-list-backend/src/plugin.ts`:
|
||||
|
||||
```ts title="plugins/todo-list-backend/src/plugin.ts"
|
||||
import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';
|
||||
import { createRouter } from './service/router';
|
||||
/* highlight-add-next-line */
|
||||
import { todoListCreatePermission } from '@internal/plugin-todo-list-common';
|
||||
|
||||
export const exampleTodoListPlugin = createBackendPlugin({
|
||||
pluginId: 'todolist',
|
||||
@@ -153,11 +144,16 @@ export const exampleTodoListPlugin = createBackendPlugin({
|
||||
httpRouter: coreServices.httpRouter,
|
||||
/* highlight-add-next-line */
|
||||
permissions: coreServices.permissions,
|
||||
/* highlight-add-next-line */
|
||||
permissionIntegrations: coreServices.permissionIntegrations,
|
||||
},
|
||||
/* highlight-remove-next-line */
|
||||
async init({ logger, httpAuth, httpRouter }) {
|
||||
/* highlight-add-next-line */
|
||||
async init({ logger, httpAuth, httpRouter, permissions }) {
|
||||
async init({ httpAuth, logger, httpRouter, permissions, permissionIntegrations }) {
|
||||
/* highlight-add-next-line */
|
||||
permissionIntegrations.addPermissions([todoListCreatePermission]);
|
||||
|
||||
httpRouter.use(
|
||||
await createRouter({
|
||||
logger,
|
||||
|
||||
@@ -47,9 +47,9 @@ Notice that unlike `todoListCreatePermission`, the `todoListUpdatePermission` pe
|
||||
|
||||
## Setting up authorization for the update permission
|
||||
|
||||
To start, let's edit `plugins/todo-list-backend/src/service/router.ts` in the same manner as we did in the previous section:
|
||||
To start, let's edit `plugins/todo-list-backend/src/plugin.ts` to add the new permission to our plugin:
|
||||
|
||||
```ts title="plugins/todo-list-backend/src/service/router.ts"
|
||||
```ts title="plugins/todo-list-backend/src/plugin.ts"
|
||||
/* highlight-remove-next-line */
|
||||
import { todoListCreatePermission } from '@internal/plugin-todo-list-common';
|
||||
/* highlight-add-start */
|
||||
@@ -61,14 +61,29 @@ import {
|
||||
|
||||
// ...
|
||||
|
||||
const permissionIntegrationRouter = createPermissionIntegrationRouter({
|
||||
/* highlight-remove-next-line */
|
||||
permissions: [todoListCreatePermission],
|
||||
/* highlight-add-next-line */
|
||||
permissions: [todoListCreatePermission, todoListUpdatePermission],
|
||||
});
|
||||
/* highlight-remove-next-line */
|
||||
permissionIntegrations.addPermissions([todoListCreatePermission]);
|
||||
/* highlight-add-start */
|
||||
permissionIntegrations.addPermissions([
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
]);
|
||||
/* highlight-add-end */
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
Then let's edit `plugins/todo-list-backend/src/service/router.ts` in the same manner as we did in the previous section:
|
||||
|
||||
```ts title="plugins/todo-list-backend/src/service/router.ts"
|
||||
/* highlight-remove-next-line */
|
||||
import { todoListCreatePermission } from '@internal/plugin-todo-list-common';
|
||||
/* highlight-add-start */
|
||||
import {
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
} from '@internal/plugin-todo-list-common';
|
||||
/* highlight-add-end */
|
||||
|
||||
router.put('/todos', async (req, res) => {
|
||||
/* highlight-add-start */
|
||||
@@ -155,49 +170,50 @@ Specifically, the `apply` function is used to understand whether the passed reso
|
||||
|
||||
Let's skip the `toQuery` function for now, we'll come back to that in the next section.
|
||||
|
||||
Now, let's create the new endpoint by editing `plugins/todo-list-backend/src/service/router.ts`. This uses the `createPermissionIntegrationRouter` helper to add the APIs needed by the permission framework to your plugin. You'll need to supply:
|
||||
Now, let's add the new resource type to the permissions system via the
|
||||
`PermissionIntegrationsService`. You'll need to supply:
|
||||
|
||||
- `getResources`: a function that accepts an array of `resourceRefs` in the same format you expect to be passed to `authorize`, and returns an array of the corresponding resources.
|
||||
- `resourceType`: the same value used in the permission rule above.
|
||||
- `permissions`: the list of permissions that your plugin accepts.
|
||||
- `rules`: an array of all the permission rules you want to support in conditional decisions.
|
||||
|
||||
```ts title="plugins/todo-list-backend/src/service/router.ts"
|
||||
```ts title="plugins/todo-list-backend/src/plugin.ts"
|
||||
// ...
|
||||
import {
|
||||
coreServices,
|
||||
createBackendPlugin,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { createRouter } from './service/router';
|
||||
import {
|
||||
/* highlight-add-next-line */
|
||||
TODO_LIST_RESOURCE_TYPE,
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
} from '@internal/plugin-todo-list-common';
|
||||
/* highlight-remove-next-line */
|
||||
import { add, getAll, update } from './todos';
|
||||
/* highlight-add-start */
|
||||
import { add, getAll, getTodo, update } from './todos';
|
||||
import { getTodo } from './todos';
|
||||
import { rules } from './rules';
|
||||
/* highlight-add-end */
|
||||
|
||||
export async function createRouter(
|
||||
options: RouterOptions,
|
||||
): Promise<express.Router> {
|
||||
const { logger, identity, permissions } = options;
|
||||
// ...
|
||||
|
||||
const permissionIntegrationRouter = createPermissionIntegrationRouter({
|
||||
permissions: [todoListCreatePermission, todoListUpdatePermission],
|
||||
/* highlight-add-start */
|
||||
getResources: async resourceRefs => {
|
||||
return resourceRefs.map(getTodo);
|
||||
},
|
||||
resourceType: TODO_LIST_RESOURCE_TYPE,
|
||||
rules: Object.values(rules),
|
||||
/* highlight-add-end */
|
||||
});
|
||||
|
||||
const router = Router();
|
||||
router.use(express.json());
|
||||
|
||||
// ...
|
||||
}
|
||||
/* highlight-remove-start */
|
||||
permissionIntegrations.addPermissions([
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
]);
|
||||
/* highlight-remove-end */
|
||||
/* highlight-add-start */
|
||||
permissionIntegrations.addResourceType({
|
||||
resourceType: TODO_LIST_RESOURCE_TYPE,
|
||||
permissions: [todoListCreatePermission, todoListUpdatePermission],
|
||||
rules: Object.values(rules),
|
||||
getResources: async resourceRefs => {
|
||||
return Promise.all(resourceRefs.map(getTodo));
|
||||
},
|
||||
});
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
## Provide utilities for policy authors
|
||||
|
||||
@@ -84,14 +84,41 @@ export const todoListPermissions = [
|
||||
|
||||
## Using conditional policy decisions
|
||||
|
||||
As usual, we'll start by updating the permission integration to include the new permission:
|
||||
|
||||
```ts title="plugins/todo-list-backend/src/plugin.ts"
|
||||
import {
|
||||
TODO_LIST_RESOURCE_TYPE,
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
/* highlight-add-next-line */
|
||||
todoListReadPermission,
|
||||
} from '@internal/plugin-todo-list-common';
|
||||
|
||||
// ...
|
||||
|
||||
permissionIntegrations.addResourceType({
|
||||
resourceType: TODO_LIST_RESOURCE_TYPE,
|
||||
/* highlight-remove-next-line */
|
||||
permissions: [todoListCreatePermission, todoListUpdatePermission],
|
||||
/* highlight-add-next-line */
|
||||
permissions: [
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
todoListReadPermission,
|
||||
],
|
||||
rules: Object.values(rules),
|
||||
getResources: async resourceRefs => {
|
||||
return Promise.all(resourceRefs.map(getTodo));
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
So far we've only used the `PermissionsService.authorize` method, which will evaluate conditional decisions before returning a result. In this step, we want to evaluate conditional decisions within our plugin, so we'll use `PermissionsService.authorizeConditional` instead.
|
||||
|
||||
```ts title="plugins/todo-list-backend/src/service/router.ts"
|
||||
/* highlight-remove-next-line */
|
||||
import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';
|
||||
/* highlight-add-start */
|
||||
import {
|
||||
createPermissionIntegrationRouter,
|
||||
createConditionTransformer,
|
||||
ConditionTransformer,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
@@ -101,7 +128,6 @@ import { add, getAll, getTodo, update } from './todos';
|
||||
/* highlight-add-next-line */
|
||||
import { add, getAll, getTodo, TodoFilter, update } from './todos';
|
||||
import {
|
||||
TODO_LIST_RESOURCE_TYPE,
|
||||
todoListCreatePermission,
|
||||
todoListUpdatePermission,
|
||||
/* highlight-add-next-line */
|
||||
@@ -110,20 +136,6 @@ import {
|
||||
|
||||
// ...
|
||||
|
||||
const permissionIntegrationRouter = createPermissionIntegrationRouter({
|
||||
/* highlight-remove-next-line */
|
||||
permissions: [todoListCreatePermission, todoListUpdatePermission],
|
||||
/* highlight-add-next-line */
|
||||
permissions: [todoListCreatePermission, todoListUpdatePermission, todoListReadPermission],
|
||||
getResources: async resourceRefs => {
|
||||
return resourceRefs.map(getTodo);
|
||||
},
|
||||
resourceType: TODO_LIST_RESOURCE_TYPE,
|
||||
rules: Object.values(rules),
|
||||
});
|
||||
|
||||
// ...
|
||||
|
||||
/* highlight-add-next-line */
|
||||
const transformConditions: ConditionTransformer<TodoFilter> = createConditionTransformer(Object.values(rules));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user