@backstage-community/plugin-rbac-backend 6.2.5 → 6.3.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 +20 -0
- package/README.md +41 -3
- 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 +5 -1
- 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 +6 -3
- 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 +131 -125
- package/dist/service/policies-rest-api.cjs.js.map +1 -1
- package/dist/service/policy-builder.cjs.js +31 -15
- package/dist/service/policy-builder.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 +4 -4
|
@@ -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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"}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
var errors = require('@backstage/errors');
|
|
4
4
|
var pluginPermissionBackend = require('@backstage/plugin-permission-backend');
|
|
5
5
|
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
6
|
-
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
7
6
|
var lodash = require('lodash');
|
|
8
7
|
var pluginRbacCommon = require('@backstage-community/plugin-rbac-common');
|
|
9
8
|
var restInterceptor = require('../auditor/rest-interceptor.cjs.js');
|
|
@@ -12,76 +11,73 @@ var helper = require('../helper.cjs.js');
|
|
|
12
11
|
var conditionValidation = require('../validation/condition-validation.cjs.js');
|
|
13
12
|
var policiesValidation = require('../validation/policies-validation.cjs.js');
|
|
14
13
|
var conditions = require('../permissions/conditions.cjs.js');
|
|
15
|
-
|
|
14
|
+
require('../permissions/rules.cjs.js');
|
|
15
|
+
var permissionDefinitionRoutes = require('./permission-definition-routes.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
54
|
const router = await pluginPermissionBackend.createRouter(this.options);
|
|
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);
|
|
55
|
+
const { logger, auditor, auth, permissionsRegistry } = this.options;
|
|
66
56
|
const isPluginEnabled = this.options.config.getOptionalBoolean("permission.enabled");
|
|
67
57
|
if (!isPluginEnabled) {
|
|
68
58
|
return router;
|
|
69
59
|
}
|
|
60
|
+
const transformConditions = conditions.conditionTransformerFunc(permissionsRegistry);
|
|
70
61
|
router.get("/", async (request, response) => {
|
|
71
|
-
await
|
|
62
|
+
await authorizeConditional(
|
|
63
|
+
request,
|
|
64
|
+
pluginRbacCommon.policyEntityReadPermission,
|
|
65
|
+
this.options
|
|
66
|
+
);
|
|
72
67
|
response.send({ status: "Authorized" });
|
|
73
68
|
});
|
|
74
69
|
router.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 = [];
|
|
@@ -119,15 +115,16 @@ class PoliciesServer {
|
|
|
119
115
|
);
|
|
120
116
|
router.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) => {
|
|
@@ -153,15 +150,16 @@ class PoliciesServer {
|
|
|
153
150
|
);
|
|
154
151
|
router.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;
|
|
@@ -184,9 +182,13 @@ class PoliciesServer {
|
|
|
184
182
|
);
|
|
185
183
|
router.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`);
|
|
@@ -208,15 +210,16 @@ class PoliciesServer {
|
|
|
208
210
|
);
|
|
209
211
|
router.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;
|
|
@@ -269,15 +272,16 @@ class PoliciesServer {
|
|
|
269
272
|
);
|
|
270
273
|
router.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);
|
|
@@ -286,15 +290,16 @@ class PoliciesServer {
|
|
|
286
290
|
);
|
|
287
291
|
router.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(
|
|
@@ -311,12 +316,13 @@ class PoliciesServer {
|
|
|
311
316
|
);
|
|
312
317
|
router.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);
|
|
@@ -366,16 +372,17 @@ class PoliciesServer {
|
|
|
366
372
|
);
|
|
367
373
|
router.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;
|
|
@@ -492,15 +499,16 @@ class PoliciesServer {
|
|
|
492
499
|
);
|
|
493
500
|
router.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
568
|
router.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(
|
|
@@ -616,15 +603,19 @@ class PoliciesServer {
|
|
|
616
603
|
);
|
|
617
604
|
router.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 };
|
|
@@ -634,12 +625,13 @@ class PoliciesServer {
|
|
|
634
625
|
);
|
|
635
626
|
router.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) => {
|
|
@@ -667,15 +659,16 @@ class PoliciesServer {
|
|
|
667
659
|
);
|
|
668
660
|
router.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)) {
|
|
@@ -702,15 +695,16 @@ class PoliciesServer {
|
|
|
702
695
|
);
|
|
703
696
|
router.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,7 +725,7 @@ 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 };
|
|
@@ -740,9 +734,13 @@ class PoliciesServer {
|
|
|
740
734
|
);
|
|
741
735
|
router.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,6 +757,13 @@ class PoliciesServer {
|
|
|
759
757
|
response.status(200).end();
|
|
760
758
|
}
|
|
761
759
|
);
|
|
760
|
+
permissionDefinitionRoutes.registerPermissionDefinitionRoutes(
|
|
761
|
+
router,
|
|
762
|
+
this.pluginPermMetaData,
|
|
763
|
+
this.pluginIdProvider,
|
|
764
|
+
this.extraPluginsIdStorage,
|
|
765
|
+
this.options
|
|
766
|
+
);
|
|
762
767
|
router.use(restInterceptor.setAuditorError());
|
|
763
768
|
return router;
|
|
764
769
|
}
|
|
@@ -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
|