@backstage-community/plugin-rbac-backend 6.3.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +3 -3
- package/dist/index.d.ts +3 -6
- package/dist/plugin.cjs.js +9 -6
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/service/policies-rest-api.cjs.js +23 -23
- package/dist/service/policies-rest-api.cjs.js.map +1 -1
- package/dist/service/policy-builder.cjs.js +13 -15
- package/dist/service/policy-builder.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +3 -1
- package/dist/service/router.cjs.js.map +1 -1
- package/package.json +16 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
### Dependencies
|
|
2
2
|
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 2e732e8: **BREAKING**: Removal of the deprecated createRouter from @backstage/plugin-permission-backend. This results in a new requirement of having the permission plugin installed alongside the RBAC backend plugin.
|
|
8
|
+
|
|
9
|
+
Recent changes to the @backstage/plugin-permission-backend resulted in the deprecating and removal of `createRouter` which was primarily used as a way to start both the permission backend plugin and the RBAC backend plugin at the same time. This removal now results in the requirement of having the permission backend plugin installed separately to ensure that the RBAC backend plugin works accordingly.
|
|
10
|
+
|
|
11
|
+
Changes required to `packages/backend/src/index.ts`
|
|
12
|
+
|
|
13
|
+
```diff
|
|
14
|
+
// permission plugin
|
|
15
|
+
+ backend.add(import('@backstage/plugin-permission-backend'));
|
|
16
|
+
backend.add(import('@backstage-community/plugin-rbac-backend'));
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 4b58a1d: Backstage version bump to v1.39.0
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 6a59fcf: remove support and lifecycle keywords in package.json
|
|
26
|
+
- Updated dependencies [6a59fcf]
|
|
27
|
+
- Updated dependencies [4b58a1d]
|
|
28
|
+
- @backstage-community/plugin-rbac-common@1.18.0
|
|
29
|
+
- @backstage-community/plugin-rbac-node@1.12.0
|
|
30
|
+
|
|
3
31
|
## 6.3.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ Add the RBAC plugin packages as dependencies by running the following command.
|
|
|
34
34
|
yarn workspace backend add @backstage-community/plugin-rbac-backend
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
**NOTE**: If you are using Red Hat Developer Hub backend plugin is pre-installed and you do not need this step.
|
|
37
|
+
**NOTE**: If you are using Red Hat Developer Hub, backend plugin is pre-installed and you do not need this step.
|
|
38
38
|
|
|
39
39
|
### Configuring the Backend
|
|
40
40
|
|
|
@@ -42,11 +42,11 @@ yarn workspace backend add @backstage-community/plugin-rbac-backend
|
|
|
42
42
|
|
|
43
43
|
The RBAC plugin supports the integration with the new backend system.
|
|
44
44
|
|
|
45
|
-
Add the RBAC plugin to the `packages/backend/src/index.ts` file and remove the
|
|
45
|
+
Add the RBAC plugin to the `packages/backend/src/index.ts` file and remove the Allow All Permission policy module.
|
|
46
46
|
|
|
47
47
|
```diff
|
|
48
48
|
// permission plugin
|
|
49
|
-
|
|
49
|
+
backend.add(import('@backstage/plugin-permission-backend'));
|
|
50
50
|
- backend.add(
|
|
51
51
|
- import('@backstage/plugin-permission-backend-module-allow-all-policy'),
|
|
52
52
|
- );
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
-
import { LoggerService, DiscoveryService, AuthService, HttpAuthService, AuditorService,
|
|
2
|
+
import { LoggerService, DiscoveryService, AuthService, HttpAuthService, AuditorService, LifecycleService, PermissionsRegistryService, PermissionsService } from '@backstage/backend-plugin-api';
|
|
3
3
|
import { Config } from '@backstage/config';
|
|
4
4
|
import express, { Router } from 'express';
|
|
5
5
|
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
|
6
|
-
import { PermissionPolicy } from '@backstage/plugin-permission-node';
|
|
7
6
|
import { PluginIdProvider, RBACProvider } from '@backstage-community/plugin-rbac-node';
|
|
8
7
|
export { PluginIdProvider } from '@backstage-community/plugin-rbac-node';
|
|
8
|
+
import { PolicyExtensionPoint } from '@backstage/plugin-permission-node/alpha';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @public
|
|
@@ -30,9 +30,9 @@ type EnvOptions = {
|
|
|
30
30
|
auth: AuthService;
|
|
31
31
|
httpAuth: HttpAuthService;
|
|
32
32
|
auditor: AuditorService;
|
|
33
|
-
userInfo: UserInfoService;
|
|
34
33
|
lifecycle: LifecycleService;
|
|
35
34
|
permissionsRegistry: PermissionsRegistryService;
|
|
35
|
+
policy: PolicyExtensionPoint;
|
|
36
36
|
};
|
|
37
37
|
/**
|
|
38
38
|
* @public
|
|
@@ -40,11 +40,8 @@ type EnvOptions = {
|
|
|
40
40
|
type RBACRouterOptions = {
|
|
41
41
|
config: Config;
|
|
42
42
|
logger: LoggerService;
|
|
43
|
-
discovery: DiscoveryService;
|
|
44
|
-
policy: PermissionPolicy;
|
|
45
43
|
auth: AuthService;
|
|
46
44
|
httpAuth: HttpAuthService;
|
|
47
|
-
userInfo: UserInfoService;
|
|
48
45
|
permissions: PermissionsService;
|
|
49
46
|
permissionsRegistry: PermissionsRegistryService;
|
|
50
47
|
auditor: AuditorService;
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
4
|
var pluginRbacBackend = require('@backstage-community/plugin-rbac-backend');
|
|
5
5
|
var pluginRbacNode = require('@backstage-community/plugin-rbac-node');
|
|
6
|
+
var alpha = require('@backstage/plugin-permission-node/alpha');
|
|
6
7
|
|
|
7
|
-
const rbacPlugin = backendPluginApi.
|
|
8
|
+
const rbacPlugin = backendPluginApi.createBackendModule({
|
|
8
9
|
pluginId: "permission",
|
|
10
|
+
moduleId: "rbac",
|
|
9
11
|
register(env) {
|
|
10
12
|
const pluginIdProviderExtensionPointImpl = new class PluginIdProviderImpl {
|
|
11
13
|
pluginIdProviders = [];
|
|
@@ -35,7 +37,8 @@ const rbacPlugin = backendPluginApi.createBackendPlugin({
|
|
|
35
37
|
auditor: backendPluginApi.coreServices.auditor,
|
|
36
38
|
userInfo: backendPluginApi.coreServices.userInfo,
|
|
37
39
|
lifecycle: backendPluginApi.coreServices.lifecycle,
|
|
38
|
-
permissionsRegistry: backendPluginApi.coreServices.permissionsRegistry
|
|
40
|
+
permissionsRegistry: backendPluginApi.coreServices.permissionsRegistry,
|
|
41
|
+
policy: alpha.policyExtensionPoint
|
|
39
42
|
},
|
|
40
43
|
async init({
|
|
41
44
|
http,
|
|
@@ -46,9 +49,9 @@ const rbacPlugin = backendPluginApi.createBackendPlugin({
|
|
|
46
49
|
auth,
|
|
47
50
|
httpAuth,
|
|
48
51
|
auditor,
|
|
49
|
-
userInfo,
|
|
50
52
|
lifecycle,
|
|
51
|
-
permissionsRegistry
|
|
53
|
+
permissionsRegistry,
|
|
54
|
+
policy
|
|
52
55
|
}) {
|
|
53
56
|
http.use(
|
|
54
57
|
await pluginRbacBackend.PolicyBuilder.build(
|
|
@@ -60,9 +63,9 @@ const rbacPlugin = backendPluginApi.createBackendPlugin({
|
|
|
60
63
|
auth,
|
|
61
64
|
httpAuth,
|
|
62
65
|
auditor,
|
|
63
|
-
userInfo,
|
|
64
66
|
lifecycle,
|
|
65
|
-
permissionsRegistry
|
|
67
|
+
permissionsRegistry,
|
|
68
|
+
policy
|
|
66
69
|
},
|
|
67
70
|
{
|
|
68
71
|
getPluginIds: () => Array.from(
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n coreServices,\n
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\n\nimport { PolicyBuilder } from '@backstage-community/plugin-rbac-backend';\nimport {\n PluginIdProvider,\n PluginIdProviderExtensionPoint,\n pluginIdProviderExtensionPoint,\n RBACProvider,\n rbacProviderExtensionPoint,\n} from '@backstage-community/plugin-rbac-node';\n\nimport { policyExtensionPoint } from '@backstage/plugin-permission-node/alpha';\n\n/**\n * @public\n * RBAC plugin\n *\n */\nexport const rbacPlugin = createBackendModule({\n pluginId: 'permission',\n moduleId: 'rbac',\n register(env) {\n const pluginIdProviderExtensionPointImpl = new (class PluginIdProviderImpl\n implements PluginIdProviderExtensionPoint\n {\n pluginIdProviders: PluginIdProvider[] = [];\n\n addPluginIdProvider(pluginIdProvider: PluginIdProvider): void {\n this.pluginIdProviders.push(pluginIdProvider);\n }\n })();\n\n env.registerExtensionPoint(\n pluginIdProviderExtensionPoint,\n pluginIdProviderExtensionPointImpl,\n );\n\n const rbacProviders = new Array<RBACProvider>();\n\n env.registerExtensionPoint(rbacProviderExtensionPoint, {\n addRBACProvider(\n ...providers: Array<RBACProvider | Array<RBACProvider>>\n ): void {\n rbacProviders.push(...providers.flat());\n },\n });\n\n env.registerInit({\n deps: {\n http: coreServices.httpRouter,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n discovery: coreServices.discovery,\n permissions: coreServices.permissions,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n userInfo: coreServices.userInfo,\n lifecycle: coreServices.lifecycle,\n permissionsRegistry: coreServices.permissionsRegistry,\n policy: policyExtensionPoint,\n },\n async init({\n http,\n config,\n logger,\n discovery,\n permissions,\n auth,\n httpAuth,\n auditor,\n lifecycle,\n permissionsRegistry: permissionsRegistry,\n policy,\n }) {\n http.use(\n await PolicyBuilder.build(\n {\n config,\n logger,\n discovery,\n permissions,\n auth,\n httpAuth,\n auditor,\n lifecycle,\n permissionsRegistry: permissionsRegistry,\n policy,\n },\n {\n getPluginIds: () =>\n Array.from(\n new Set(\n pluginIdProviderExtensionPointImpl.pluginIdProviders.flatMap(\n p => p.getPluginIds(),\n ),\n ),\n ),\n },\n rbacProviders,\n ),\n );\n },\n });\n },\n});\n"],"names":["createBackendModule","pluginIdProviderExtensionPoint","rbacProviderExtensionPoint","coreServices","policyExtensionPoint","PolicyBuilder"],"mappings":";;;;;;;AAoCO,MAAM,aAAaA,oCAAoB,CAAA;AAAA,EAC5C,QAAU,EAAA,YAAA;AAAA,EACV,QAAU,EAAA,MAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAM,MAAA,kCAAA,GAAqC,IAAK,MAAM,oBAEtD,CAAA;AAAA,MACE,oBAAwC,EAAC;AAAA,MAEzC,oBAAoB,gBAA0C,EAAA;AAC5D,QAAK,IAAA,CAAA,iBAAA,CAAkB,KAAK,gBAAgB,CAAA;AAAA;AAC9C,KACC,EAAA;AAEH,IAAI,GAAA,CAAA,sBAAA;AAAA,MACFC,6CAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAM,MAAA,aAAA,GAAgB,IAAI,KAAoB,EAAA;AAE9C,IAAA,GAAA,CAAI,uBAAuBC,yCAA4B,EAAA;AAAA,MACrD,mBACK,SACG,EAAA;AACN,QAAA,aAAA,CAAc,IAAK,CAAA,GAAG,SAAU,CAAA,IAAA,EAAM,CAAA;AAAA;AACxC,KACD,CAAA;AAED,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,MAAMC,6BAAa,CAAA,UAAA;AAAA,QACnB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,aAAaA,6BAAa,CAAA,WAAA;AAAA,QAC1B,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,SAASA,6BAAa,CAAA,OAAA;AAAA,QACtB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,qBAAqBA,6BAAa,CAAA,mBAAA;AAAA,QAClC,MAAQ,EAAAC;AAAA,OACV;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,WAAA;AAAA,QACA,IAAA;AAAA,QACA,QAAA;AAAA,QACA,OAAA;AAAA,QACA,SAAA;AAAA,QACA,mBAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAK,IAAA,CAAA,GAAA;AAAA,UACH,MAAMC,+BAAc,CAAA,KAAA;AAAA,YAClB;AAAA,cACE,MAAA;AAAA,cACA,MAAA;AAAA,cACA,SAAA;AAAA,cACA,WAAA;AAAA,cACA,IAAA;AAAA,cACA,QAAA;AAAA,cACA,OAAA;AAAA,cACA,SAAA;AAAA,cACA,mBAAA;AAAA,cACA;AAAA,aACF;AAAA,YACA;AAAA,cACE,YAAA,EAAc,MACZ,KAAM,CAAA,IAAA;AAAA,gBACJ,IAAI,GAAA;AAAA,kBACF,mCAAmC,iBAAkB,CAAA,OAAA;AAAA,oBACnD,CAAA,CAAA,KAAK,EAAE,YAAa;AAAA;AACtB;AACF;AACF,aACJ;AAAA,YACA;AAAA;AACF,SACF;AAAA;AACF,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var errors = require('@backstage/errors');
|
|
4
|
-
var pluginPermissionBackend = require('@backstage/plugin-permission-backend');
|
|
5
4
|
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
6
5
|
var lodash = require('lodash');
|
|
7
6
|
var pluginRbacCommon = require('@backstage-community/plugin-rbac-common');
|
|
@@ -13,6 +12,7 @@ var policiesValidation = require('../validation/policies-validation.cjs.js');
|
|
|
13
12
|
var conditions = require('../permissions/conditions.cjs.js');
|
|
14
13
|
require('../permissions/rules.cjs.js');
|
|
15
14
|
var permissionDefinitionRoutes = require('./permission-definition-routes.cjs.js');
|
|
15
|
+
var router = require('./router.cjs.js');
|
|
16
16
|
|
|
17
17
|
async function authorizeConditional(request, permission, deps) {
|
|
18
18
|
const { auth, httpAuth, permissions } = deps;
|
|
@@ -51,14 +51,14 @@ class PoliciesServer {
|
|
|
51
51
|
this.rbacProviders = rbacProviders;
|
|
52
52
|
}
|
|
53
53
|
async serve() {
|
|
54
|
-
const router = await
|
|
54
|
+
const router$1 = await router.createRouter(this.options);
|
|
55
55
|
const { logger, auditor, auth, permissionsRegistry } = this.options;
|
|
56
56
|
const isPluginEnabled = this.options.config.getOptionalBoolean("permission.enabled");
|
|
57
57
|
if (!isPluginEnabled) {
|
|
58
|
-
return router;
|
|
58
|
+
return router$1;
|
|
59
59
|
}
|
|
60
60
|
const transformConditions = conditions.conditionTransformerFunc(permissionsRegistry);
|
|
61
|
-
router.get("/", async (request, response) => {
|
|
61
|
+
router$1.get("/", async (request, response) => {
|
|
62
62
|
await authorizeConditional(
|
|
63
63
|
request,
|
|
64
64
|
pluginRbacCommon.policyEntityReadPermission,
|
|
@@ -66,7 +66,7 @@ class PoliciesServer {
|
|
|
66
66
|
);
|
|
67
67
|
response.send({ status: "Authorized" });
|
|
68
68
|
});
|
|
69
|
-
router.get(
|
|
69
|
+
router$1.get(
|
|
70
70
|
"/policies",
|
|
71
71
|
restInterceptor.logAuditorEvent(auditor),
|
|
72
72
|
async (request, response) => {
|
|
@@ -113,7 +113,7 @@ class PoliciesServer {
|
|
|
113
113
|
response.json(body);
|
|
114
114
|
}
|
|
115
115
|
);
|
|
116
|
-
router.get(
|
|
116
|
+
router$1.get(
|
|
117
117
|
"/policies/:kind/:namespace/:name",
|
|
118
118
|
restInterceptor.logAuditorEvent(auditor),
|
|
119
119
|
async (request, response) => {
|
|
@@ -148,7 +148,7 @@ class PoliciesServer {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
);
|
|
151
|
-
router.delete(
|
|
151
|
+
router$1.delete(
|
|
152
152
|
"/policies/:kind/:namespace/:name",
|
|
153
153
|
restInterceptor.logAuditorEvent(auditor),
|
|
154
154
|
async (request, response) => {
|
|
@@ -180,7 +180,7 @@ class PoliciesServer {
|
|
|
180
180
|
response.status(204).end();
|
|
181
181
|
}
|
|
182
182
|
);
|
|
183
|
-
router.post(
|
|
183
|
+
router$1.post(
|
|
184
184
|
"/policies",
|
|
185
185
|
restInterceptor.logAuditorEvent(auditor),
|
|
186
186
|
async (request, response) => {
|
|
@@ -208,7 +208,7 @@ class PoliciesServer {
|
|
|
208
208
|
response.status(201).end();
|
|
209
209
|
}
|
|
210
210
|
);
|
|
211
|
-
router.put(
|
|
211
|
+
router$1.put(
|
|
212
212
|
"/policies/:kind/:namespace/:name",
|
|
213
213
|
restInterceptor.logAuditorEvent(auditor),
|
|
214
214
|
async (request, response) => {
|
|
@@ -270,7 +270,7 @@ class PoliciesServer {
|
|
|
270
270
|
response.status(200).end();
|
|
271
271
|
}
|
|
272
272
|
);
|
|
273
|
-
router.get(
|
|
273
|
+
router$1.get(
|
|
274
274
|
"/roles",
|
|
275
275
|
restInterceptor.logAuditorEvent(auditor),
|
|
276
276
|
async (request, response) => {
|
|
@@ -288,7 +288,7 @@ class PoliciesServer {
|
|
|
288
288
|
response.json(body);
|
|
289
289
|
}
|
|
290
290
|
);
|
|
291
|
-
router.get(
|
|
291
|
+
router$1.get(
|
|
292
292
|
"/roles/:kind/:namespace/:name",
|
|
293
293
|
restInterceptor.logAuditorEvent(auditor),
|
|
294
294
|
async (request, response) => {
|
|
@@ -314,7 +314,7 @@ class PoliciesServer {
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
);
|
|
317
|
-
router.post(
|
|
317
|
+
router$1.post(
|
|
318
318
|
"/roles",
|
|
319
319
|
restInterceptor.logAuditorEvent(auditor),
|
|
320
320
|
async (request, response) => {
|
|
@@ -370,7 +370,7 @@ class PoliciesServer {
|
|
|
370
370
|
response.status(201).end();
|
|
371
371
|
}
|
|
372
372
|
);
|
|
373
|
-
router.put(
|
|
373
|
+
router$1.put(
|
|
374
374
|
"/roles/:kind/:namespace/:name",
|
|
375
375
|
restInterceptor.logAuditorEvent(auditor),
|
|
376
376
|
async (request, response) => {
|
|
@@ -497,7 +497,7 @@ class PoliciesServer {
|
|
|
497
497
|
response.status(200).end();
|
|
498
498
|
}
|
|
499
499
|
);
|
|
500
|
-
router.delete(
|
|
500
|
+
router$1.delete(
|
|
501
501
|
"/roles/:kind/:namespace/:name",
|
|
502
502
|
restInterceptor.logAuditorEvent(auditor),
|
|
503
503
|
async (request, response) => {
|
|
@@ -565,7 +565,7 @@ class PoliciesServer {
|
|
|
565
565
|
response.status(204).end();
|
|
566
566
|
}
|
|
567
567
|
);
|
|
568
|
-
router.get(
|
|
568
|
+
router$1.get(
|
|
569
569
|
"/roles/conditions",
|
|
570
570
|
restInterceptor.logAuditorEvent(auditor),
|
|
571
571
|
async (request, response) => {
|
|
@@ -601,7 +601,7 @@ class PoliciesServer {
|
|
|
601
601
|
response.json(body);
|
|
602
602
|
}
|
|
603
603
|
);
|
|
604
|
-
router.post(
|
|
604
|
+
router$1.post(
|
|
605
605
|
"/roles/conditions",
|
|
606
606
|
restInterceptor.logAuditorEvent(auditor),
|
|
607
607
|
async (request, response) => {
|
|
@@ -623,7 +623,7 @@ class PoliciesServer {
|
|
|
623
623
|
response.status(201).json(body);
|
|
624
624
|
}
|
|
625
625
|
);
|
|
626
|
-
router.get(
|
|
626
|
+
router$1.get(
|
|
627
627
|
"/roles/conditions/:id",
|
|
628
628
|
restInterceptor.logAuditorEvent(auditor),
|
|
629
629
|
async (request, response) => {
|
|
@@ -657,7 +657,7 @@ class PoliciesServer {
|
|
|
657
657
|
response.json(body);
|
|
658
658
|
}
|
|
659
659
|
);
|
|
660
|
-
router.delete(
|
|
660
|
+
router$1.delete(
|
|
661
661
|
"/roles/conditions/:id",
|
|
662
662
|
restInterceptor.logAuditorEvent(auditor),
|
|
663
663
|
async (request, response) => {
|
|
@@ -693,7 +693,7 @@ class PoliciesServer {
|
|
|
693
693
|
response.status(204).end();
|
|
694
694
|
}
|
|
695
695
|
);
|
|
696
|
-
router.put(
|
|
696
|
+
router$1.put(
|
|
697
697
|
"/roles/conditions/:id",
|
|
698
698
|
restInterceptor.logAuditorEvent(auditor),
|
|
699
699
|
async (request, response) => {
|
|
@@ -732,7 +732,7 @@ class PoliciesServer {
|
|
|
732
732
|
response.status(200).end();
|
|
733
733
|
}
|
|
734
734
|
);
|
|
735
|
-
router.post(
|
|
735
|
+
router$1.post(
|
|
736
736
|
"/refresh/:id",
|
|
737
737
|
restInterceptor.logAuditorEvent(auditor),
|
|
738
738
|
async (request, response) => {
|
|
@@ -758,14 +758,14 @@ class PoliciesServer {
|
|
|
758
758
|
}
|
|
759
759
|
);
|
|
760
760
|
permissionDefinitionRoutes.registerPermissionDefinitionRoutes(
|
|
761
|
-
router,
|
|
761
|
+
router$1,
|
|
762
762
|
this.pluginPermMetaData,
|
|
763
763
|
this.pluginIdProvider,
|
|
764
764
|
this.extraPluginsIdStorage,
|
|
765
765
|
this.options
|
|
766
766
|
);
|
|
767
|
-
router.use(restInterceptor.setAuditorError());
|
|
768
|
-
return router;
|
|
767
|
+
router$1.use(restInterceptor.setAuditorError());
|
|
768
|
+
return router$1;
|
|
769
769
|
}
|
|
770
770
|
getEntityReference(request, role) {
|
|
771
771
|
const kind = request.params.kind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policies-rest-api.cjs.js","sources":["../../src/service/policies-rest-api.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type {\n AuthService,\n BackstageCredentials,\n BackstageServicePrincipal,\n BackstageUserPrincipal,\n HttpAuthService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\nimport { createRouter } from '@backstage/plugin-permission-backend';\nimport {\n AuthorizeResult,\n BasicPermission,\n PolicyDecision,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\n\nimport express from 'express';\nimport type { Request } from 'express-serve-static-core';\nimport { isEmpty, isEqual } from 'lodash';\nimport type { ParsedQs } from 'qs';\n\nimport {\n policyEntityCreatePermission,\n policyEntityDeletePermission,\n policyEntityReadPermission,\n policyEntityUpdatePermission,\n type PermissionAction,\n type Role,\n type RoleBasedPolicy,\n type RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\nimport type { RBACProvider } from '@backstage-community/plugin-rbac-node';\n\nimport { setAuditorError, logAuditorEvent } from '../auditor/rest-interceptor';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport {\n daoToMetadata,\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport {\n buildRoleSourceMap,\n deepSortedEqual,\n isPermissionAction,\n policyToString,\n processConditionMapping,\n matches,\n} from '../helper';\nimport { validateRoleCondition } from '../validation/condition-validation';\nimport {\n validateEntityReference,\n validatePolicy,\n validateRole,\n validateSource,\n} from '../validation/policies-validation';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { RBACRouterOptions } from './policy-builder';\nimport { conditionTransformerFunc, RBACFilters } from '../permissions';\nimport { registerPermissionDefinitionRoutes } from './permission-definition-routes';\nimport { PermissionDependentPluginStore } from '../database/extra-permission-enabled-plugins-storage';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\n\nexport async function authorizeConditional(\n request: Request,\n permission: ResourcePermission<'policy-entity'> | BasicPermission,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n permissions: PermissionsService;\n },\n): Promise<{\n decision: PolicyDecision;\n credentials: BackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal\n >;\n}> {\n const { auth, httpAuth, permissions } = deps;\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user', 'service'],\n });\n\n // allow service to service communication, but only with read permission\n if (\n auth.isPrincipal(credentials, 'service') &&\n permission !== policyEntityReadPermission\n ) {\n throw new NotAllowedError(\n `Only credential principal with type 'user' permitted to modify permissions`,\n );\n }\n\n let decision: PolicyDecision;\n if (permission.type === 'resource') {\n decision = (\n await permissions.authorizeConditional([{ permission }], {\n credentials,\n })\n )[0];\n } else {\n decision = (\n await permissions.authorize([{ permission }], {\n credentials,\n })\n )[0];\n }\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n return { decision, credentials };\n}\n\nexport class PoliciesServer {\n constructor(\n private readonly options: RBACRouterOptions,\n private readonly enforcer: EnforcerDelegate,\n private readonly conditionalStorage: ConditionalStorage,\n private readonly pluginPermMetaData: PluginPermissionMetadataCollector,\n private readonly roleMetadata: RoleMetadataStorage,\n private readonly extraPluginsIdStorage: PermissionDependentPluginStore,\n private readonly pluginIdProvider: ExtendablePluginIdProvider,\n private readonly rbacProviders?: RBACProvider[],\n ) {}\n\n async serve(): Promise<express.Router> {\n const router = await createRouter(this.options);\n\n const { logger, auditor, auth, permissionsRegistry } = this.options;\n\n const isPluginEnabled =\n this.options.config.getOptionalBoolean('permission.enabled');\n if (!isPluginEnabled) {\n return router;\n }\n\n const transformConditions = conditionTransformerFunc(permissionsRegistry);\n\n router.get('/', async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n response.send({ status: 'Authorized' });\n });\n\n // Policy CRUD\n\n router.get(\n '/policies',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n let policies: string[][] = [];\n if (this.isPolicyFilterEnabled(request)) {\n const entityRef = this.getFirstQuery(request.query.entityRef);\n const permission = this.getFirstQuery(request.query.permission);\n const policy = this.getFirstQuery(request.query.policy);\n const effect = this.getFirstQuery(request.query.effect);\n\n const matchedRoleName = roleMetadata.flatMap(\n role => role.roleEntityRef,\n );\n\n const filter: string[] = [entityRef, permission, policy, effect];\n policies = matchedRoleName.includes(entityRef)\n ? await this.enforcer.getFilteredPolicy(0, ...filter)\n : [];\n } else {\n for (const role of roleMetadata) {\n policies.push(\n ...(await this.enforcer.getFilteredPolicy(\n 0,\n ...[role.roleEntityRef],\n )),\n );\n }\n }\n\n const body = await this.transformPolicyArray(...policies);\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n body.map(policy => {\n if (\n policy.permission === 'policy-entity' &&\n policy.policy === 'create'\n ) {\n policy.permission = 'policy.entity.create';\n logger.warn(\n `Permission policy with resource type 'policy-entity' and action 'create' has been removed. Please consider updating policy ${[policy.entityReference, 'policy-entity', policy.policy, policy.effect]} to use 'policy.entity.create' instead of 'policy-entity' from source ${policy.metadata?.source}`,\n );\n }\n });\n\n response.json(body);\n },\n );\n\n router.get(\n '/policies/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n const matchedRoleName = roleMetadata.flatMap(role => {\n return role.roleEntityRef;\n });\n\n const entityRef = this.getEntityReference(request);\n\n const policy = matchedRoleName.includes(entityRef)\n ? await this.enforcer.getFilteredPolicy(0, entityRef)\n : [];\n if (policy.length !== 0) {\n const body = await this.transformPolicyArray(...policy);\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n body.map(bodyPolicy => {\n if (\n bodyPolicy.permission === 'policy-entity' &&\n bodyPolicy.policy === 'create'\n ) {\n bodyPolicy.permission = 'policy.entity.create';\n logger.warn(\n `Permission policy with resource type 'policy-entity' and action 'create' has been removed. Please consider updating policy ${[bodyPolicy.entityReference, 'policy-entity', bodyPolicy.policy, bodyPolicy.effect]} to use 'policy.entity.create' instead of 'policy-entity' from source ${bodyPolicy.metadata?.source}`,\n );\n }\n });\n\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n },\n );\n\n router.delete(\n '/policies/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityDeletePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const entityRef = this.getEntityReference(request);\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n policyRaw.forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedPolicies = await this.processPolicies(\n policyRaw,\n true,\n undefined,\n conditionsFilter,\n );\n\n await this.enforcer.removePolicies(processedPolicies);\n\n response.locals.meta = { policies: processedPolicies }; // auditor\n\n response.status(204).end();\n },\n );\n\n router.post(\n '/policies',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n const processedPolicies = await this.processPolicies(\n policyRaw,\n false,\n undefined,\n );\n\n const entityRef = processedPolicies[0][0];\n const roleMetadata =\n await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.addPolicies(processedPolicies);\n\n response.locals.meta = { policies: processedPolicies }; // auditor\n\n response.status(201).end();\n },\n );\n\n router.put(\n '/policies/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityUpdatePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const entityRef = this.getEntityReference(request);\n\n const oldPolicyRaw: RoleBasedPolicy[] = request.body.oldPolicy;\n if (isEmpty(oldPolicyRaw)) {\n throw new InputError(`'oldPolicy' object must be present`); // 400\n }\n const newPolicyRaw: RoleBasedPolicy[] = request.body.newPolicy;\n if (isEmpty(newPolicyRaw)) {\n throw new InputError(`'newPolicy' object must be present`); // 400\n }\n\n [...oldPolicyRaw, ...newPolicyRaw].forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedOldPolicy = await this.processPolicies(\n oldPolicyRaw,\n true,\n 'old policy',\n conditionsFilter,\n );\n\n oldPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n newPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n if (\n isEqual(oldPolicyRaw, newPolicyRaw) &&\n !oldPolicyRaw.some(isEmpty)\n ) {\n response.status(204).end();\n } else if (oldPolicyRaw.length > newPolicyRaw.length) {\n throw new InputError(\n `'oldPolicy' object has more permission policies compared to 'newPolicy' object`,\n );\n }\n\n const processedNewPolicy = await this.processPolicies(\n newPolicyRaw,\n false,\n 'new policy',\n conditionsFilter,\n );\n\n const roleMetadata =\n await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.updatePolicies(\n processedOldPolicy,\n processedNewPolicy,\n );\n\n response.locals.meta = { policies: processedNewPolicy }; // auditor\n\n response.status(200).end();\n },\n );\n\n // Role CRUD\n\n router.get(\n '/roles',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roles = await this.enforcer.getGroupingPolicy();\n const body = await this.transformRoleArray(conditionsFilter, ...roles);\n\n response.json(body);\n },\n );\n\n router.get(\n '/roles/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n const role = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n\n const body = await this.transformRoleArray(conditionsFilter, ...role);\n if (body.length !== 0) {\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n },\n );\n\n router.post(\n '/roles',\n logAuditorEvent(auditor),\n async (request, response) => {\n const uniqueItems = new Set<string>();\n const { credentials } = await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n const roleRaw: Role = request.body;\n let err = validateRole(roleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid role definition. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(roleRaw);\n\n const rMetadata = await this.roleMetadata.findRoleMetadata(\n roleRaw.name,\n );\n\n err = await validateSource('rest', rMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to add role: ${err.message}`);\n }\n\n const roles = this.transformRoleToArray(roleRaw);\n\n for (const role of roles) {\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n throw new ConflictError(); // 409\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n const modifiedBy = (\n credentials as BackstageCredentials<BackstageUserPrincipal>\n ).principal.userEntityRef;\n const metadata: RoleMetadataDao = {\n roleEntityRef: roleRaw.name,\n source: 'rest',\n description: roleRaw.metadata?.description ?? '',\n author: modifiedBy,\n modifiedBy,\n owner: roleRaw.metadata?.owner ?? modifiedBy,\n };\n\n await this.enforcer.addGroupingPolicies(roles, metadata);\n\n response.locals.meta = { ...metadata, members: roles.map(gp => gp[0]) }; // auditor\n\n response.status(201).end();\n },\n );\n\n router.put(\n '/roles/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n const uniqueItems = new Set<string>();\n let conditionsFilter: RBACFilters | undefined;\n const { decision, credentials } = await authorizeConditional(\n request,\n policyEntityUpdatePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n const oldRoleRaw: Role = request.body.oldRole;\n\n if (!oldRoleRaw) {\n throw new InputError(`'oldRole' object must be present`); // 400\n }\n const newRoleRaw: Role = request.body.newRole;\n if (!newRoleRaw) {\n throw new InputError(`'newRole' object must be present`); // 400\n }\n\n oldRoleRaw.name = roleEntityRef;\n let err = validateRole(oldRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid old role object. Cause: ${err.message}`,\n );\n }\n err = validateRole(newRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid new role object. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(oldRoleRaw);\n this.transformMemberReferencesToLowercase(newRoleRaw);\n\n const oldRole = this.transformRoleToArray(oldRoleRaw);\n const newRole = this.transformRoleToArray(newRoleRaw);\n // todo shell we allow newRole with an empty array?...\n\n const modifiedBy = (\n credentials as BackstageCredentials<BackstageUserPrincipal>\n ).principal.userEntityRef;\n const newMetadata: RoleMetadataDao = {\n ...newRoleRaw.metadata,\n source: newRoleRaw.metadata?.source ?? 'rest',\n roleEntityRef: newRoleRaw.name,\n modifiedBy,\n owner: newRoleRaw.metadata?.owner ?? '',\n };\n\n const oldMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n if (!oldMetadata) {\n throw new NotFoundError(\n `Unable to find metadata for ${roleEntityRef}`,\n );\n }\n\n err = await validateSource('rest', oldMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to edit role: ${err.message}`);\n }\n\n if (!matches(oldMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n if (\n isEqual(oldRole, newRole) &&\n deepSortedEqual(oldMetadata, newMetadata, [\n 'author',\n 'modifiedBy',\n 'createdAt',\n 'lastModified',\n 'owner',\n ])\n ) {\n // no content: old role and new role are equal and their metadata too\n response.status(204).end();\n return;\n }\n\n for (const role of newRole) {\n const hasRole = oldRole.some(element => {\n return isEqual(element, role);\n });\n // if the role is already part of old role and is a grouping policy we want to skip returning a conflict error\n // to allow for other roles to be checked and added\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n if (!hasRole) {\n throw new ConflictError(); // 409\n }\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n uniqueItems.clear();\n for (const role of oldRole) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(\n `Member reference: ${role[0]} was not found for role ${roleEntityRef}`,\n ); // 404\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n await this.enforcer.updateGroupingPolicies(\n oldRole,\n newRole,\n newMetadata,\n );\n\n let message = `Updated ${oldMetadata.roleEntityRef}.`;\n if (newMetadata.roleEntityRef !== oldMetadata.roleEntityRef) {\n message = `${message}. Role entity reference renamed to ${newMetadata.roleEntityRef}`;\n }\n response.locals.meta = {\n ...newMetadata,\n members: newRole.map(gp => gp[0]),\n }; // auditor\n\n response.status(200).end();\n },\n );\n\n router.delete(\n '/roles/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision, credentials } = await authorizeConditional(\n request,\n policyEntityDeletePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n const currentMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n\n if (!matches(currentMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n const err = await validateSource('rest', currentMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to delete role: ${err.message}`);\n }\n\n let roleMembers = [];\n if (request.query.memberReferences) {\n const memberReference = this.getFirstQuery(\n request.query.memberReferences!,\n ).toLocaleLowerCase('en-US');\n const gp = await this.enforcer.getFilteredGroupingPolicy(\n 0,\n memberReference,\n roleEntityRef,\n );\n if (gp.length > 0) {\n roleMembers.push(gp[0]);\n } else {\n throw new NotFoundError(\n `role member '${memberReference}' was not found`,\n ); // 404\n }\n } else {\n roleMembers = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n }\n\n for (const role of roleMembers) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(`role member '${role[0]}' was not found`);\n }\n }\n\n const modifiedBy = (\n credentials as BackstageCredentials<BackstageUserPrincipal>\n ).principal.userEntityRef;\n const metadata: RoleMetadataDao = {\n roleEntityRef,\n source: 'rest',\n modifiedBy,\n };\n\n await this.enforcer.removeGroupingPolicies(\n roleMembers,\n metadata,\n false,\n );\n\n response.locals.meta = {\n ...metadata,\n members: roleMembers.map(gp => gp[0]),\n }; // auditor\n\n response.status(204).end();\n },\n );\n\n router.get(\n '/roles/conditions',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n const matchedRoleName = roleMetadata.flatMap(role => {\n return role.roleEntityRef;\n });\n\n const conditions = await this.conditionalStorage.filterConditions(\n this.getFirstQuery(request.query.roleEntityRef),\n this.getFirstQuery(request.query.pluginId),\n this.getFirstQuery(request.query.resourceType),\n this.getActionQueries(request.query.actions),\n );\n\n const body: RoleConditionalPolicyDecision<PermissionAction>[] =\n conditions\n .map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(\n pm => pm.action,\n ),\n };\n })\n .filter(condition => {\n return matchedRoleName.includes(condition.roleEntityRef);\n });\n\n response.json(body);\n },\n );\n\n router.post(\n '/roles/conditions',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToCreate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n auth,\n );\n\n const id =\n await this.conditionalStorage.createCondition(conditionToCreate);\n\n const body = { id: id };\n\n response.locals.meta = { condition: roleConditionPolicy }; // auditor\n\n response.status(201).json(body);\n },\n );\n\n router.get(\n '/roles/conditions/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError();\n }\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n const matchedRoleName = roleMetadata.flatMap(role => {\n return role.roleEntityRef;\n });\n\n const body: RoleConditionalPolicyDecision<PermissionAction> | [] =\n matchedRoleName.includes(condition.roleEntityRef)\n ? {\n ...condition,\n permissionMapping: condition.permissionMapping.map(\n pm => pm.action,\n ),\n }\n : [];\n\n response.json(body);\n },\n );\n\n router.delete(\n '/roles/conditions/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityDeletePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError(`Condition with id ${id} was not found`);\n }\n const conditionToDelete: RoleConditionalPolicyDecision<PermissionAction> =\n {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n\n const roleMetadata = await this.roleMetadata.findRoleMetadata(\n conditionToDelete.roleEntityRef,\n );\n\n if (!matches(roleMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n await this.conditionalStorage.deleteCondition(id);\n response.locals.meta = { condition: conditionToDelete }; // auditor\n\n response.status(204).end();\n },\n );\n\n router.put(\n '/roles/conditions/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityUpdatePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n\n if (!condition) {\n throw new NotFoundError(`Condition with id ${id} was not found`);\n }\n\n const roleMetadata = await this.roleMetadata.findRoleMetadata(\n condition.roleEntityRef,\n );\n\n if (!matches(roleMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToUpdate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n auth,\n );\n\n await this.conditionalStorage.updateCondition(id, conditionToUpdate);\n\n response.locals.meta = { condition: roleConditionPolicy }; // auditor\n\n response.status(200).end();\n },\n );\n\n router.post(\n '/refresh/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n if (!this.rbacProviders) {\n throw new NotFoundError(`No RBAC providers were found`);\n }\n\n const idProvider = this.rbacProviders.find(provider => {\n const id = provider.getProviderName();\n return id === request.params.id;\n });\n\n if (!idProvider) {\n throw new NotFoundError(\n `The RBAC provider ${request.params.id} was not found`,\n );\n }\n\n await idProvider.refresh();\n response.status(200).end();\n },\n );\n\n registerPermissionDefinitionRoutes(\n router,\n this.pluginPermMetaData,\n this.pluginIdProvider,\n this.extraPluginsIdStorage,\n this.options,\n );\n\n router.use(setAuditorError());\n\n return router;\n }\n\n getEntityReference(request: Request, role?: boolean): string {\n const kind = request.params.kind;\n const namespace = request.params.namespace;\n const name = request.params.name;\n const entityRef = `${kind}:${namespace}/${name}`;\n\n const err = validateEntityReference(entityRef, role);\n if (err) {\n throw new InputError(err.message);\n }\n\n return entityRef;\n }\n\n async transformPolicyArray(\n ...policies: string[][]\n ): Promise<RoleBasedPolicy[]> {\n const roleToSourceMap = await buildRoleSourceMap(\n policies,\n this.roleMetadata,\n );\n\n const roleBasedPolices: RoleBasedPolicy[] = [];\n for (const p of policies) {\n const [entityReference, permission, policy, effect] = p;\n roleBasedPolices.push({\n entityReference,\n permission,\n policy,\n effect,\n metadata: { source: roleToSourceMap.get(entityReference)! },\n });\n }\n\n return roleBasedPolices;\n }\n\n async transformRoleArray(\n filter?: RBACFilters,\n ...roles: string[][]\n ): Promise<Role[]> {\n const combinedRoles: { [key: string]: string[] } = {};\n\n roles.forEach(([value, role]) => {\n if (combinedRoles.hasOwnProperty(role)) {\n combinedRoles[role].push(value);\n } else {\n combinedRoles[role] = [value];\n }\n });\n\n const result: Role[] = await Promise.all(\n Object.entries(combinedRoles).flatMap(async ([role, value]) => {\n const metadataDao = await this.roleMetadata.findRoleMetadata(role);\n const metadata = metadataDao ? daoToMetadata(metadataDao) : undefined;\n return Promise.resolve({\n memberReferences: value,\n name: role,\n metadata,\n });\n }),\n );\n\n const filteredResult = result.filter(role => {\n return role.metadata && matches(role.metadata, filter);\n });\n\n return filteredResult;\n }\n\n transformPolicyToArray(policy: RoleBasedPolicy): string[] {\n return [\n policy.entityReference!,\n policy.permission!,\n policy.policy!,\n policy.effect!,\n ];\n }\n\n transformRoleToArray(role: Role): string[][] {\n const roles: string[][] = [];\n for (const entity of role.memberReferences) {\n roles.push([entity, role.name]);\n }\n return roles;\n }\n\n transformMemberReferencesToLowercase(role: Role) {\n role.memberReferences = role.memberReferences.map(member =>\n member.toLocaleLowerCase('en-US'),\n );\n }\n\n getActionQueries(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): PermissionAction[] | undefined {\n if (!queryValue) {\n return undefined;\n }\n if (Array.isArray(queryValue)) {\n const permissionNames: PermissionAction[] = [];\n for (const permissionQuery of queryValue) {\n if (\n typeof permissionQuery === 'string' &&\n isPermissionAction(permissionQuery)\n ) {\n permissionNames.push(permissionQuery);\n } else {\n throw new InputError(\n `Invalid permission action query value: ${permissionQuery}. Permission name should be string.`,\n );\n }\n }\n return permissionNames;\n }\n\n if (typeof queryValue === 'string' && isPermissionAction(queryValue)) {\n return [queryValue];\n }\n throw new InputError(\n `Invalid permission action query value: ${queryValue}. Permission name should be string.`,\n );\n }\n\n getFirstQuery(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): string {\n if (!queryValue) {\n return '';\n }\n if (Array.isArray(queryValue)) {\n if (typeof queryValue[0] === 'string') {\n return queryValue[0].toString();\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n if (typeof queryValue === 'string') {\n return queryValue;\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n isPolicyFilterEnabled(request: Request): boolean {\n return (\n !!request.query.entityRef ||\n !!request.query.permission ||\n !!request.query.policy ||\n !!request.query.effect\n );\n }\n\n async processPolicies(\n policyArray: RoleBasedPolicy[],\n isOld?: boolean,\n errorMessage?: string,\n filter?: RBACFilters,\n ): Promise<string[][]> {\n const policies: string[][] = [];\n const uniqueItems = new Set<string>();\n for (const policy of policyArray) {\n let err = validatePolicy(policy);\n if (err) {\n throw new InputError(\n `Invalid ${errorMessage ?? 'policy'} definition. Cause: ${\n err.message\n }`,\n ); // 400\n }\n\n const metadata = await this.roleMetadata.findRoleMetadata(\n policy.entityReference!,\n );\n\n if (!matches(metadata, filter)) {\n throw new NotAllowedError(); // 403\n }\n\n let action = errorMessage ? 'edit' : 'delete';\n action = isOld ? action : 'add';\n\n err = await validateSource('rest', metadata);\n if (err) {\n throw new NotAllowedError(\n `Unable to ${action} policy ${policy.entityReference},${policy.permission},${policy.policy},${policy.effect}: ${err.message}`,\n );\n }\n\n const transformedPolicy = this.transformPolicyToArray(policy);\n if (isOld && !(await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new NotFoundError(\n `Policy '${policyToString(transformedPolicy)}' not found`,\n ); // 404\n }\n\n if (!isOld && (await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new ConflictError(\n `Policy '${policyToString(\n transformedPolicy,\n )}' has been already stored`,\n ); // 409\n }\n\n // We want to ensure that there are not duplicate permission policies\n const rowString = JSON.stringify(transformedPolicy);\n if (uniqueItems.has(rowString)) {\n throw new ConflictError(\n `Duplicate polices found; ${policy.entityReference}, ${policy.permission}, ${policy.policy}, ${policy.effect} is a duplicate`,\n );\n } else {\n uniqueItems.add(rowString);\n policies.push(transformedPolicy);\n }\n }\n return policies;\n }\n\n nameSort(nameA: string, nameB: string): number {\n if (nameA.toLocaleUpperCase('en-US') < nameB.toLocaleUpperCase('en-US')) {\n return -1;\n }\n if (nameA.toLocaleUpperCase('en-US') > nameB.toLocaleUpperCase('en-US')) {\n return 1;\n }\n return 0;\n }\n}\n"],"names":["policyEntityReadPermission","NotAllowedError","AuthorizeResult","createRouter","conditionTransformerFunc","logAuditorEvent","NotFoundError","policyEntityDeletePermission","isEmpty","InputError","policyEntityCreatePermission","policyEntityUpdatePermission","isEqual","validateRole","validateSource","ConflictError","matches","deepSortedEqual","validateRoleCondition","processConditionMapping","registerPermissionDefinitionRoutes","setAuditorError","validateEntityReference","buildRoleSourceMap","daoToMetadata","isPermissionAction","validatePolicy","policyToString"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"policies-rest-api.cjs.js","sources":["../../src/service/policies-rest-api.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type {\n AuthService,\n BackstageCredentials,\n BackstageServicePrincipal,\n BackstageUserPrincipal,\n HttpAuthService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\nimport {\n AuthorizeResult,\n BasicPermission,\n PolicyDecision,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\n\nimport express from 'express';\nimport type { Request } from 'express-serve-static-core';\nimport { isEmpty, isEqual } from 'lodash';\nimport type { ParsedQs } from 'qs';\n\nimport {\n policyEntityCreatePermission,\n policyEntityDeletePermission,\n policyEntityReadPermission,\n policyEntityUpdatePermission,\n type PermissionAction,\n type Role,\n type RoleBasedPolicy,\n type RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\nimport type { RBACProvider } from '@backstage-community/plugin-rbac-node';\n\nimport { setAuditorError, logAuditorEvent } from '../auditor/rest-interceptor';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport {\n daoToMetadata,\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport {\n buildRoleSourceMap,\n deepSortedEqual,\n isPermissionAction,\n policyToString,\n processConditionMapping,\n matches,\n} from '../helper';\nimport { validateRoleCondition } from '../validation/condition-validation';\nimport {\n validateEntityReference,\n validatePolicy,\n validateRole,\n validateSource,\n} from '../validation/policies-validation';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { RBACRouterOptions } from './policy-builder';\nimport { conditionTransformerFunc, RBACFilters } from '../permissions';\nimport { registerPermissionDefinitionRoutes } from './permission-definition-routes';\nimport { PermissionDependentPluginStore } from '../database/extra-permission-enabled-plugins-storage';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\nimport { createRouter } from './router';\n\nexport async function authorizeConditional(\n request: Request,\n permission: ResourcePermission<'policy-entity'> | BasicPermission,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n permissions: PermissionsService;\n },\n): Promise<{\n decision: PolicyDecision;\n credentials: BackstageCredentials<\n BackstageUserPrincipal | BackstageServicePrincipal\n >;\n}> {\n const { auth, httpAuth, permissions } = deps;\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user', 'service'],\n });\n\n // allow service to service communication, but only with read permission\n if (\n auth.isPrincipal(credentials, 'service') &&\n permission !== policyEntityReadPermission\n ) {\n throw new NotAllowedError(\n `Only credential principal with type 'user' permitted to modify permissions`,\n );\n }\n\n let decision: PolicyDecision;\n if (permission.type === 'resource') {\n decision = (\n await permissions.authorizeConditional([{ permission }], {\n credentials,\n })\n )[0];\n } else {\n decision = (\n await permissions.authorize([{ permission }], {\n credentials,\n })\n )[0];\n }\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n return { decision, credentials };\n}\n\nexport class PoliciesServer {\n constructor(\n private readonly options: RBACRouterOptions,\n private readonly enforcer: EnforcerDelegate,\n private readonly conditionalStorage: ConditionalStorage,\n private readonly pluginPermMetaData: PluginPermissionMetadataCollector,\n private readonly roleMetadata: RoleMetadataStorage,\n private readonly extraPluginsIdStorage: PermissionDependentPluginStore,\n private readonly pluginIdProvider: ExtendablePluginIdProvider,\n private readonly rbacProviders?: RBACProvider[],\n ) {}\n\n async serve(): Promise<express.Router> {\n const router = await createRouter(this.options);\n\n const { logger, auditor, auth, permissionsRegistry } = this.options;\n\n const isPluginEnabled =\n this.options.config.getOptionalBoolean('permission.enabled');\n if (!isPluginEnabled) {\n return router;\n }\n\n const transformConditions = conditionTransformerFunc(permissionsRegistry);\n\n router.get('/', async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n response.send({ status: 'Authorized' });\n });\n\n // Policy CRUD\n\n router.get(\n '/policies',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n let policies: string[][] = [];\n if (this.isPolicyFilterEnabled(request)) {\n const entityRef = this.getFirstQuery(request.query.entityRef);\n const permission = this.getFirstQuery(request.query.permission);\n const policy = this.getFirstQuery(request.query.policy);\n const effect = this.getFirstQuery(request.query.effect);\n\n const matchedRoleName = roleMetadata.flatMap(\n role => role.roleEntityRef,\n );\n\n const filter: string[] = [entityRef, permission, policy, effect];\n policies = matchedRoleName.includes(entityRef)\n ? await this.enforcer.getFilteredPolicy(0, ...filter)\n : [];\n } else {\n for (const role of roleMetadata) {\n policies.push(\n ...(await this.enforcer.getFilteredPolicy(\n 0,\n ...[role.roleEntityRef],\n )),\n );\n }\n }\n\n const body = await this.transformPolicyArray(...policies);\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n body.map(policy => {\n if (\n policy.permission === 'policy-entity' &&\n policy.policy === 'create'\n ) {\n policy.permission = 'policy.entity.create';\n logger.warn(\n `Permission policy with resource type 'policy-entity' and action 'create' has been removed. Please consider updating policy ${[policy.entityReference, 'policy-entity', policy.policy, policy.effect]} to use 'policy.entity.create' instead of 'policy-entity' from source ${policy.metadata?.source}`,\n );\n }\n });\n\n response.json(body);\n },\n );\n\n router.get(\n '/policies/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n const matchedRoleName = roleMetadata.flatMap(role => {\n return role.roleEntityRef;\n });\n\n const entityRef = this.getEntityReference(request);\n\n const policy = matchedRoleName.includes(entityRef)\n ? await this.enforcer.getFilteredPolicy(0, entityRef)\n : [];\n if (policy.length !== 0) {\n const body = await this.transformPolicyArray(...policy);\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n body.map(bodyPolicy => {\n if (\n bodyPolicy.permission === 'policy-entity' &&\n bodyPolicy.policy === 'create'\n ) {\n bodyPolicy.permission = 'policy.entity.create';\n logger.warn(\n `Permission policy with resource type 'policy-entity' and action 'create' has been removed. Please consider updating policy ${[bodyPolicy.entityReference, 'policy-entity', bodyPolicy.policy, bodyPolicy.effect]} to use 'policy.entity.create' instead of 'policy-entity' from source ${bodyPolicy.metadata?.source}`,\n );\n }\n });\n\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n },\n );\n\n router.delete(\n '/policies/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityDeletePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const entityRef = this.getEntityReference(request);\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n policyRaw.forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedPolicies = await this.processPolicies(\n policyRaw,\n true,\n undefined,\n conditionsFilter,\n );\n\n await this.enforcer.removePolicies(processedPolicies);\n\n response.locals.meta = { policies: processedPolicies }; // auditor\n\n response.status(204).end();\n },\n );\n\n router.post(\n '/policies',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n const processedPolicies = await this.processPolicies(\n policyRaw,\n false,\n undefined,\n );\n\n const entityRef = processedPolicies[0][0];\n const roleMetadata =\n await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.addPolicies(processedPolicies);\n\n response.locals.meta = { policies: processedPolicies }; // auditor\n\n response.status(201).end();\n },\n );\n\n router.put(\n '/policies/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityUpdatePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const entityRef = this.getEntityReference(request);\n\n const oldPolicyRaw: RoleBasedPolicy[] = request.body.oldPolicy;\n if (isEmpty(oldPolicyRaw)) {\n throw new InputError(`'oldPolicy' object must be present`); // 400\n }\n const newPolicyRaw: RoleBasedPolicy[] = request.body.newPolicy;\n if (isEmpty(newPolicyRaw)) {\n throw new InputError(`'newPolicy' object must be present`); // 400\n }\n\n [...oldPolicyRaw, ...newPolicyRaw].forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedOldPolicy = await this.processPolicies(\n oldPolicyRaw,\n true,\n 'old policy',\n conditionsFilter,\n );\n\n oldPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n newPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n if (\n isEqual(oldPolicyRaw, newPolicyRaw) &&\n !oldPolicyRaw.some(isEmpty)\n ) {\n response.status(204).end();\n } else if (oldPolicyRaw.length > newPolicyRaw.length) {\n throw new InputError(\n `'oldPolicy' object has more permission policies compared to 'newPolicy' object`,\n );\n }\n\n const processedNewPolicy = await this.processPolicies(\n newPolicyRaw,\n false,\n 'new policy',\n conditionsFilter,\n );\n\n const roleMetadata =\n await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.updatePolicies(\n processedOldPolicy,\n processedNewPolicy,\n );\n\n response.locals.meta = { policies: processedNewPolicy }; // auditor\n\n response.status(200).end();\n },\n );\n\n // Role CRUD\n\n router.get(\n '/roles',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roles = await this.enforcer.getGroupingPolicy();\n const body = await this.transformRoleArray(conditionsFilter, ...roles);\n\n response.json(body);\n },\n );\n\n router.get(\n '/roles/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n const role = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n\n const body = await this.transformRoleArray(conditionsFilter, ...role);\n if (body.length !== 0) {\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n },\n );\n\n router.post(\n '/roles',\n logAuditorEvent(auditor),\n async (request, response) => {\n const uniqueItems = new Set<string>();\n const { credentials } = await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n const roleRaw: Role = request.body;\n let err = validateRole(roleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid role definition. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(roleRaw);\n\n const rMetadata = await this.roleMetadata.findRoleMetadata(\n roleRaw.name,\n );\n\n err = await validateSource('rest', rMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to add role: ${err.message}`);\n }\n\n const roles = this.transformRoleToArray(roleRaw);\n\n for (const role of roles) {\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n throw new ConflictError(); // 409\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n const modifiedBy = (\n credentials as BackstageCredentials<BackstageUserPrincipal>\n ).principal.userEntityRef;\n const metadata: RoleMetadataDao = {\n roleEntityRef: roleRaw.name,\n source: 'rest',\n description: roleRaw.metadata?.description ?? '',\n author: modifiedBy,\n modifiedBy,\n owner: roleRaw.metadata?.owner ?? modifiedBy,\n };\n\n await this.enforcer.addGroupingPolicies(roles, metadata);\n\n response.locals.meta = { ...metadata, members: roles.map(gp => gp[0]) }; // auditor\n\n response.status(201).end();\n },\n );\n\n router.put(\n '/roles/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n const uniqueItems = new Set<string>();\n let conditionsFilter: RBACFilters | undefined;\n const { decision, credentials } = await authorizeConditional(\n request,\n policyEntityUpdatePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n const oldRoleRaw: Role = request.body.oldRole;\n\n if (!oldRoleRaw) {\n throw new InputError(`'oldRole' object must be present`); // 400\n }\n const newRoleRaw: Role = request.body.newRole;\n if (!newRoleRaw) {\n throw new InputError(`'newRole' object must be present`); // 400\n }\n\n oldRoleRaw.name = roleEntityRef;\n let err = validateRole(oldRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid old role object. Cause: ${err.message}`,\n );\n }\n err = validateRole(newRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid new role object. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(oldRoleRaw);\n this.transformMemberReferencesToLowercase(newRoleRaw);\n\n const oldRole = this.transformRoleToArray(oldRoleRaw);\n const newRole = this.transformRoleToArray(newRoleRaw);\n // todo shell we allow newRole with an empty array?...\n\n const modifiedBy = (\n credentials as BackstageCredentials<BackstageUserPrincipal>\n ).principal.userEntityRef;\n const newMetadata: RoleMetadataDao = {\n ...newRoleRaw.metadata,\n source: newRoleRaw.metadata?.source ?? 'rest',\n roleEntityRef: newRoleRaw.name,\n modifiedBy,\n owner: newRoleRaw.metadata?.owner ?? '',\n };\n\n const oldMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n if (!oldMetadata) {\n throw new NotFoundError(\n `Unable to find metadata for ${roleEntityRef}`,\n );\n }\n\n err = await validateSource('rest', oldMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to edit role: ${err.message}`);\n }\n\n if (!matches(oldMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n if (\n isEqual(oldRole, newRole) &&\n deepSortedEqual(oldMetadata, newMetadata, [\n 'author',\n 'modifiedBy',\n 'createdAt',\n 'lastModified',\n 'owner',\n ])\n ) {\n // no content: old role and new role are equal and their metadata too\n response.status(204).end();\n return;\n }\n\n for (const role of newRole) {\n const hasRole = oldRole.some(element => {\n return isEqual(element, role);\n });\n // if the role is already part of old role and is a grouping policy we want to skip returning a conflict error\n // to allow for other roles to be checked and added\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n if (!hasRole) {\n throw new ConflictError(); // 409\n }\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n uniqueItems.clear();\n for (const role of oldRole) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(\n `Member reference: ${role[0]} was not found for role ${roleEntityRef}`,\n ); // 404\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n await this.enforcer.updateGroupingPolicies(\n oldRole,\n newRole,\n newMetadata,\n );\n\n let message = `Updated ${oldMetadata.roleEntityRef}.`;\n if (newMetadata.roleEntityRef !== oldMetadata.roleEntityRef) {\n message = `${message}. Role entity reference renamed to ${newMetadata.roleEntityRef}`;\n }\n response.locals.meta = {\n ...newMetadata,\n members: newRole.map(gp => gp[0]),\n }; // auditor\n\n response.status(200).end();\n },\n );\n\n router.delete(\n '/roles/:kind/:namespace/:name',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision, credentials } = await authorizeConditional(\n request,\n policyEntityDeletePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n const currentMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n\n if (!matches(currentMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n const err = await validateSource('rest', currentMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to delete role: ${err.message}`);\n }\n\n let roleMembers = [];\n if (request.query.memberReferences) {\n const memberReference = this.getFirstQuery(\n request.query.memberReferences!,\n ).toLocaleLowerCase('en-US');\n const gp = await this.enforcer.getFilteredGroupingPolicy(\n 0,\n memberReference,\n roleEntityRef,\n );\n if (gp.length > 0) {\n roleMembers.push(gp[0]);\n } else {\n throw new NotFoundError(\n `role member '${memberReference}' was not found`,\n ); // 404\n }\n } else {\n roleMembers = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n }\n\n for (const role of roleMembers) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(`role member '${role[0]}' was not found`);\n }\n }\n\n const modifiedBy = (\n credentials as BackstageCredentials<BackstageUserPrincipal>\n ).principal.userEntityRef;\n const metadata: RoleMetadataDao = {\n roleEntityRef,\n source: 'rest',\n modifiedBy,\n };\n\n await this.enforcer.removeGroupingPolicies(\n roleMembers,\n metadata,\n false,\n );\n\n response.locals.meta = {\n ...metadata,\n members: roleMembers.map(gp => gp[0]),\n }; // auditor\n\n response.status(204).end();\n },\n );\n\n router.get(\n '/roles/conditions',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n const matchedRoleName = roleMetadata.flatMap(role => {\n return role.roleEntityRef;\n });\n\n const conditions = await this.conditionalStorage.filterConditions(\n this.getFirstQuery(request.query.roleEntityRef),\n this.getFirstQuery(request.query.pluginId),\n this.getFirstQuery(request.query.resourceType),\n this.getActionQueries(request.query.actions),\n );\n\n const body: RoleConditionalPolicyDecision<PermissionAction>[] =\n conditions\n .map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(\n pm => pm.action,\n ),\n };\n })\n .filter(condition => {\n return matchedRoleName.includes(condition.roleEntityRef);\n });\n\n response.json(body);\n },\n );\n\n router.post(\n '/roles/conditions',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToCreate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n auth,\n );\n\n const id =\n await this.conditionalStorage.createCondition(conditionToCreate);\n\n const body = { id: id };\n\n response.locals.meta = { condition: roleConditionPolicy }; // auditor\n\n response.status(201).json(body);\n },\n );\n\n router.get(\n '/roles/conditions/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityReadPermission,\n this.options,\n );\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError();\n }\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const roleMetadata =\n await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);\n\n const matchedRoleName = roleMetadata.flatMap(role => {\n return role.roleEntityRef;\n });\n\n const body: RoleConditionalPolicyDecision<PermissionAction> | [] =\n matchedRoleName.includes(condition.roleEntityRef)\n ? {\n ...condition,\n permissionMapping: condition.permissionMapping.map(\n pm => pm.action,\n ),\n }\n : [];\n\n response.json(body);\n },\n );\n\n router.delete(\n '/roles/conditions/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityDeletePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError(`Condition with id ${id} was not found`);\n }\n const conditionToDelete: RoleConditionalPolicyDecision<PermissionAction> =\n {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n\n const roleMetadata = await this.roleMetadata.findRoleMetadata(\n conditionToDelete.roleEntityRef,\n );\n\n if (!matches(roleMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n await this.conditionalStorage.deleteCondition(id);\n response.locals.meta = { condition: conditionToDelete }; // auditor\n\n response.status(204).end();\n },\n );\n\n router.put(\n '/roles/conditions/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n let conditionsFilter: RBACFilters | undefined;\n const { decision } = await authorizeConditional(\n request,\n policyEntityUpdatePermission,\n this.options,\n );\n\n if (decision.result === AuthorizeResult.CONDITIONAL) {\n conditionsFilter = transformConditions(decision.conditions);\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n\n if (!condition) {\n throw new NotFoundError(`Condition with id ${id} was not found`);\n }\n\n const roleMetadata = await this.roleMetadata.findRoleMetadata(\n condition.roleEntityRef,\n );\n\n if (!matches(roleMetadata, conditionsFilter)) {\n throw new NotAllowedError(); // 403\n }\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToUpdate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n auth,\n );\n\n await this.conditionalStorage.updateCondition(id, conditionToUpdate);\n\n response.locals.meta = { condition: roleConditionPolicy }; // auditor\n\n response.status(200).end();\n },\n );\n\n router.post(\n '/refresh/:id',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(\n request,\n policyEntityCreatePermission,\n this.options,\n );\n\n if (!this.rbacProviders) {\n throw new NotFoundError(`No RBAC providers were found`);\n }\n\n const idProvider = this.rbacProviders.find(provider => {\n const id = provider.getProviderName();\n return id === request.params.id;\n });\n\n if (!idProvider) {\n throw new NotFoundError(\n `The RBAC provider ${request.params.id} was not found`,\n );\n }\n\n await idProvider.refresh();\n response.status(200).end();\n },\n );\n\n registerPermissionDefinitionRoutes(\n router,\n this.pluginPermMetaData,\n this.pluginIdProvider,\n this.extraPluginsIdStorage,\n this.options,\n );\n\n router.use(setAuditorError());\n\n return router;\n }\n\n getEntityReference(request: Request, role?: boolean): string {\n const kind = request.params.kind;\n const namespace = request.params.namespace;\n const name = request.params.name;\n const entityRef = `${kind}:${namespace}/${name}`;\n\n const err = validateEntityReference(entityRef, role);\n if (err) {\n throw new InputError(err.message);\n }\n\n return entityRef;\n }\n\n async transformPolicyArray(\n ...policies: string[][]\n ): Promise<RoleBasedPolicy[]> {\n const roleToSourceMap = await buildRoleSourceMap(\n policies,\n this.roleMetadata,\n );\n\n const roleBasedPolices: RoleBasedPolicy[] = [];\n for (const p of policies) {\n const [entityReference, permission, policy, effect] = p;\n roleBasedPolices.push({\n entityReference,\n permission,\n policy,\n effect,\n metadata: { source: roleToSourceMap.get(entityReference)! },\n });\n }\n\n return roleBasedPolices;\n }\n\n async transformRoleArray(\n filter?: RBACFilters,\n ...roles: string[][]\n ): Promise<Role[]> {\n const combinedRoles: { [key: string]: string[] } = {};\n\n roles.forEach(([value, role]) => {\n if (combinedRoles.hasOwnProperty(role)) {\n combinedRoles[role].push(value);\n } else {\n combinedRoles[role] = [value];\n }\n });\n\n const result: Role[] = await Promise.all(\n Object.entries(combinedRoles).flatMap(async ([role, value]) => {\n const metadataDao = await this.roleMetadata.findRoleMetadata(role);\n const metadata = metadataDao ? daoToMetadata(metadataDao) : undefined;\n return Promise.resolve({\n memberReferences: value,\n name: role,\n metadata,\n });\n }),\n );\n\n const filteredResult = result.filter(role => {\n return role.metadata && matches(role.metadata, filter);\n });\n\n return filteredResult;\n }\n\n transformPolicyToArray(policy: RoleBasedPolicy): string[] {\n return [\n policy.entityReference!,\n policy.permission!,\n policy.policy!,\n policy.effect!,\n ];\n }\n\n transformRoleToArray(role: Role): string[][] {\n const roles: string[][] = [];\n for (const entity of role.memberReferences) {\n roles.push([entity, role.name]);\n }\n return roles;\n }\n\n transformMemberReferencesToLowercase(role: Role) {\n role.memberReferences = role.memberReferences.map(member =>\n member.toLocaleLowerCase('en-US'),\n );\n }\n\n getActionQueries(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): PermissionAction[] | undefined {\n if (!queryValue) {\n return undefined;\n }\n if (Array.isArray(queryValue)) {\n const permissionNames: PermissionAction[] = [];\n for (const permissionQuery of queryValue) {\n if (\n typeof permissionQuery === 'string' &&\n isPermissionAction(permissionQuery)\n ) {\n permissionNames.push(permissionQuery);\n } else {\n throw new InputError(\n `Invalid permission action query value: ${permissionQuery}. Permission name should be string.`,\n );\n }\n }\n return permissionNames;\n }\n\n if (typeof queryValue === 'string' && isPermissionAction(queryValue)) {\n return [queryValue];\n }\n throw new InputError(\n `Invalid permission action query value: ${queryValue}. Permission name should be string.`,\n );\n }\n\n getFirstQuery(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): string {\n if (!queryValue) {\n return '';\n }\n if (Array.isArray(queryValue)) {\n if (typeof queryValue[0] === 'string') {\n return queryValue[0].toString();\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n if (typeof queryValue === 'string') {\n return queryValue;\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n isPolicyFilterEnabled(request: Request): boolean {\n return (\n !!request.query.entityRef ||\n !!request.query.permission ||\n !!request.query.policy ||\n !!request.query.effect\n );\n }\n\n async processPolicies(\n policyArray: RoleBasedPolicy[],\n isOld?: boolean,\n errorMessage?: string,\n filter?: RBACFilters,\n ): Promise<string[][]> {\n const policies: string[][] = [];\n const uniqueItems = new Set<string>();\n for (const policy of policyArray) {\n let err = validatePolicy(policy);\n if (err) {\n throw new InputError(\n `Invalid ${errorMessage ?? 'policy'} definition. Cause: ${\n err.message\n }`,\n ); // 400\n }\n\n const metadata = await this.roleMetadata.findRoleMetadata(\n policy.entityReference!,\n );\n\n if (!matches(metadata, filter)) {\n throw new NotAllowedError(); // 403\n }\n\n let action = errorMessage ? 'edit' : 'delete';\n action = isOld ? action : 'add';\n\n err = await validateSource('rest', metadata);\n if (err) {\n throw new NotAllowedError(\n `Unable to ${action} policy ${policy.entityReference},${policy.permission},${policy.policy},${policy.effect}: ${err.message}`,\n );\n }\n\n const transformedPolicy = this.transformPolicyToArray(policy);\n if (isOld && !(await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new NotFoundError(\n `Policy '${policyToString(transformedPolicy)}' not found`,\n ); // 404\n }\n\n if (!isOld && (await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new ConflictError(\n `Policy '${policyToString(\n transformedPolicy,\n )}' has been already stored`,\n ); // 409\n }\n\n // We want to ensure that there are not duplicate permission policies\n const rowString = JSON.stringify(transformedPolicy);\n if (uniqueItems.has(rowString)) {\n throw new ConflictError(\n `Duplicate polices found; ${policy.entityReference}, ${policy.permission}, ${policy.policy}, ${policy.effect} is a duplicate`,\n );\n } else {\n uniqueItems.add(rowString);\n policies.push(transformedPolicy);\n }\n }\n return policies;\n }\n\n nameSort(nameA: string, nameB: string): number {\n if (nameA.toLocaleUpperCase('en-US') < nameB.toLocaleUpperCase('en-US')) {\n return -1;\n }\n if (nameA.toLocaleUpperCase('en-US') > nameB.toLocaleUpperCase('en-US')) {\n return 1;\n }\n return 0;\n }\n}\n"],"names":["policyEntityReadPermission","NotAllowedError","AuthorizeResult","router","createRouter","conditionTransformerFunc","logAuditorEvent","NotFoundError","policyEntityDeletePermission","isEmpty","InputError","policyEntityCreatePermission","policyEntityUpdatePermission","isEqual","validateRole","validateSource","ConflictError","matches","deepSortedEqual","validateRoleCondition","processConditionMapping","registerPermissionDefinitionRoutes","setAuditorError","validateEntityReference","buildRoleSourceMap","daoToMetadata","isPermissionAction","validatePolicy","policyToString"],"mappings":"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"}
|
|
@@ -24,7 +24,6 @@ var extendableIdProvider = require('./extendable-id-provider.cjs.js');
|
|
|
24
24
|
|
|
25
25
|
class PolicyBuilder {
|
|
26
26
|
static async build(env, pluginIdProvider = { getPluginIds: () => [] }, rbacProviders) {
|
|
27
|
-
let policy;
|
|
28
27
|
const databaseManager = database.DatabaseManager.fromConfig(env.config).forPlugin(
|
|
29
28
|
"permission",
|
|
30
29
|
{ logger: env.logger, lifecycle: env.lifecycle }
|
|
@@ -99,31 +98,30 @@ class PolicyBuilder {
|
|
|
99
98
|
const isPluginEnabled = env.config.getOptionalBoolean("permission.enabled");
|
|
100
99
|
if (isPluginEnabled) {
|
|
101
100
|
env.logger.info("RBAC backend plugin was enabled");
|
|
102
|
-
policy
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
env.policy.setPolicy(
|
|
102
|
+
await permissionPolicy.RBACPermissionPolicy.build(
|
|
103
|
+
env.logger,
|
|
104
|
+
env.auditor,
|
|
105
|
+
env.config,
|
|
106
|
+
conditionStorage,
|
|
107
|
+
enforcerDelegate$1,
|
|
108
|
+
roleMetadataStorage,
|
|
109
|
+
databaseClient,
|
|
110
|
+
pluginPermMetaData,
|
|
111
|
+
env.auth
|
|
112
|
+
)
|
|
112
113
|
);
|
|
113
114
|
} else {
|
|
114
115
|
env.logger.warn(
|
|
115
116
|
"RBAC backend plugin was disabled by application config permission.enabled: false"
|
|
116
117
|
);
|
|
117
|
-
policy
|
|
118
|
+
env.policy.setPolicy(new allowAllPolicy.AllowAllPolicy());
|
|
118
119
|
}
|
|
119
120
|
const options = {
|
|
120
121
|
config: env.config,
|
|
121
122
|
logger: env.logger,
|
|
122
|
-
discovery: env.discovery,
|
|
123
|
-
policy,
|
|
124
123
|
auth: env.auth,
|
|
125
124
|
httpAuth: env.httpAuth,
|
|
126
|
-
userInfo: env.userInfo,
|
|
127
125
|
permissions: env.permissions,
|
|
128
126
|
permissionsRegistry: env.permissionsRegistry,
|
|
129
127
|
auditor: env.auditor
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy-builder.cjs.js","sources":["../../src/service/policy-builder.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DatabaseManager } from '@backstage/backend-defaults/database';\nimport type {\n AuditorService,\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\nimport type { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { PermissionPolicy } from '@backstage/plugin-permission-node';\n\nimport { newEnforcer, newModelFromString } from 'casbin';\nimport type { Router } from 'express';\n\nimport type {\n PluginIdProvider,\n RBACProvider,\n} from '@backstage-community/plugin-rbac-node';\n\nimport { CasbinDBAdapterFactory } from '../database/casbin-adapter-factory';\nimport { DataBaseConditionalStorage } from '../database/conditional-storage';\nimport { migrate } from '../database/migration';\nimport { DataBaseRoleMetadataStorage } from '../database/role-metadata';\nimport { AllowAllPolicy } from '../policies/allow-all-policy';\nimport { RBACPermissionPolicy } from '../policies/permission-policy';\nimport { connectRBACProviders } from '../providers/connect-providers';\nimport { BackstageRoleManager } from '../role-manager/role-manager';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { MODEL } from './permission-model';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { PoliciesServer } from './policies-rest-api';\nimport { policyEntityPermissions } from '@backstage-community/plugin-rbac-common';\nimport { rules } from '../permissions';\nimport { permissionMetadataResourceRef } from '../permissions/resource';\nimport { PermissionDependentPluginDatabaseStore } from '../database/extra-permission-enabled-plugins-storage';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\n\n/**\n * @public\n */\nexport type EnvOptions = {\n config: Config;\n logger: LoggerService;\n discovery: DiscoveryService;\n permissions: PermissionEvaluator;\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n userInfo: UserInfoService;\n lifecycle: LifecycleService;\n permissionsRegistry: PermissionsRegistryService;\n};\n\n/**\n * @public\n */\nexport type RBACRouterOptions = {\n config: Config;\n logger: LoggerService;\n discovery: DiscoveryService;\n policy: PermissionPolicy;\n auth: AuthService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n auditor: AuditorService;\n};\n\n/**\n * @public\n */\nexport class PolicyBuilder {\n public static async build(\n env: EnvOptions,\n pluginIdProvider: PluginIdProvider = { getPluginIds: () => [] },\n rbacProviders?: Array<RBACProvider>,\n ): Promise<Router> {\n let policy: PermissionPolicy;\n\n const databaseManager = DatabaseManager.fromConfig(env.config).forPlugin(\n 'permission',\n { logger: env.logger, lifecycle: env.lifecycle },\n );\n\n const databaseClient = await databaseManager.getClient();\n\n const adapter = await new CasbinDBAdapterFactory(\n env.config,\n databaseClient,\n ).createAdapter();\n\n const enf = await newEnforcer(newModelFromString(MODEL), adapter);\n await enf.loadPolicy();\n enf.enableAutoSave(true);\n\n const catalogClient = new CatalogClient({ discoveryApi: env.discovery });\n const catalogDBClient = await DatabaseManager.fromConfig(env.config)\n .forPlugin('catalog', { logger: env.logger, lifecycle: env.lifecycle })\n .getClient();\n\n const rm = new BackstageRoleManager(\n catalogClient,\n env.logger,\n catalogDBClient,\n databaseClient,\n env.config,\n env.auth,\n );\n enf.setRoleManager(rm);\n enf.enableAutoBuildRoleLinks(false);\n await enf.buildRoleLinks();\n\n await migrate(databaseManager);\n\n const conditionStorage = new DataBaseConditionalStorage(databaseClient);\n\n const roleMetadataStorage = new DataBaseRoleMetadataStorage(databaseClient);\n const enforcerDelegate = new EnforcerDelegate(\n enf,\n env.auditor,\n conditionStorage,\n roleMetadataStorage,\n databaseClient,\n );\n\n env.permissionsRegistry.addResourceType({\n resourceRef: permissionMetadataResourceRef,\n getResources: resourceRefs =>\n Promise.all(\n resourceRefs.map(ref => {\n return roleMetadataStorage.findRoleMetadata(ref);\n }),\n ),\n permissions: policyEntityPermissions,\n rules: Object.values(rules),\n });\n\n if (rbacProviders) {\n await connectRBACProviders(\n rbacProviders,\n enforcerDelegate,\n roleMetadataStorage,\n env.logger,\n env.auditor,\n );\n }\n\n const extraPluginsIdStorage = new PermissionDependentPluginDatabaseStore(\n databaseClient,\n );\n const extendablePluginIdProvider = new ExtendablePluginIdProvider(\n extraPluginsIdStorage,\n pluginIdProvider,\n env.config,\n );\n await extendablePluginIdProvider.handleConflictedPluginIds();\n const pluginPermMetaData = new PluginPermissionMetadataCollector({\n deps: {\n discovery: env.discovery,\n pluginIdProvider: extendablePluginIdProvider,\n logger: env.logger,\n config: env.config,\n },\n });\n\n const isPluginEnabled = env.config.getOptionalBoolean('permission.enabled');\n if (isPluginEnabled) {\n env.logger.info('RBAC backend plugin was enabled');\n\n policy = await RBACPermissionPolicy.build(\n env.logger,\n env.auditor,\n env.config,\n conditionStorage,\n enforcerDelegate,\n roleMetadataStorage,\n databaseClient,\n pluginPermMetaData,\n env.auth,\n );\n } else {\n env.logger.warn(\n 'RBAC backend plugin was disabled by application config permission.enabled: false',\n );\n\n policy = new AllowAllPolicy();\n }\n\n const options: RBACRouterOptions = {\n config: env.config,\n logger: env.logger,\n discovery: env.discovery,\n policy,\n auth: env.auth,\n httpAuth: env.httpAuth,\n userInfo: env.userInfo,\n permissions: env.permissions,\n permissionsRegistry: env.permissionsRegistry,\n auditor: env.auditor,\n };\n\n const server = new PoliciesServer(\n options,\n enforcerDelegate,\n conditionStorage,\n pluginPermMetaData,\n roleMetadataStorage,\n extraPluginsIdStorage,\n extendablePluginIdProvider,\n rbacProviders,\n );\n return server.serve();\n }\n}\n"],"names":["DatabaseManager","CasbinDBAdapterFactory","newEnforcer","newModelFromString","MODEL","catalogClient","CatalogClient","BackstageRoleManager","migrate","DataBaseConditionalStorage","DataBaseRoleMetadataStorage","enforcerDelegate","EnforcerDelegate","permissionMetadataResourceRef","policyEntityPermissions","rules","connectRBACProviders","PermissionDependentPluginDatabaseStore","ExtendablePluginIdProvider","PluginPermissionMetadataCollector","RBACPermissionPolicy","AllowAllPolicy","PoliciesServer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"policy-builder.cjs.js","sources":["../../src/service/policy-builder.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DatabaseManager } from '@backstage/backend-defaults/database';\nimport type {\n AuditorService,\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\nimport type { PermissionEvaluator } from '@backstage/plugin-permission-common';\n\nimport { newEnforcer, newModelFromString } from 'casbin';\nimport type { Router } from 'express';\n\nimport type {\n PluginIdProvider,\n RBACProvider,\n} from '@backstage-community/plugin-rbac-node';\n\nimport { CasbinDBAdapterFactory } from '../database/casbin-adapter-factory';\nimport { DataBaseConditionalStorage } from '../database/conditional-storage';\nimport { migrate } from '../database/migration';\nimport { DataBaseRoleMetadataStorage } from '../database/role-metadata';\nimport { AllowAllPolicy } from '../policies/allow-all-policy';\nimport { RBACPermissionPolicy } from '../policies/permission-policy';\nimport { connectRBACProviders } from '../providers/connect-providers';\nimport { BackstageRoleManager } from '../role-manager/role-manager';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { MODEL } from './permission-model';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { PoliciesServer } from './policies-rest-api';\nimport { policyEntityPermissions } from '@backstage-community/plugin-rbac-common';\nimport { rules } from '../permissions';\nimport { permissionMetadataResourceRef } from '../permissions/resource';\nimport { PermissionDependentPluginDatabaseStore } from '../database/extra-permission-enabled-plugins-storage';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\nimport { PolicyExtensionPoint } from '@backstage/plugin-permission-node/alpha';\n\n/**\n * @public\n */\nexport type EnvOptions = {\n config: Config;\n logger: LoggerService;\n discovery: DiscoveryService;\n permissions: PermissionEvaluator;\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n lifecycle: LifecycleService;\n permissionsRegistry: PermissionsRegistryService;\n policy: PolicyExtensionPoint;\n};\n\n/**\n * @public\n */\nexport type RBACRouterOptions = {\n config: Config;\n logger: LoggerService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n auditor: AuditorService;\n};\n\n/**\n * @public\n */\nexport class PolicyBuilder {\n public static async build(\n env: EnvOptions,\n pluginIdProvider: PluginIdProvider = { getPluginIds: () => [] },\n rbacProviders?: Array<RBACProvider>,\n ): Promise<Router> {\n const databaseManager = DatabaseManager.fromConfig(env.config).forPlugin(\n 'permission',\n { logger: env.logger, lifecycle: env.lifecycle },\n );\n\n const databaseClient = await databaseManager.getClient();\n\n const adapter = await new CasbinDBAdapterFactory(\n env.config,\n databaseClient,\n ).createAdapter();\n\n const enf = await newEnforcer(newModelFromString(MODEL), adapter);\n await enf.loadPolicy();\n enf.enableAutoSave(true);\n\n const catalogClient = new CatalogClient({ discoveryApi: env.discovery });\n const catalogDBClient = await DatabaseManager.fromConfig(env.config)\n .forPlugin('catalog', { logger: env.logger, lifecycle: env.lifecycle })\n .getClient();\n\n const rm = new BackstageRoleManager(\n catalogClient,\n env.logger,\n catalogDBClient,\n databaseClient,\n env.config,\n env.auth,\n );\n enf.setRoleManager(rm);\n enf.enableAutoBuildRoleLinks(false);\n await enf.buildRoleLinks();\n\n await migrate(databaseManager);\n\n const conditionStorage = new DataBaseConditionalStorage(databaseClient);\n\n const roleMetadataStorage = new DataBaseRoleMetadataStorage(databaseClient);\n const enforcerDelegate = new EnforcerDelegate(\n enf,\n env.auditor,\n conditionStorage,\n roleMetadataStorage,\n databaseClient,\n );\n\n env.permissionsRegistry.addResourceType({\n resourceRef: permissionMetadataResourceRef,\n getResources: resourceRefs =>\n Promise.all(\n resourceRefs.map(ref => {\n return roleMetadataStorage.findRoleMetadata(ref);\n }),\n ),\n permissions: policyEntityPermissions,\n rules: Object.values(rules),\n });\n\n if (rbacProviders) {\n await connectRBACProviders(\n rbacProviders,\n enforcerDelegate,\n roleMetadataStorage,\n env.logger,\n env.auditor,\n );\n }\n\n const extraPluginsIdStorage = new PermissionDependentPluginDatabaseStore(\n databaseClient,\n );\n const extendablePluginIdProvider = new ExtendablePluginIdProvider(\n extraPluginsIdStorage,\n pluginIdProvider,\n env.config,\n );\n await extendablePluginIdProvider.handleConflictedPluginIds();\n const pluginPermMetaData = new PluginPermissionMetadataCollector({\n deps: {\n discovery: env.discovery,\n pluginIdProvider: extendablePluginIdProvider,\n logger: env.logger,\n config: env.config,\n },\n });\n\n const isPluginEnabled = env.config.getOptionalBoolean('permission.enabled');\n if (isPluginEnabled) {\n env.logger.info('RBAC backend plugin was enabled');\n\n env.policy.setPolicy(\n await RBACPermissionPolicy.build(\n env.logger,\n env.auditor,\n env.config,\n conditionStorage,\n enforcerDelegate,\n roleMetadataStorage,\n databaseClient,\n pluginPermMetaData,\n env.auth,\n ),\n );\n } else {\n env.logger.warn(\n 'RBAC backend plugin was disabled by application config permission.enabled: false',\n );\n\n env.policy.setPolicy(new AllowAllPolicy());\n }\n\n const options: RBACRouterOptions = {\n config: env.config,\n logger: env.logger,\n auth: env.auth,\n httpAuth: env.httpAuth,\n permissions: env.permissions,\n permissionsRegistry: env.permissionsRegistry,\n auditor: env.auditor,\n };\n\n const server = new PoliciesServer(\n options,\n enforcerDelegate,\n conditionStorage,\n pluginPermMetaData,\n roleMetadataStorage,\n extraPluginsIdStorage,\n extendablePluginIdProvider,\n rbacProviders,\n );\n return server.serve();\n }\n}\n"],"names":["DatabaseManager","CasbinDBAdapterFactory","newEnforcer","newModelFromString","MODEL","catalogClient","CatalogClient","BackstageRoleManager","migrate","DataBaseConditionalStorage","DataBaseRoleMetadataStorage","enforcerDelegate","EnforcerDelegate","permissionMetadataResourceRef","policyEntityPermissions","rules","connectRBACProviders","PermissionDependentPluginDatabaseStore","ExtendablePluginIdProvider","PluginPermissionMetadataCollector","RBACPermissionPolicy","AllowAllPolicy","PoliciesServer"],"mappings":"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"}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
|
|
4
|
+
var Router = require('express-promise-router');
|
|
4
5
|
var express = require('express');
|
|
5
6
|
|
|
6
7
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
7
8
|
|
|
9
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
8
10
|
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
9
11
|
|
|
10
12
|
async function createRouter(options) {
|
|
11
13
|
const { logger, config } = options;
|
|
12
|
-
const router =
|
|
14
|
+
const router = Router__default.default();
|
|
13
15
|
router.use(express__default.default.json());
|
|
14
16
|
router.get("/health", (_, response) => {
|
|
15
17
|
logger.info("PONG!");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport express from 'express';\n\n/**\n * @public\n */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n}\n\n/**\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config } = options;\n\n const router =
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport Router from 'express-promise-router';\n\nimport express from 'express';\n\n/**\n * @public\n */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n}\n\n/**\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config } = options;\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["Router","express","MiddlewareFactory"],"mappings":";;;;;;;;;;;AAiCA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAM,MAAA,EAAE,MAAQ,EAAA,MAAA,EAAW,GAAA,OAAA;AAE3B,EAAA,MAAM,SAASA,uBAAO,EAAA;AACtB,EAAO,MAAA,CAAA,GAAA,CAAIC,wBAAQ,CAAA,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAI,CAAA,SAAA,EAAW,CAAC,CAAA,EAAG,QAAa,KAAA;AACrC,IAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,IAAA,QAAA,CAAS,IAAK,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,CAAA;AAAA,GAC/B,CAAA;AAED,EAAA,MAAM,aAAaC,gCAAkB,CAAA,MAAA,CAAO,EAAE,MAAA,EAAQ,QAAQ,CAAA;AAE9D,EAAO,MAAA,CAAA,GAAA,CAAI,UAAW,CAAA,KAAA,EAAO,CAAA;AAC7B,EAAO,OAAA,MAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-rbac-backend",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
},
|
|
12
12
|
"backstage": {
|
|
13
13
|
"role": "backend-plugin",
|
|
14
|
-
"supported-versions": "^1.28.4",
|
|
15
14
|
"pluginId": "rbac",
|
|
16
15
|
"pluginPackages": [
|
|
17
16
|
"@backstage-community/plugin-rbac",
|
|
@@ -37,22 +36,23 @@
|
|
|
37
36
|
"postpack": "backstage-cli package postpack"
|
|
38
37
|
},
|
|
39
38
|
"dependencies": {
|
|
40
|
-
"@backstage-community/plugin-rbac-common": "^1.
|
|
41
|
-
"@backstage-community/plugin-rbac-node": "^1.
|
|
42
|
-
"@backstage/backend-defaults": "^0.
|
|
43
|
-
"@backstage/backend-plugin-api": "^1.3.
|
|
44
|
-
"@backstage/catalog-client": "^1.
|
|
45
|
-
"@backstage/catalog-model": "^1.7.
|
|
39
|
+
"@backstage-community/plugin-rbac-common": "^1.18.0",
|
|
40
|
+
"@backstage-community/plugin-rbac-node": "^1.12.0",
|
|
41
|
+
"@backstage/backend-defaults": "^0.10.0",
|
|
42
|
+
"@backstage/backend-plugin-api": "^1.3.1",
|
|
43
|
+
"@backstage/catalog-client": "^1.10.0",
|
|
44
|
+
"@backstage/catalog-model": "^1.7.4",
|
|
46
45
|
"@backstage/errors": "^1.2.7",
|
|
47
|
-
"@backstage/plugin-auth-node": "^0.6.
|
|
48
|
-
"@backstage/plugin-permission-backend": "^0.
|
|
49
|
-
"@backstage/plugin-permission-common": "^0.
|
|
50
|
-
"@backstage/plugin-permission-node": "^0.
|
|
46
|
+
"@backstage/plugin-auth-node": "^0.6.3",
|
|
47
|
+
"@backstage/plugin-permission-backend": "^0.7.0",
|
|
48
|
+
"@backstage/plugin-permission-common": "^0.9.0",
|
|
49
|
+
"@backstage/plugin-permission-node": "^0.10.0",
|
|
51
50
|
"@dagrejs/graphlib": "^2.1.13",
|
|
52
51
|
"casbin": "^5.27.1",
|
|
53
52
|
"chokidar": "^3.6.0",
|
|
54
53
|
"csv-parse": "^5.5.5",
|
|
55
54
|
"express": "^4.18.2",
|
|
55
|
+
"express-promise-router": "^4.1.0",
|
|
56
56
|
"js-yaml": "^4.1.0",
|
|
57
57
|
"knex": "^3.0.0",
|
|
58
58
|
"lodash": "^4.17.21",
|
|
@@ -61,10 +61,11 @@
|
|
|
61
61
|
"zod-to-json-schema": "^3.24.5"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@backstage/backend-test-utils": "^1.
|
|
65
|
-
"@backstage/cli": "^0.32.
|
|
64
|
+
"@backstage/backend-test-utils": "^1.5.0",
|
|
65
|
+
"@backstage/cli": "^0.32.1",
|
|
66
66
|
"@backstage/config": "^1.3.2",
|
|
67
|
-
"@backstage/core-plugin-api": "^1.10.
|
|
67
|
+
"@backstage/core-plugin-api": "^1.10.7",
|
|
68
|
+
"@backstage/plugin-catalog-node": "^1.17.0",
|
|
68
69
|
"@backstage/types": "^1.2.1",
|
|
69
70
|
"@types/express": "4.17.22",
|
|
70
71
|
"@types/knex": "^0.16.1",
|
|
@@ -87,8 +88,6 @@
|
|
|
87
88
|
"directory": "workspaces/rbac/plugins/rbac-backend"
|
|
88
89
|
},
|
|
89
90
|
"keywords": [
|
|
90
|
-
"support:production",
|
|
91
|
-
"lifecycle:active",
|
|
92
91
|
"backstage",
|
|
93
92
|
"plugin"
|
|
94
93
|
],
|