@backstage-community/plugin-rbac-backend 6.2.6 → 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 +42 -0
- package/README.md +44 -6
- package/dist/auditor/auditor.cjs.js +5 -0
- package/dist/auditor/auditor.cjs.js.map +1 -1
- package/dist/auditor/rest-interceptor.cjs.js +5 -0
- package/dist/auditor/rest-interceptor.cjs.js.map +1 -1
- package/dist/database/extra-permission-enabled-plugins-storage.cjs.js +21 -0
- package/dist/database/extra-permission-enabled-plugins-storage.cjs.js.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/permissions/conditions.cjs.js +6 -5
- package/dist/permissions/conditions.cjs.js.map +1 -1
- package/dist/permissions/resource.cjs.js +12 -0
- package/dist/permissions/resource.cjs.js.map +1 -0
- package/dist/permissions/rules.cjs.js +3 -4
- package/dist/permissions/rules.cjs.js.map +1 -1
- package/dist/plugin.cjs.js +12 -6
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/service/extendable-id-provider.cjs.js +32 -0
- package/dist/service/extendable-id-provider.cjs.js.map +1 -0
- package/dist/service/permission-definition-routes.cjs.js +104 -0
- package/dist/service/permission-definition-routes.cjs.js.map +1 -0
- package/dist/service/plugin-endpoints.cjs.js +5 -4
- package/dist/service/plugin-endpoints.cjs.js.map +1 -1
- package/dist/service/policies-rest-api.cjs.js +153 -147
- package/dist/service/policies-rest-api.cjs.js.map +1 -1
- package/dist/service/policy-builder.cjs.js +43 -29
- 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/dist/validation/plugin-validation.cjs.js +15 -0
- package/dist/validation/plugin-validation.cjs.js.map +1 -0
- package/migrations/20250509110032_migrations.js +29 -0
- package/package.json +18 -19
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-definition-routes.cjs.js","sources":["../../src/service/permission-definition-routes.ts"],"sourcesContent":["/*\n * Copyright 2025 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 PermissionDependentPluginList,\n policyEntityCreatePermission,\n policyEntityDeletePermission,\n policyEntityReadPermission,\n} from '@backstage-community/plugin-rbac-common';\nimport { logAuditorEvent } from '../auditor/rest-interceptor';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport {\n PermissionDependentPluginDTO,\n PermissionDependentPluginStore,\n} from '../database/extra-permission-enabled-plugins-storage';\nimport { authorizeConditional } from './policies-rest-api';\nimport {\n AuditorService,\n AuthService,\n HttpAuthService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\nimport {\n ConflictError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\nimport { validatePermissionDependentPlugin } from '../validation/plugin-validation';\nimport express from 'express';\n\nexport function registerPermissionDefinitionRoutes(\n router: express.Router,\n pluginPermMetaData: PluginPermissionMetadataCollector,\n pluginIdProvider: ExtendablePluginIdProvider,\n extraPluginsIdStorage: PermissionDependentPluginStore,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n permissions: PermissionsService;\n },\n) {\n const { auth, auditor } = deps;\n\n router.get(\n '/plugins/policies',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(request, policyEntityReadPermission, deps);\n\n const body = await pluginPermMetaData.getPluginPolicies(auth);\n\n response.json(body);\n },\n );\n\n router.get(\n '/plugins/condition-rules',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(request, policyEntityReadPermission, deps);\n\n const body = await pluginPermMetaData.getPluginConditionRules(auth);\n\n response.json(body);\n },\n );\n\n router.get(\n '/plugins/id',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(request, policyEntityReadPermission, deps);\n\n const actualPluginIds = await pluginIdProvider.getPluginIds();\n response.status(200).json(pluginIdsToResponse(actualPluginIds));\n },\n );\n\n router.post(\n '/plugins/id',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(request, policyEntityCreatePermission, deps);\n const pluginIds: PermissionDependentPluginList = request.body;\n validatePermissionDependentPlugin(pluginIds);\n const pluginDtos = permissionDependentPluginListToDTO(pluginIds);\n\n let actualPluginIds = await pluginIdProvider.getPluginIds();\n const conflictedIds = pluginIds.ids.filter(id =>\n actualPluginIds.includes(id),\n );\n if (conflictedIds.length > 0) {\n throw new ConflictError(\n `Plugin IDs ${JSON.stringify(conflictedIds)} already exist in the system. Please use a different set of plugin ids.`,\n );\n }\n await extraPluginsIdStorage.addPlugins(pluginDtos);\n response.locals.meta = pluginIds;\n\n actualPluginIds = await pluginIdProvider.getPluginIds();\n response.status(200).json(pluginIdsToResponse(actualPluginIds));\n },\n );\n\n router.delete(\n '/plugins/id',\n logAuditorEvent(auditor),\n async (request, response) => {\n await authorizeConditional(request, policyEntityDeletePermission, deps);\n const pluginIds: PermissionDependentPluginList = request.body;\n validatePermissionDependentPlugin(pluginIds);\n const configuredPluginIds = pluginIds.ids.filter(pluginId =>\n pluginIdProvider.isConfiguredPluginId(pluginId),\n );\n if (configuredPluginIds.length > 0) {\n throw new NotAllowedError(\n `Plugin IDs ${JSON.stringify(pluginIds.ids)} can be removed only with help of configuration.`,\n );\n }\n\n let actualPluginIds = await pluginIdProvider.getPluginIds();\n const notFoundPlugins = pluginIds.ids.filter(\n pluginToDel => !actualPluginIds.includes(pluginToDel),\n );\n if (notFoundPlugins.length > 0) {\n throw new NotFoundError(\n `Plugin IDs ${JSON.stringify(notFoundPlugins)} were not found.`,\n );\n }\n\n await extraPluginsIdStorage.deletePlugins(pluginIds.ids);\n response.locals.meta = pluginIds;\n\n actualPluginIds = await pluginIdProvider.getPluginIds();\n response.status(200).json(pluginIdsToResponse(actualPluginIds));\n },\n );\n}\n\nexport function pluginIdsToResponse(\n pluginIds: string[],\n): PermissionDependentPluginList {\n return { ids: pluginIds };\n}\n\nexport function permissionDependentPluginListToDTO(\n pluginList: PermissionDependentPluginList,\n): PermissionDependentPluginDTO[] {\n return pluginList.ids.map(pluginId => {\n return { pluginId };\n });\n}\n"],"names":["logAuditorEvent","authorizeConditional","policyEntityReadPermission","policyEntityCreatePermission","validatePermissionDependentPlugin","ConflictError","policyEntityDeletePermission","NotAllowedError","NotFoundError"],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ const rbacPermissionMetadata = {
|
|
|
12
12
|
rules: [rules.rbacRules]
|
|
13
13
|
};
|
|
14
14
|
class PluginPermissionMetadataCollector {
|
|
15
|
-
|
|
15
|
+
pluginIdProvider;
|
|
16
16
|
discovery;
|
|
17
17
|
logger;
|
|
18
18
|
urlReader;
|
|
@@ -20,9 +20,9 @@ class PluginPermissionMetadataCollector {
|
|
|
20
20
|
deps,
|
|
21
21
|
optional
|
|
22
22
|
}) {
|
|
23
|
-
const { discovery,
|
|
24
|
-
this.pluginIds = pluginIdProvider.getPluginIds();
|
|
23
|
+
const { discovery, logger, config, pluginIdProvider } = deps;
|
|
25
24
|
this.discovery = discovery;
|
|
25
|
+
this.pluginIdProvider = pluginIdProvider;
|
|
26
26
|
this.logger = logger;
|
|
27
27
|
this.urlReader = optional?.urlReader ?? urlReader.UrlReaders.default({
|
|
28
28
|
config,
|
|
@@ -55,7 +55,8 @@ class PluginPermissionMetadataCollector {
|
|
|
55
55
|
};
|
|
56
56
|
async getPluginMetaData(auth) {
|
|
57
57
|
let pluginResponses = [];
|
|
58
|
-
|
|
58
|
+
const pluginIds = await this.pluginIdProvider.getPluginIds();
|
|
59
|
+
for (const pluginId of pluginIds) {
|
|
59
60
|
try {
|
|
60
61
|
const { token } = await auth.getPluginRequestToken({
|
|
61
62
|
onBehalfOf: await auth.getOwnServiceCredentials(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-endpoints.cjs.js","sources":["../../src/service/plugin-endpoints.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 FetchUrlReader,\n ReaderFactory,\n UrlReaders,\n} from '@backstage/backend-defaults/urlReader';\nimport type {\n AuthService,\n DiscoveryService,\n LoggerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport { isError } from '@backstage/errors';\nimport {\n isResourcePermission,\n Permission,\n} from '@backstage/plugin-permission-common';\nimport type {\n MetadataResponse,\n MetadataResponseSerializedRule,\n} from '@backstage/plugin-permission-node';\n\nimport {\n policyEntityPermissions,\n type PluginPermissionMetaData,\n type PolicyDetails,\n} from '@backstage-community/plugin-rbac-common';\nimport type { PluginIdProvider } from '@backstage-community/plugin-rbac-node';\nimport { rbacRules } from '../permissions';\n\ntype PluginMetadataResponse = {\n pluginId: string;\n metaDataResponse: MetadataResponse;\n};\n\nexport type PluginMetadataResponseSerializedRule = {\n pluginId: string;\n rules: MetadataResponseSerializedRule[];\n};\n\nconst rbacPermissionMetadata: MetadataResponse = {\n permissions: policyEntityPermissions,\n rules: [rbacRules],\n};\n\nexport class PluginPermissionMetadataCollector {\n private readonly pluginIds: string[];\n private readonly discovery: DiscoveryService;\n private readonly logger: LoggerService;\n private readonly urlReader: UrlReaderService;\n\n constructor({\n deps,\n optional,\n }: {\n deps: {\n discovery: DiscoveryService;\n pluginIdProvider: PluginIdProvider;\n logger: LoggerService;\n config: Config;\n };\n optional?: {\n urlReader?: UrlReaderService;\n };\n }) {\n const { discovery, pluginIdProvider, logger, config } = deps;\n this.pluginIds = pluginIdProvider.getPluginIds();\n this.discovery = discovery;\n this.logger = logger;\n this.urlReader =\n optional?.urlReader ??\n UrlReaders.default({\n config,\n logger,\n factories: [PluginPermissionMetadataCollector.permissionFactory],\n });\n }\n\n async getPluginConditionRules(\n auth: AuthService,\n ): Promise<PluginMetadataResponseSerializedRule[]> {\n const pluginMetadata = await this.getPluginMetaData(auth);\n\n return pluginMetadata\n .filter(metadata => metadata.metaDataResponse.rules.length > 0)\n .map(metadata => {\n return {\n pluginId: metadata.pluginId,\n rules: metadata.metaDataResponse.rules,\n };\n });\n }\n\n async getPluginPolicies(\n auth: AuthService,\n ): Promise<PluginPermissionMetaData[]> {\n const pluginMetadata = await this.getPluginMetaData(auth);\n\n return pluginMetadata\n .filter(metadata => metadata.metaDataResponse.permissions !== undefined)\n .map(metadata => {\n return {\n pluginId: metadata.pluginId,\n policies: permissionsToCasbinPolicies(\n metadata.metaDataResponse.permissions!,\n ),\n };\n });\n }\n\n private static permissionFactory: ReaderFactory = () => {\n return [{ reader: new FetchUrlReader(), predicate: (_url: URL) => true }];\n };\n\n private async getPluginMetaData(\n auth: AuthService,\n ): Promise<PluginMetadataResponse[]> {\n let pluginResponses: PluginMetadataResponse[] = [];\n\n for (const pluginId of this.pluginIds) {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: pluginId,\n });\n\n const permMetaData = await this.getMetadataByPluginId(pluginId, token);\n if (permMetaData) {\n pluginResponses = [\n ...pluginResponses,\n {\n metaDataResponse: permMetaData,\n pluginId,\n },\n ];\n }\n } catch (error) {\n this.logger.error(\n `Failed to retrieve permission metadata for ${pluginId}. ${error}`,\n );\n }\n }\n\n return pluginResponses;\n }\n\n async getMetadataByPluginId(\n pluginId: string,\n token: string | undefined,\n ): Promise<MetadataResponse | undefined> {\n let permMetaData: MetadataResponse | undefined;\n\n // Work around: This is needed for start up whenever a conditional policy for the plugin permission in the yaml file\n // will make a check to the well known endpoint\n // However, our plugin has not completely started and as such will throw a 503 error\n // TODO: see if we are able to remove this after we migrate to the permission registry\n if (pluginId === 'permission') {\n return rbacPermissionMetadata;\n }\n\n try {\n const baseEndpoint = await this.discovery.getBaseUrl(pluginId);\n const wellKnownURL = `${baseEndpoint}/.well-known/backstage/permissions/metadata`;\n\n const permResp = await this.urlReader.readUrl(wellKnownURL, { token });\n const permMetaDataRaw = (await permResp.buffer()).toString();\n\n try {\n permMetaData = JSON.parse(permMetaDataRaw);\n } catch (err) {\n // workaround for https://issues.redhat.com/browse/RHIDP-1456\n return undefined;\n }\n } catch (err) {\n if (isError(err) && err.name === 'NotFoundError') {\n this.logger.warn(\n `No permission metadata found for ${pluginId}. ${err}`,\n );\n return undefined;\n }\n this.logger.error(\n `Failed to retrieve permission metadata for ${pluginId}. ${err}`,\n );\n }\n return permMetaData;\n }\n}\n\nfunction permissionsToCasbinPolicies(\n permissions: Permission[],\n): PolicyDetails[] {\n const policies: PolicyDetails[] = [];\n for (const permission of permissions) {\n if (isResourcePermission(permission)) {\n policies.push({\n resourceType: permission.resourceType,\n name: permission.name,\n policy: permission.attributes.action || 'use',\n });\n } else {\n policies.push({\n name: permission.name,\n policy: permission.attributes.action || 'use',\n });\n }\n }\n\n return policies;\n}\n"],"names":["policyEntityPermissions","rbacRules","UrlReaders","FetchUrlReader","isError","isResourcePermission"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-endpoints.cjs.js","sources":["../../src/service/plugin-endpoints.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 FetchUrlReader,\n ReaderFactory,\n UrlReaders,\n} from '@backstage/backend-defaults/urlReader';\nimport type {\n AuthService,\n DiscoveryService,\n LoggerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\nimport { isError } from '@backstage/errors';\nimport {\n isResourcePermission,\n Permission,\n} from '@backstage/plugin-permission-common';\nimport type {\n MetadataResponse,\n MetadataResponseSerializedRule,\n} from '@backstage/plugin-permission-node';\n\nimport {\n policyEntityPermissions,\n type PluginPermissionMetaData,\n type PolicyDetails,\n} from '@backstage-community/plugin-rbac-common';\nimport { rbacRules } from '../permissions';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\n\ntype PluginMetadataResponse = {\n pluginId: string;\n metaDataResponse: MetadataResponse;\n};\n\nexport type PluginMetadataResponseSerializedRule = {\n pluginId: string;\n rules: MetadataResponseSerializedRule[];\n};\n\nconst rbacPermissionMetadata: MetadataResponse = {\n permissions: policyEntityPermissions,\n rules: [rbacRules],\n};\n\nexport class PluginPermissionMetadataCollector {\n private readonly pluginIdProvider: ExtendablePluginIdProvider;\n private readonly discovery: DiscoveryService;\n private readonly logger: LoggerService;\n private readonly urlReader: UrlReaderService;\n\n constructor({\n deps,\n optional,\n }: {\n deps: {\n discovery: DiscoveryService;\n pluginIdProvider: ExtendablePluginIdProvider;\n logger: LoggerService;\n config: Config;\n };\n optional?: {\n urlReader?: UrlReaderService;\n };\n }) {\n const { discovery, logger, config, pluginIdProvider } = deps;\n this.discovery = discovery;\n this.pluginIdProvider = pluginIdProvider;\n this.logger = logger;\n this.urlReader =\n optional?.urlReader ??\n UrlReaders.default({\n config,\n logger,\n factories: [PluginPermissionMetadataCollector.permissionFactory],\n });\n }\n\n async getPluginConditionRules(\n auth: AuthService,\n ): Promise<PluginMetadataResponseSerializedRule[]> {\n const pluginMetadata = await this.getPluginMetaData(auth);\n\n return pluginMetadata\n .filter(metadata => metadata.metaDataResponse.rules.length > 0)\n .map(metadata => {\n return {\n pluginId: metadata.pluginId,\n rules: metadata.metaDataResponse.rules,\n };\n });\n }\n\n async getPluginPolicies(\n auth: AuthService,\n ): Promise<PluginPermissionMetaData[]> {\n const pluginMetadata = await this.getPluginMetaData(auth);\n\n return pluginMetadata\n .filter(metadata => metadata.metaDataResponse.permissions !== undefined)\n .map(metadata => {\n return {\n pluginId: metadata.pluginId,\n policies: permissionsToCasbinPolicies(\n metadata.metaDataResponse.permissions!,\n ),\n };\n });\n }\n\n private static permissionFactory: ReaderFactory = () => {\n return [{ reader: new FetchUrlReader(), predicate: (_url: URL) => true }];\n };\n\n private async getPluginMetaData(\n auth: AuthService,\n ): Promise<PluginMetadataResponse[]> {\n let pluginResponses: PluginMetadataResponse[] = [];\n\n const pluginIds = await this.pluginIdProvider.getPluginIds();\n for (const pluginId of pluginIds) {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: pluginId,\n });\n\n const permMetaData = await this.getMetadataByPluginId(pluginId, token);\n if (permMetaData) {\n pluginResponses = [\n ...pluginResponses,\n {\n metaDataResponse: permMetaData,\n pluginId,\n },\n ];\n }\n } catch (error) {\n this.logger.error(\n `Failed to retrieve permission metadata for ${pluginId}. ${error}`,\n );\n }\n }\n\n return pluginResponses;\n }\n\n async getMetadataByPluginId(\n pluginId: string,\n token: string | undefined,\n ): Promise<MetadataResponse | undefined> {\n let permMetaData: MetadataResponse | undefined;\n\n // Work around: This is needed for start up whenever a conditional policy for the plugin permission in the yaml file\n // will make a check to the well known endpoint\n // However, our plugin has not completely started and as such will throw a 503 error\n // TODO: see if we are able to remove this after we migrate to the permission registry\n if (pluginId === 'permission') {\n return rbacPermissionMetadata;\n }\n\n try {\n const baseEndpoint = await this.discovery.getBaseUrl(pluginId);\n const wellKnownURL = `${baseEndpoint}/.well-known/backstage/permissions/metadata`;\n\n const permResp = await this.urlReader.readUrl(wellKnownURL, { token });\n const permMetaDataRaw = (await permResp.buffer()).toString();\n\n try {\n permMetaData = JSON.parse(permMetaDataRaw);\n } catch (err) {\n // workaround for https://issues.redhat.com/browse/RHIDP-1456\n return undefined;\n }\n } catch (err) {\n if (isError(err) && err.name === 'NotFoundError') {\n this.logger.warn(\n `No permission metadata found for ${pluginId}. ${err}`,\n );\n return undefined;\n }\n this.logger.error(\n `Failed to retrieve permission metadata for ${pluginId}. ${err}`,\n );\n }\n return permMetaData;\n }\n}\n\nfunction permissionsToCasbinPolicies(\n permissions: Permission[],\n): PolicyDetails[] {\n const policies: PolicyDetails[] = [];\n for (const permission of permissions) {\n if (isResourcePermission(permission)) {\n policies.push({\n resourceType: permission.resourceType,\n name: permission.name,\n policy: permission.attributes.action || 'use',\n });\n } else {\n policies.push({\n name: permission.name,\n policy: permission.attributes.action || 'use',\n });\n }\n }\n\n return policies;\n}\n"],"names":["policyEntityPermissions","rbacRules","UrlReaders","FetchUrlReader","isError","isResourcePermission"],"mappings":"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"}
|
|
@@ -1,9 +1,7 @@
|
|
|
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
|
-
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
7
5
|
var lodash = require('lodash');
|
|
8
6
|
var pluginRbacCommon = require('@backstage-community/plugin-rbac-common');
|
|
9
7
|
var restInterceptor = require('../auditor/rest-interceptor.cjs.js');
|
|
@@ -12,76 +10,74 @@ var helper = require('../helper.cjs.js');
|
|
|
12
10
|
var conditionValidation = require('../validation/condition-validation.cjs.js');
|
|
13
11
|
var policiesValidation = require('../validation/policies-validation.cjs.js');
|
|
14
12
|
var conditions = require('../permissions/conditions.cjs.js');
|
|
15
|
-
|
|
13
|
+
require('../permissions/rules.cjs.js');
|
|
14
|
+
var permissionDefinitionRoutes = require('./permission-definition-routes.cjs.js');
|
|
15
|
+
var router = require('./router.cjs.js');
|
|
16
16
|
|
|
17
|
+
async function authorizeConditional(request, permission, deps) {
|
|
18
|
+
const { auth, httpAuth, permissions } = deps;
|
|
19
|
+
const credentials = await httpAuth.credentials(request, {
|
|
20
|
+
allow: ["user", "service"]
|
|
21
|
+
});
|
|
22
|
+
if (auth.isPrincipal(credentials, "service") && permission !== pluginRbacCommon.policyEntityReadPermission) {
|
|
23
|
+
throw new errors.NotAllowedError(
|
|
24
|
+
`Only credential principal with type 'user' permitted to modify permissions`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
let decision;
|
|
28
|
+
if (permission.type === "resource") {
|
|
29
|
+
decision = (await permissions.authorizeConditional([{ permission }], {
|
|
30
|
+
credentials
|
|
31
|
+
}))[0];
|
|
32
|
+
} else {
|
|
33
|
+
decision = (await permissions.authorize([{ permission }], {
|
|
34
|
+
credentials
|
|
35
|
+
}))[0];
|
|
36
|
+
}
|
|
37
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
38
|
+
throw new errors.NotAllowedError();
|
|
39
|
+
}
|
|
40
|
+
return { decision, credentials };
|
|
41
|
+
}
|
|
17
42
|
class PoliciesServer {
|
|
18
|
-
constructor(
|
|
19
|
-
this.permissions = permissions;
|
|
43
|
+
constructor(options, enforcer, conditionalStorage, pluginPermMetaData, roleMetadata, extraPluginsIdStorage, pluginIdProvider, rbacProviders) {
|
|
20
44
|
this.options = options;
|
|
21
45
|
this.enforcer = enforcer;
|
|
22
46
|
this.conditionalStorage = conditionalStorage;
|
|
23
47
|
this.pluginPermMetaData = pluginPermMetaData;
|
|
24
48
|
this.roleMetadata = roleMetadata;
|
|
25
|
-
this.
|
|
49
|
+
this.extraPluginsIdStorage = extraPluginsIdStorage;
|
|
50
|
+
this.pluginIdProvider = pluginIdProvider;
|
|
26
51
|
this.rbacProviders = rbacProviders;
|
|
27
52
|
}
|
|
28
|
-
async authorizeConditional(request, permission) {
|
|
29
|
-
const credentials = await this.options.httpAuth.credentials(request, {
|
|
30
|
-
allow: ["user", "service"]
|
|
31
|
-
});
|
|
32
|
-
if (this.options.auth.isPrincipal(credentials, "service") && permission !== pluginRbacCommon.policyEntityReadPermission) {
|
|
33
|
-
throw new errors.NotAllowedError(
|
|
34
|
-
`Only credential principal with type 'user' permitted to modify permissions`
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
let decision;
|
|
38
|
-
if (permission.type === "resource") {
|
|
39
|
-
decision = (await this.permissions.authorizeConditional([{ permission }], {
|
|
40
|
-
credentials
|
|
41
|
-
}))[0];
|
|
42
|
-
} else {
|
|
43
|
-
decision = (await this.permissions.authorize([{ permission }], {
|
|
44
|
-
credentials
|
|
45
|
-
}))[0];
|
|
46
|
-
}
|
|
47
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
48
|
-
throw new errors.NotAllowedError();
|
|
49
|
-
}
|
|
50
|
-
return { decision, credentials };
|
|
51
|
-
}
|
|
52
53
|
async serve() {
|
|
53
|
-
const router = await
|
|
54
|
-
const { logger } = this.options;
|
|
55
|
-
const policyPermissionsIntegrationRouter = pluginPermissionNode.createPermissionIntegrationRouter({
|
|
56
|
-
resourceType: pluginRbacCommon.RESOURCE_TYPE_POLICY_ENTITY,
|
|
57
|
-
getResources: (resourceRefs) => Promise.all(
|
|
58
|
-
resourceRefs.map((ref) => {
|
|
59
|
-
return this.roleMetadata.findRoleMetadata(ref);
|
|
60
|
-
})
|
|
61
|
-
),
|
|
62
|
-
permissions: pluginRbacCommon.policyEntityPermissions,
|
|
63
|
-
rules: Object.values(rules.rules)
|
|
64
|
-
});
|
|
65
|
-
router.use(policyPermissionsIntegrationRouter);
|
|
54
|
+
const router$1 = await router.createRouter(this.options);
|
|
55
|
+
const { logger, auditor, auth, permissionsRegistry } = this.options;
|
|
66
56
|
const isPluginEnabled = this.options.config.getOptionalBoolean("permission.enabled");
|
|
67
57
|
if (!isPluginEnabled) {
|
|
68
|
-
return router;
|
|
58
|
+
return router$1;
|
|
69
59
|
}
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
const transformConditions = conditions.conditionTransformerFunc(permissionsRegistry);
|
|
61
|
+
router$1.get("/", async (request, response) => {
|
|
62
|
+
await authorizeConditional(
|
|
63
|
+
request,
|
|
64
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
65
|
+
this.options
|
|
66
|
+
);
|
|
72
67
|
response.send({ status: "Authorized" });
|
|
73
68
|
});
|
|
74
|
-
router.get(
|
|
69
|
+
router$1.get(
|
|
75
70
|
"/policies",
|
|
76
|
-
restInterceptor.logAuditorEvent(
|
|
71
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
77
72
|
async (request, response) => {
|
|
78
73
|
let conditionsFilter;
|
|
79
|
-
const { decision } = await
|
|
74
|
+
const { decision } = await authorizeConditional(
|
|
80
75
|
request,
|
|
81
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
76
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
77
|
+
this.options
|
|
82
78
|
);
|
|
83
79
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
84
|
-
conditionsFilter =
|
|
80
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
85
81
|
}
|
|
86
82
|
const roleMetadata = await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);
|
|
87
83
|
let policies = [];
|
|
@@ -117,17 +113,18 @@ class PoliciesServer {
|
|
|
117
113
|
response.json(body);
|
|
118
114
|
}
|
|
119
115
|
);
|
|
120
|
-
router.get(
|
|
116
|
+
router$1.get(
|
|
121
117
|
"/policies/:kind/:namespace/:name",
|
|
122
|
-
restInterceptor.logAuditorEvent(
|
|
118
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
123
119
|
async (request, response) => {
|
|
124
120
|
let conditionsFilter;
|
|
125
|
-
const { decision } = await
|
|
121
|
+
const { decision } = await authorizeConditional(
|
|
126
122
|
request,
|
|
127
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
123
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
124
|
+
this.options
|
|
128
125
|
);
|
|
129
126
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
130
|
-
conditionsFilter =
|
|
127
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
131
128
|
}
|
|
132
129
|
const roleMetadata = await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);
|
|
133
130
|
const matchedRoleName = roleMetadata.flatMap((role) => {
|
|
@@ -151,17 +148,18 @@ class PoliciesServer {
|
|
|
151
148
|
}
|
|
152
149
|
}
|
|
153
150
|
);
|
|
154
|
-
router.delete(
|
|
151
|
+
router$1.delete(
|
|
155
152
|
"/policies/:kind/:namespace/:name",
|
|
156
|
-
restInterceptor.logAuditorEvent(
|
|
153
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
157
154
|
async (request, response) => {
|
|
158
155
|
let conditionsFilter;
|
|
159
|
-
const { decision } = await
|
|
156
|
+
const { decision } = await authorizeConditional(
|
|
160
157
|
request,
|
|
161
|
-
pluginRbacCommon.policyEntityDeletePermission
|
|
158
|
+
pluginRbacCommon.policyEntityDeletePermission,
|
|
159
|
+
this.options
|
|
162
160
|
);
|
|
163
161
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
164
|
-
conditionsFilter =
|
|
162
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
165
163
|
}
|
|
166
164
|
const entityRef = this.getEntityReference(request);
|
|
167
165
|
const policyRaw = request.body;
|
|
@@ -182,11 +180,15 @@ class PoliciesServer {
|
|
|
182
180
|
response.status(204).end();
|
|
183
181
|
}
|
|
184
182
|
);
|
|
185
|
-
router.post(
|
|
183
|
+
router$1.post(
|
|
186
184
|
"/policies",
|
|
187
|
-
restInterceptor.logAuditorEvent(
|
|
185
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
188
186
|
async (request, response) => {
|
|
189
|
-
await
|
|
187
|
+
await authorizeConditional(
|
|
188
|
+
request,
|
|
189
|
+
pluginRbacCommon.policyEntityCreatePermission,
|
|
190
|
+
this.options
|
|
191
|
+
);
|
|
190
192
|
const policyRaw = request.body;
|
|
191
193
|
if (lodash.isEmpty(policyRaw)) {
|
|
192
194
|
throw new errors.InputError(`permission policy must be present`);
|
|
@@ -206,17 +208,18 @@ class PoliciesServer {
|
|
|
206
208
|
response.status(201).end();
|
|
207
209
|
}
|
|
208
210
|
);
|
|
209
|
-
router.put(
|
|
211
|
+
router$1.put(
|
|
210
212
|
"/policies/:kind/:namespace/:name",
|
|
211
|
-
restInterceptor.logAuditorEvent(
|
|
213
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
212
214
|
async (request, response) => {
|
|
213
215
|
let conditionsFilter;
|
|
214
|
-
const { decision } = await
|
|
216
|
+
const { decision } = await authorizeConditional(
|
|
215
217
|
request,
|
|
216
|
-
pluginRbacCommon.policyEntityUpdatePermission
|
|
218
|
+
pluginRbacCommon.policyEntityUpdatePermission,
|
|
219
|
+
this.options
|
|
217
220
|
);
|
|
218
221
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
219
|
-
conditionsFilter =
|
|
222
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
220
223
|
}
|
|
221
224
|
const entityRef = this.getEntityReference(request);
|
|
222
225
|
const oldPolicyRaw = request.body.oldPolicy;
|
|
@@ -267,34 +270,36 @@ class PoliciesServer {
|
|
|
267
270
|
response.status(200).end();
|
|
268
271
|
}
|
|
269
272
|
);
|
|
270
|
-
router.get(
|
|
273
|
+
router$1.get(
|
|
271
274
|
"/roles",
|
|
272
|
-
restInterceptor.logAuditorEvent(
|
|
275
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
273
276
|
async (request, response) => {
|
|
274
277
|
let conditionsFilter;
|
|
275
|
-
const { decision } = await
|
|
278
|
+
const { decision } = await authorizeConditional(
|
|
276
279
|
request,
|
|
277
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
280
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
281
|
+
this.options
|
|
278
282
|
);
|
|
279
283
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
280
|
-
conditionsFilter =
|
|
284
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
281
285
|
}
|
|
282
286
|
const roles = await this.enforcer.getGroupingPolicy();
|
|
283
287
|
const body = await this.transformRoleArray(conditionsFilter, ...roles);
|
|
284
288
|
response.json(body);
|
|
285
289
|
}
|
|
286
290
|
);
|
|
287
|
-
router.get(
|
|
291
|
+
router$1.get(
|
|
288
292
|
"/roles/:kind/:namespace/:name",
|
|
289
|
-
restInterceptor.logAuditorEvent(
|
|
293
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
290
294
|
async (request, response) => {
|
|
291
295
|
let conditionsFilter;
|
|
292
|
-
const { decision } = await
|
|
296
|
+
const { decision } = await authorizeConditional(
|
|
293
297
|
request,
|
|
294
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
298
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
299
|
+
this.options
|
|
295
300
|
);
|
|
296
301
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
297
|
-
conditionsFilter =
|
|
302
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
298
303
|
}
|
|
299
304
|
const roleEntityRef = this.getEntityReference(request, true);
|
|
300
305
|
const role = await this.enforcer.getFilteredGroupingPolicy(
|
|
@@ -309,14 +314,15 @@ class PoliciesServer {
|
|
|
309
314
|
}
|
|
310
315
|
}
|
|
311
316
|
);
|
|
312
|
-
router.post(
|
|
317
|
+
router$1.post(
|
|
313
318
|
"/roles",
|
|
314
|
-
restInterceptor.logAuditorEvent(
|
|
319
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
315
320
|
async (request, response) => {
|
|
316
321
|
const uniqueItems = /* @__PURE__ */ new Set();
|
|
317
|
-
const { credentials } = await
|
|
322
|
+
const { credentials } = await authorizeConditional(
|
|
318
323
|
request,
|
|
319
|
-
pluginRbacCommon.policyEntityCreatePermission
|
|
324
|
+
pluginRbacCommon.policyEntityCreatePermission,
|
|
325
|
+
this.options
|
|
320
326
|
);
|
|
321
327
|
const roleRaw = request.body;
|
|
322
328
|
let err = policiesValidation.validateRole(roleRaw);
|
|
@@ -364,18 +370,19 @@ class PoliciesServer {
|
|
|
364
370
|
response.status(201).end();
|
|
365
371
|
}
|
|
366
372
|
);
|
|
367
|
-
router.put(
|
|
373
|
+
router$1.put(
|
|
368
374
|
"/roles/:kind/:namespace/:name",
|
|
369
|
-
restInterceptor.logAuditorEvent(
|
|
375
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
370
376
|
async (request, response) => {
|
|
371
377
|
const uniqueItems = /* @__PURE__ */ new Set();
|
|
372
378
|
let conditionsFilter;
|
|
373
|
-
const { decision, credentials } = await
|
|
379
|
+
const { decision, credentials } = await authorizeConditional(
|
|
374
380
|
request,
|
|
375
|
-
pluginRbacCommon.policyEntityUpdatePermission
|
|
381
|
+
pluginRbacCommon.policyEntityUpdatePermission,
|
|
382
|
+
this.options
|
|
376
383
|
);
|
|
377
384
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
378
|
-
conditionsFilter =
|
|
385
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
379
386
|
}
|
|
380
387
|
const roleEntityRef = this.getEntityReference(request, true);
|
|
381
388
|
const oldRoleRaw = request.body.oldRole;
|
|
@@ -490,17 +497,18 @@ class PoliciesServer {
|
|
|
490
497
|
response.status(200).end();
|
|
491
498
|
}
|
|
492
499
|
);
|
|
493
|
-
router.delete(
|
|
500
|
+
router$1.delete(
|
|
494
501
|
"/roles/:kind/:namespace/:name",
|
|
495
|
-
restInterceptor.logAuditorEvent(
|
|
502
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
496
503
|
async (request, response) => {
|
|
497
504
|
let conditionsFilter;
|
|
498
|
-
const { decision, credentials } = await
|
|
505
|
+
const { decision, credentials } = await authorizeConditional(
|
|
499
506
|
request,
|
|
500
|
-
pluginRbacCommon.policyEntityDeletePermission
|
|
507
|
+
pluginRbacCommon.policyEntityDeletePermission,
|
|
508
|
+
this.options
|
|
501
509
|
);
|
|
502
510
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
503
|
-
conditionsFilter =
|
|
511
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
504
512
|
}
|
|
505
513
|
const roleEntityRef = this.getEntityReference(request, true);
|
|
506
514
|
const currentMetadata = await this.roleMetadata.findRoleMetadata(roleEntityRef);
|
|
@@ -557,51 +565,30 @@ class PoliciesServer {
|
|
|
557
565
|
response.status(204).end();
|
|
558
566
|
}
|
|
559
567
|
);
|
|
560
|
-
router.get(
|
|
561
|
-
"/plugins/policies",
|
|
562
|
-
restInterceptor.logAuditorEvent(this.auditor),
|
|
563
|
-
async (request, response) => {
|
|
564
|
-
await this.authorizeConditional(request, pluginRbacCommon.policyEntityReadPermission);
|
|
565
|
-
const body = await this.pluginPermMetaData.getPluginPolicies(
|
|
566
|
-
this.options.auth
|
|
567
|
-
);
|
|
568
|
-
response.json(body);
|
|
569
|
-
}
|
|
570
|
-
);
|
|
571
|
-
router.get(
|
|
572
|
-
"/plugins/condition-rules",
|
|
573
|
-
restInterceptor.logAuditorEvent(this.auditor),
|
|
574
|
-
async (request, response) => {
|
|
575
|
-
await this.authorizeConditional(request, pluginRbacCommon.policyEntityReadPermission);
|
|
576
|
-
const body = await this.pluginPermMetaData.getPluginConditionRules(
|
|
577
|
-
this.options.auth
|
|
578
|
-
);
|
|
579
|
-
response.json(body);
|
|
580
|
-
}
|
|
581
|
-
);
|
|
582
|
-
router.get(
|
|
568
|
+
router$1.get(
|
|
583
569
|
"/roles/conditions",
|
|
584
|
-
restInterceptor.logAuditorEvent(
|
|
570
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
585
571
|
async (request, response) => {
|
|
586
572
|
let conditionsFilter;
|
|
587
|
-
const { decision } = await
|
|
573
|
+
const { decision } = await authorizeConditional(
|
|
588
574
|
request,
|
|
589
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
575
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
576
|
+
this.options
|
|
590
577
|
);
|
|
591
578
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
592
|
-
conditionsFilter =
|
|
579
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
593
580
|
}
|
|
594
581
|
const roleMetadata = await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);
|
|
595
582
|
const matchedRoleName = roleMetadata.flatMap((role) => {
|
|
596
583
|
return role.roleEntityRef;
|
|
597
584
|
});
|
|
598
|
-
const conditions
|
|
585
|
+
const conditions = await this.conditionalStorage.filterConditions(
|
|
599
586
|
this.getFirstQuery(request.query.roleEntityRef),
|
|
600
587
|
this.getFirstQuery(request.query.pluginId),
|
|
601
588
|
this.getFirstQuery(request.query.resourceType),
|
|
602
589
|
this.getActionQueries(request.query.actions)
|
|
603
590
|
);
|
|
604
|
-
const body = conditions
|
|
591
|
+
const body = conditions.map((condition) => {
|
|
605
592
|
return {
|
|
606
593
|
...condition,
|
|
607
594
|
permissionMapping: condition.permissionMapping.map(
|
|
@@ -614,17 +601,21 @@ class PoliciesServer {
|
|
|
614
601
|
response.json(body);
|
|
615
602
|
}
|
|
616
603
|
);
|
|
617
|
-
router.post(
|
|
604
|
+
router$1.post(
|
|
618
605
|
"/roles/conditions",
|
|
619
|
-
restInterceptor.logAuditorEvent(
|
|
606
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
620
607
|
async (request, response) => {
|
|
621
|
-
await
|
|
608
|
+
await authorizeConditional(
|
|
609
|
+
request,
|
|
610
|
+
pluginRbacCommon.policyEntityCreatePermission,
|
|
611
|
+
this.options
|
|
612
|
+
);
|
|
622
613
|
const roleConditionPolicy = request.body;
|
|
623
614
|
conditionValidation.validateRoleCondition(roleConditionPolicy);
|
|
624
615
|
const conditionToCreate = await helper.processConditionMapping(
|
|
625
616
|
roleConditionPolicy,
|
|
626
617
|
this.pluginPermMetaData,
|
|
627
|
-
|
|
618
|
+
auth
|
|
628
619
|
);
|
|
629
620
|
const id = await this.conditionalStorage.createCondition(conditionToCreate);
|
|
630
621
|
const body = { id };
|
|
@@ -632,14 +623,15 @@ class PoliciesServer {
|
|
|
632
623
|
response.status(201).json(body);
|
|
633
624
|
}
|
|
634
625
|
);
|
|
635
|
-
router.get(
|
|
626
|
+
router$1.get(
|
|
636
627
|
"/roles/conditions/:id",
|
|
637
|
-
restInterceptor.logAuditorEvent(
|
|
628
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
638
629
|
async (request, response) => {
|
|
639
630
|
let conditionsFilter;
|
|
640
|
-
const { decision } = await
|
|
631
|
+
const { decision } = await authorizeConditional(
|
|
641
632
|
request,
|
|
642
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
633
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
634
|
+
this.options
|
|
643
635
|
);
|
|
644
636
|
const id = parseInt(request.params.id, 10);
|
|
645
637
|
if (isNaN(id)) {
|
|
@@ -650,7 +642,7 @@ class PoliciesServer {
|
|
|
650
642
|
throw new errors.NotFoundError();
|
|
651
643
|
}
|
|
652
644
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
653
|
-
conditionsFilter =
|
|
645
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
654
646
|
}
|
|
655
647
|
const roleMetadata = await this.roleMetadata.filterForOwnerRoleMetadata(conditionsFilter);
|
|
656
648
|
const matchedRoleName = roleMetadata.flatMap((role) => {
|
|
@@ -665,17 +657,18 @@ class PoliciesServer {
|
|
|
665
657
|
response.json(body);
|
|
666
658
|
}
|
|
667
659
|
);
|
|
668
|
-
router.delete(
|
|
660
|
+
router$1.delete(
|
|
669
661
|
"/roles/conditions/:id",
|
|
670
|
-
restInterceptor.logAuditorEvent(
|
|
662
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
671
663
|
async (request, response) => {
|
|
672
664
|
let conditionsFilter;
|
|
673
|
-
const { decision } = await
|
|
665
|
+
const { decision } = await authorizeConditional(
|
|
674
666
|
request,
|
|
675
|
-
pluginRbacCommon.policyEntityDeletePermission
|
|
667
|
+
pluginRbacCommon.policyEntityDeletePermission,
|
|
668
|
+
this.options
|
|
676
669
|
);
|
|
677
670
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
678
|
-
conditionsFilter =
|
|
671
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
679
672
|
}
|
|
680
673
|
const id = parseInt(request.params.id, 10);
|
|
681
674
|
if (isNaN(id)) {
|
|
@@ -700,17 +693,18 @@ class PoliciesServer {
|
|
|
700
693
|
response.status(204).end();
|
|
701
694
|
}
|
|
702
695
|
);
|
|
703
|
-
router.put(
|
|
696
|
+
router$1.put(
|
|
704
697
|
"/roles/conditions/:id",
|
|
705
|
-
restInterceptor.logAuditorEvent(
|
|
698
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
706
699
|
async (request, response) => {
|
|
707
700
|
let conditionsFilter;
|
|
708
|
-
const { decision } = await
|
|
701
|
+
const { decision } = await authorizeConditional(
|
|
709
702
|
request,
|
|
710
|
-
pluginRbacCommon.policyEntityUpdatePermission
|
|
703
|
+
pluginRbacCommon.policyEntityUpdatePermission,
|
|
704
|
+
this.options
|
|
711
705
|
);
|
|
712
706
|
if (decision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
|
|
713
|
-
conditionsFilter =
|
|
707
|
+
conditionsFilter = transformConditions(decision.conditions);
|
|
714
708
|
}
|
|
715
709
|
const id = parseInt(request.params.id, 10);
|
|
716
710
|
if (isNaN(id)) {
|
|
@@ -731,18 +725,22 @@ class PoliciesServer {
|
|
|
731
725
|
const conditionToUpdate = await helper.processConditionMapping(
|
|
732
726
|
roleConditionPolicy,
|
|
733
727
|
this.pluginPermMetaData,
|
|
734
|
-
|
|
728
|
+
auth
|
|
735
729
|
);
|
|
736
730
|
await this.conditionalStorage.updateCondition(id, conditionToUpdate);
|
|
737
731
|
response.locals.meta = { condition: roleConditionPolicy };
|
|
738
732
|
response.status(200).end();
|
|
739
733
|
}
|
|
740
734
|
);
|
|
741
|
-
router.post(
|
|
735
|
+
router$1.post(
|
|
742
736
|
"/refresh/:id",
|
|
743
|
-
restInterceptor.logAuditorEvent(
|
|
737
|
+
restInterceptor.logAuditorEvent(auditor),
|
|
744
738
|
async (request, response) => {
|
|
745
|
-
await
|
|
739
|
+
await authorizeConditional(
|
|
740
|
+
request,
|
|
741
|
+
pluginRbacCommon.policyEntityCreatePermission,
|
|
742
|
+
this.options
|
|
743
|
+
);
|
|
746
744
|
if (!this.rbacProviders) {
|
|
747
745
|
throw new errors.NotFoundError(`No RBAC providers were found`);
|
|
748
746
|
}
|
|
@@ -759,8 +757,15 @@ class PoliciesServer {
|
|
|
759
757
|
response.status(200).end();
|
|
760
758
|
}
|
|
761
759
|
);
|
|
762
|
-
|
|
763
|
-
|
|
760
|
+
permissionDefinitionRoutes.registerPermissionDefinitionRoutes(
|
|
761
|
+
router$1,
|
|
762
|
+
this.pluginPermMetaData,
|
|
763
|
+
this.pluginIdProvider,
|
|
764
|
+
this.extraPluginsIdStorage,
|
|
765
|
+
this.options
|
|
766
|
+
);
|
|
767
|
+
router$1.use(restInterceptor.setAuditorError());
|
|
768
|
+
return router$1;
|
|
764
769
|
}
|
|
765
770
|
getEntityReference(request, role) {
|
|
766
771
|
const kind = request.params.kind;
|
|
@@ -939,4 +944,5 @@ class PoliciesServer {
|
|
|
939
944
|
}
|
|
940
945
|
|
|
941
946
|
exports.PoliciesServer = PoliciesServer;
|
|
947
|
+
exports.authorizeConditional = authorizeConditional;
|
|
942
948
|
//# sourceMappingURL=policies-rest-api.cjs.js.map
|