@backstage-community/plugin-rbac-backend 7.9.1 → 7.11.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 +37 -0
- package/README.md +24 -0
- package/config.d.ts +23 -0
- package/dist/database/role-metadata.cjs.js +49 -3
- package/dist/database/role-metadata.cjs.js.map +1 -1
- package/dist/default-permissions/default-permissions.cjs.js +133 -0
- package/dist/default-permissions/default-permissions.cjs.js.map +1 -0
- package/dist/helper.cjs.js +19 -0
- package/dist/helper.cjs.js.map +1 -1
- package/dist/permissions/resource.cjs.js.map +1 -1
- package/dist/permissions/rules.cjs.js +3 -0
- package/dist/permissions/rules.cjs.js.map +1 -1
- package/dist/providers/connect-providers.cjs.js +82 -2
- package/dist/providers/connect-providers.cjs.js.map +1 -1
- package/dist/role-manager/role-manager.cjs.js +7 -2
- package/dist/role-manager/role-manager.cjs.js.map +1 -1
- package/dist/service/policies-rest-api.cjs.js +29 -12
- package/dist/service/policies-rest-api.cjs.js.map +1 -1
- package/dist/service/policy-builder.cjs.js +14 -1
- package/dist/service/policy-builder.cjs.js.map +1 -1
- package/migrations/20260216100000_add_is_default_to_role_metadata.js +43 -0
- package/package.json +4 -8
|
@@ -5,12 +5,14 @@ var auditor = require('../auditor/auditor.cjs.js');
|
|
|
5
5
|
var helper = require('../helper.cjs.js');
|
|
6
6
|
var permissionModel = require('../service/permission-model.cjs.js');
|
|
7
7
|
var policiesValidation = require('../validation/policies-validation.cjs.js');
|
|
8
|
+
var lodash = require('lodash');
|
|
8
9
|
|
|
9
10
|
class Connection {
|
|
10
|
-
constructor(id, enforcer, roleMetadataStorage, logger, auditor) {
|
|
11
|
+
constructor(id, enforcer, roleMetadataStorage, conditionStorage, logger, auditor) {
|
|
11
12
|
this.id = id;
|
|
12
13
|
this.enforcer = enforcer;
|
|
13
14
|
this.roleMetadataStorage = roleMetadataStorage;
|
|
15
|
+
this.conditionStorage = conditionStorage;
|
|
14
16
|
this.logger = logger;
|
|
15
17
|
this.auditor = auditor;
|
|
16
18
|
}
|
|
@@ -49,6 +51,27 @@ class Connection {
|
|
|
49
51
|
await this.removePermissions(providerPermissions, tempEnforcer);
|
|
50
52
|
await this.addPermissions(permissions);
|
|
51
53
|
}
|
|
54
|
+
async applyConditionalPermissions(conditionalPermissions) {
|
|
55
|
+
const storedConditionalPermissions = await this.conditionStorage.filterConditions();
|
|
56
|
+
const conditionsToBeAdded = conditionalPermissions.filter(
|
|
57
|
+
(conditionalPermission) => !storedConditionalPermissions.some(
|
|
58
|
+
(stored) => conditionalPermission.roleEntityRef === stored.roleEntityRef && conditionalPermission.pluginId === stored.pluginId && conditionalPermission.resourceType === stored.resourceType && lodash.isEqual(
|
|
59
|
+
conditionalPermission.permissionMapping,
|
|
60
|
+
stored.permissionMapping
|
|
61
|
+
) && lodash.isEqual(conditionalPermission.conditions, stored.conditions)
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
const conditionsToBeRemoved = storedConditionalPermissions.filter(
|
|
65
|
+
(stored) => !conditionalPermissions.some(
|
|
66
|
+
(conditionalPermission) => stored.roleEntityRef === conditionalPermission.roleEntityRef && stored.pluginId === conditionalPermission.pluginId && stored.resourceType === conditionalPermission.resourceType && lodash.isEqual(
|
|
67
|
+
stored.permissionMapping,
|
|
68
|
+
conditionalPermission.permissionMapping
|
|
69
|
+
) && lodash.isEqual(stored.conditions, conditionalPermission.conditions)
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
await this.removeConditionalPermissions(conditionsToBeRemoved);
|
|
73
|
+
await this.addConditionalPermissions(conditionsToBeAdded);
|
|
74
|
+
}
|
|
52
75
|
async addRoles(roles) {
|
|
53
76
|
for (const role of roles) {
|
|
54
77
|
if (!await this.enforcer.hasGroupingPolicy(...role)) {
|
|
@@ -193,6 +216,62 @@ class Connection {
|
|
|
193
216
|
}
|
|
194
217
|
}
|
|
195
218
|
}
|
|
219
|
+
async addConditionalPermissions(conditionalPermissions) {
|
|
220
|
+
for (const condition of conditionalPermissions) {
|
|
221
|
+
const auditorMeta = {
|
|
222
|
+
policies: [condition]
|
|
223
|
+
};
|
|
224
|
+
const auditorEvent = await this.auditor.createEvent({
|
|
225
|
+
eventId: auditor.ConditionEvents.CONDITION_WRITE,
|
|
226
|
+
severityLevel: "medium",
|
|
227
|
+
meta: {
|
|
228
|
+
actionType: auditor.ActionType.CREATE,
|
|
229
|
+
source: this.id
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
try {
|
|
233
|
+
const metadata = await this.roleMetadataStorage.findRoleMetadata(
|
|
234
|
+
condition.roleEntityRef
|
|
235
|
+
);
|
|
236
|
+
const err = await policiesValidation.validateSource(this.id, metadata);
|
|
237
|
+
if (err) {
|
|
238
|
+
throw err;
|
|
239
|
+
}
|
|
240
|
+
await this.conditionStorage.createCondition(condition);
|
|
241
|
+
await auditorEvent.success({ meta: auditorMeta });
|
|
242
|
+
} catch (error) {
|
|
243
|
+
await auditorEvent.fail({ error, meta: auditorMeta });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async removeConditionalPermissions(conditionalPermissions) {
|
|
248
|
+
for (const conditionalPermission of conditionalPermissions) {
|
|
249
|
+
const auditorMeta = {
|
|
250
|
+
policies: [conditionalPermission]
|
|
251
|
+
};
|
|
252
|
+
const auditorEvent = await this.auditor.createEvent({
|
|
253
|
+
eventId: auditor.ConditionEvents.CONDITION_WRITE,
|
|
254
|
+
severityLevel: "medium",
|
|
255
|
+
meta: { actionType: auditor.ActionType.DELETE, source: this.id }
|
|
256
|
+
});
|
|
257
|
+
try {
|
|
258
|
+
const metadata = await this.roleMetadataStorage.findRoleMetadata(
|
|
259
|
+
conditionalPermission.roleEntityRef
|
|
260
|
+
);
|
|
261
|
+
const err = await policiesValidation.validateSource(this.id, metadata);
|
|
262
|
+
if (err) {
|
|
263
|
+
throw err;
|
|
264
|
+
}
|
|
265
|
+
await this.conditionStorage.deleteCondition(conditionalPermission.id);
|
|
266
|
+
await auditorEvent.success({ meta: auditorMeta });
|
|
267
|
+
} catch (error) {
|
|
268
|
+
await auditorEvent.fail({
|
|
269
|
+
error,
|
|
270
|
+
meta: auditorMeta
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
196
275
|
async getProviderRoles() {
|
|
197
276
|
const currentRoles = await this.roleMetadataStorage.filterRoleMetadata(
|
|
198
277
|
this.id
|
|
@@ -200,7 +279,7 @@ class Connection {
|
|
|
200
279
|
return currentRoles.map((meta) => meta.roleEntityRef);
|
|
201
280
|
}
|
|
202
281
|
}
|
|
203
|
-
async function connectRBACProviders(providers, enforcer, roleMetadataStorage, logger, auditor) {
|
|
282
|
+
async function connectRBACProviders(providers, enforcer, roleMetadataStorage, conditionStorage, logger, auditor) {
|
|
204
283
|
await Promise.all(
|
|
205
284
|
providers.map(async (provider) => {
|
|
206
285
|
try {
|
|
@@ -208,6 +287,7 @@ async function connectRBACProviders(providers, enforcer, roleMetadataStorage, lo
|
|
|
208
287
|
provider.getProviderName(),
|
|
209
288
|
enforcer,
|
|
210
289
|
roleMetadataStorage,
|
|
290
|
+
conditionStorage,
|
|
211
291
|
logger,
|
|
212
292
|
auditor
|
|
213
293
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect-providers.cjs.js","sources":["../../src/providers/connect-providers.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 AuditorService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\nimport {\n Enforcer,\n newEnforcer,\n newModelFromString,\n StringAdapter,\n} from 'casbin';\n\nimport type {\n RBACProvider,\n RBACProviderConnection,\n} from '@backstage-community/plugin-rbac-node';\n\nimport { ActionType, PermissionEvents, RoleEvents } from '../auditor/auditor';\nimport { RoleMetadataStorage } from '../database/role-metadata';\nimport {\n transformArrayToPolicy,\n transformRolesGroupToLowercase,\n typedPoliciesToString,\n} from '../helper';\nimport { EnforcerDelegate } from '../service/enforcer-delegate';\nimport { MODEL } from '../service/permission-model';\nimport {\n validateGroupingPolicy,\n validatePolicy,\n validateSource,\n} from '../validation/policies-validation';\n\nexport class Connection implements RBACProviderConnection {\n constructor(\n private readonly id: string,\n private readonly enforcer: EnforcerDelegate,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly logger: LoggerService,\n private readonly auditor: AuditorService,\n ) {}\n\n async applyRoles(roles: string[][]): Promise<void> {\n const lowercasedRoles = transformRolesGroupToLowercase(roles);\n const stringPolicy = typedPoliciesToString(lowercasedRoles, 'g');\n const providerRolesforRemoval: string[][] = [];\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new StringAdapter(stringPolicy),\n );\n\n const providerRoles = await this.getProviderRoles();\n\n await this.enforcer.loadPolicy();\n // Get the roles for this provider coming from rbac plugin\n for (const providerRole of providerRoles) {\n providerRolesforRemoval.push(\n ...(await this.enforcer.getFilteredGroupingPolicy(1, providerRole)),\n );\n }\n\n // Remove role\n // role exists in rbac but does not exist in provider\n await this.removeRoles(providerRolesforRemoval, tempEnforcer);\n\n // Add the role\n // role exists in provider but does not exist in rbac\n await this.addRoles(lowercasedRoles);\n }\n\n async applyPermissions(permissions: string[][]): Promise<void> {\n const stringPolicy = typedPoliciesToString(permissions, 'p');\n\n const providerPermissions: string[][] = [];\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new StringAdapter(stringPolicy),\n );\n\n const providerRoles = await this.getProviderRoles();\n\n await this.enforcer.loadPolicy();\n // Get the roles for this provider coming from rbac plugin\n for (const providerRole of providerRoles) {\n providerPermissions.push(\n ...(await this.enforcer.getFilteredPolicy(0, providerRole)),\n );\n }\n\n await this.removePermissions(providerPermissions, tempEnforcer);\n\n await this.addPermissions(permissions);\n }\n\n private async addRoles(roles: string[][]): Promise<void> {\n for (const role of roles) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n role[1],\n );\n const err = await validateGroupingPolicy(role, metadata, this.id);\n\n if (err) {\n this.logger.warn(err.message);\n continue; // Skip adding this role as there was an error\n }\n\n let roleMeta = await this.roleMetadataStorage.findRoleMetadata(role[1]);\n // role does not exist in rbac, create the metadata for it\n if (!roleMeta) {\n roleMeta = {\n modifiedBy: this.id,\n source: this.id,\n roleEntityRef: role[1],\n };\n }\n\n const auditorMeta = {\n ...roleMeta,\n members: [role[0]],\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: RoleEvents.ROLE_WRITE,\n severityLevel: 'medium',\n meta: {\n actionType: roleMeta ? ActionType.UPDATE : ActionType.CREATE,\n source: auditorMeta.source,\n },\n });\n\n try {\n await this.enforcer.addGroupingPolicy(role, roleMeta);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n }\n\n private async removeRoles(\n providerRoles: string[][],\n tempEnforcer: Enforcer,\n ): Promise<void> {\n // Remove role\n // role exists in rbac but does not exist in provider\n const lowercasedProviderRoles =\n transformRolesGroupToLowercase(providerRoles);\n for (const role of lowercasedProviderRoles) {\n if (!(await tempEnforcer.hasGroupingPolicy(...role))) {\n const roleMeta = await this.roleMetadataStorage.findRoleMetadata(\n role[1],\n );\n\n const currentRole = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n role[1],\n );\n\n if (!roleMeta) {\n this.logger.warn('role does not exist');\n continue;\n }\n\n const singleRole = roleMeta && currentRole.length === 1;\n const actionType = singleRole ? ActionType.DELETE : ActionType.UPDATE;\n\n const auditorMeta = { ...roleMeta, members: [role[0]] };\n const auditorEvent = await this.auditor.createEvent({\n eventId: RoleEvents.ROLE_WRITE,\n severityLevel: 'medium',\n meta: { actionType, source: roleMeta.source },\n });\n\n try {\n await this.enforcer.removeGroupingPolicy(\n role,\n roleMeta,\n actionType === ActionType.UPDATE,\n );\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n }\n\n private async addPermissions(permissions: string[][]): Promise<void> {\n for (const permission of permissions) {\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n if (permission[1] === 'policy-entity' && permission[2] === 'create') {\n this.logger.warn(\n `Permission policy with resource type 'policy-entity' and action 'create' has been removed. Please consider updating policy ${permission} to use 'policy.entity.create' instead of 'policy-entity' from source ${this.id}`,\n );\n }\n\n if (!(await this.enforcer.hasPolicy(...permission))) {\n const transformedPolicy = transformArrayToPolicy(permission);\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n permission[0],\n );\n\n const auditorMeta = {\n policies: [permission],\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: PermissionEvents.POLICY_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.CREATE, source: this.id },\n });\n\n let err = validatePolicy(transformedPolicy);\n if (err) {\n auditorEvent.fail({ error: err, meta: auditorMeta });\n continue; // Skip this invalid permission policy\n }\n\n err = await validateSource(this.id, metadata);\n if (err) {\n auditorEvent.fail({ error: err, meta: auditorMeta });\n continue;\n }\n\n try {\n await this.enforcer.addPolicy(permission);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({ error, meta: auditorMeta });\n }\n }\n }\n }\n\n private async removePermissions(\n providerPermissions: string[][],\n tempEnforcer: Enforcer,\n ): Promise<void> {\n for (const permission of providerPermissions) {\n if (!(await tempEnforcer.hasPolicy(...permission))) {\n const auditorMeta = {\n policies: [permission],\n };\n const auditorEvent = await this.auditor?.createEvent({\n eventId: PermissionEvents.POLICY_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.DELETE, source: this.id },\n });\n\n try {\n await this.enforcer.removePolicy(permission);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n }\n\n private async getProviderRoles(): Promise<string[]> {\n const currentRoles = await this.roleMetadataStorage.filterRoleMetadata(\n this.id,\n );\n return currentRoles.map(meta => meta.roleEntityRef);\n }\n}\n\nexport async function connectRBACProviders(\n providers: RBACProvider[],\n enforcer: EnforcerDelegate,\n roleMetadataStorage: RoleMetadataStorage,\n logger: LoggerService,\n auditor: AuditorService,\n) {\n await Promise.all(\n providers.map(async provider => {\n try {\n const connection = new Connection(\n provider.getProviderName(),\n enforcer,\n roleMetadataStorage,\n logger,\n auditor,\n );\n return provider.connect(connection);\n } catch (error) {\n throw new Error(\n `Unable to connect provider ${provider.getProviderName()}, ${error}`,\n );\n }\n }),\n );\n}\n"],"names":["transformRolesGroupToLowercase","typedPoliciesToString","newEnforcer","newModelFromString","MODEL","StringAdapter","validateGroupingPolicy","RoleEvents","ActionType","transformArrayToPolicy","PermissionEvents","validatePolicy","validateSource"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connect-providers.cjs.js","sources":["../../src/providers/connect-providers.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 AuditorService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\nimport {\n Enforcer,\n newEnforcer,\n newModelFromString,\n StringAdapter,\n} from 'casbin';\n\nimport type {\n RBACProvider,\n RBACProviderConnection,\n} from '@backstage-community/plugin-rbac-node';\n\nimport {\n ActionType,\n ConditionEvents,\n PermissionEvents,\n RoleEvents,\n} from '../auditor/auditor';\nimport { RoleMetadataStorage } from '../database/role-metadata';\nimport {\n transformArrayToPolicy,\n transformRolesGroupToLowercase,\n typedPoliciesToString,\n} from '../helper';\nimport { EnforcerDelegate } from '../service/enforcer-delegate';\nimport { MODEL } from '../service/permission-model';\nimport {\n validateGroupingPolicy,\n validatePolicy,\n validateSource,\n} from '../validation/policies-validation';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport {\n PermissionInfo,\n RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\nimport { isEqual } from 'lodash';\n\nexport class Connection implements RBACProviderConnection {\n constructor(\n private readonly id: string,\n private readonly enforcer: EnforcerDelegate,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly conditionStorage: ConditionalStorage,\n private readonly logger: LoggerService,\n private readonly auditor: AuditorService,\n ) {}\n\n async applyRoles(roles: string[][]): Promise<void> {\n const lowercasedRoles = transformRolesGroupToLowercase(roles);\n const stringPolicy = typedPoliciesToString(lowercasedRoles, 'g');\n const providerRolesforRemoval: string[][] = [];\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new StringAdapter(stringPolicy),\n );\n\n const providerRoles = await this.getProviderRoles();\n\n await this.enforcer.loadPolicy();\n // Get the roles for this provider coming from rbac plugin\n for (const providerRole of providerRoles) {\n providerRolesforRemoval.push(\n ...(await this.enforcer.getFilteredGroupingPolicy(1, providerRole)),\n );\n }\n\n // Remove role\n // role exists in rbac but does not exist in provider\n await this.removeRoles(providerRolesforRemoval, tempEnforcer);\n\n // Add the role\n // role exists in provider but does not exist in rbac\n await this.addRoles(lowercasedRoles);\n }\n\n async applyPermissions(permissions: string[][]): Promise<void> {\n const stringPolicy = typedPoliciesToString(permissions, 'p');\n\n const providerPermissions: string[][] = [];\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new StringAdapter(stringPolicy),\n );\n\n const providerRoles = await this.getProviderRoles();\n\n await this.enforcer.loadPolicy();\n // Get the roles for this provider coming from rbac plugin\n for (const providerRole of providerRoles) {\n providerPermissions.push(\n ...(await this.enforcer.getFilteredPolicy(0, providerRole)),\n );\n }\n\n await this.removePermissions(providerPermissions, tempEnforcer);\n\n await this.addPermissions(permissions);\n }\n\n async applyConditionalPermissions(\n conditionalPermissions: RoleConditionalPolicyDecision<PermissionInfo>[],\n ): Promise<void> {\n const storedConditionalPermissions =\n await this.conditionStorage.filterConditions();\n\n const conditionsToBeAdded: RoleConditionalPolicyDecision<PermissionInfo>[] =\n conditionalPermissions.filter(\n conditionalPermission =>\n !storedConditionalPermissions.some(\n stored =>\n conditionalPermission.roleEntityRef === stored.roleEntityRef &&\n conditionalPermission.pluginId === stored.pluginId &&\n conditionalPermission.resourceType === stored.resourceType &&\n isEqual(\n conditionalPermission.permissionMapping,\n stored.permissionMapping,\n ) &&\n isEqual(conditionalPermission.conditions, stored.conditions),\n ),\n );\n\n // Updated policies fails the 'some' check due to permissionMapping differences\n const conditionsToBeRemoved: RoleConditionalPolicyDecision<PermissionInfo>[] =\n storedConditionalPermissions.filter(\n stored =>\n !conditionalPermissions.some(\n conditionalPermission =>\n stored.roleEntityRef === conditionalPermission.roleEntityRef &&\n stored.pluginId === conditionalPermission.pluginId &&\n stored.resourceType === conditionalPermission.resourceType &&\n isEqual(\n stored.permissionMapping,\n conditionalPermission.permissionMapping,\n ) &&\n isEqual(stored.conditions, conditionalPermission.conditions),\n ),\n );\n\n await this.removeConditionalPermissions(conditionsToBeRemoved);\n\n await this.addConditionalPermissions(conditionsToBeAdded);\n }\n\n private async addRoles(roles: string[][]): Promise<void> {\n for (const role of roles) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n role[1],\n );\n const err = await validateGroupingPolicy(role, metadata, this.id);\n\n if (err) {\n this.logger.warn(err.message);\n continue; // Skip adding this role as there was an error\n }\n\n let roleMeta = await this.roleMetadataStorage.findRoleMetadata(role[1]);\n // role does not exist in rbac, create the metadata for it\n if (!roleMeta) {\n roleMeta = {\n modifiedBy: this.id,\n source: this.id,\n roleEntityRef: role[1],\n };\n }\n\n const auditorMeta = {\n ...roleMeta,\n members: [role[0]],\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: RoleEvents.ROLE_WRITE,\n severityLevel: 'medium',\n meta: {\n actionType: roleMeta ? ActionType.UPDATE : ActionType.CREATE,\n source: auditorMeta.source,\n },\n });\n\n try {\n await this.enforcer.addGroupingPolicy(role, roleMeta);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n }\n\n private async removeRoles(\n providerRoles: string[][],\n tempEnforcer: Enforcer,\n ): Promise<void> {\n // Remove role\n // role exists in rbac but does not exist in provider\n const lowercasedProviderRoles =\n transformRolesGroupToLowercase(providerRoles);\n for (const role of lowercasedProviderRoles) {\n if (!(await tempEnforcer.hasGroupingPolicy(...role))) {\n const roleMeta = await this.roleMetadataStorage.findRoleMetadata(\n role[1],\n );\n\n const currentRole = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n role[1],\n );\n\n if (!roleMeta) {\n this.logger.warn('role does not exist');\n continue;\n }\n\n const singleRole = roleMeta && currentRole.length === 1;\n const actionType = singleRole ? ActionType.DELETE : ActionType.UPDATE;\n\n const auditorMeta = { ...roleMeta, members: [role[0]] };\n const auditorEvent = await this.auditor.createEvent({\n eventId: RoleEvents.ROLE_WRITE,\n severityLevel: 'medium',\n meta: { actionType, source: roleMeta.source },\n });\n\n try {\n await this.enforcer.removeGroupingPolicy(\n role,\n roleMeta,\n actionType === ActionType.UPDATE,\n );\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n }\n\n private async addPermissions(permissions: string[][]): Promise<void> {\n for (const permission of permissions) {\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n if (permission[1] === 'policy-entity' && permission[2] === 'create') {\n this.logger.warn(\n `Permission policy with resource type 'policy-entity' and action 'create' has been removed. Please consider updating policy ${permission} to use 'policy.entity.create' instead of 'policy-entity' from source ${this.id}`,\n );\n }\n\n if (!(await this.enforcer.hasPolicy(...permission))) {\n const transformedPolicy = transformArrayToPolicy(permission);\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n permission[0],\n );\n\n const auditorMeta = {\n policies: [permission],\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: PermissionEvents.POLICY_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.CREATE, source: this.id },\n });\n\n let err = validatePolicy(transformedPolicy);\n if (err) {\n auditorEvent.fail({ error: err, meta: auditorMeta });\n continue; // Skip this invalid permission policy\n }\n\n err = await validateSource(this.id, metadata);\n if (err) {\n auditorEvent.fail({ error: err, meta: auditorMeta });\n continue;\n }\n\n try {\n await this.enforcer.addPolicy(permission);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({ error, meta: auditorMeta });\n }\n }\n }\n }\n\n private async removePermissions(\n providerPermissions: string[][],\n tempEnforcer: Enforcer,\n ): Promise<void> {\n for (const permission of providerPermissions) {\n if (!(await tempEnforcer.hasPolicy(...permission))) {\n const auditorMeta = {\n policies: [permission],\n };\n const auditorEvent = await this.auditor?.createEvent({\n eventId: PermissionEvents.POLICY_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.DELETE, source: this.id },\n });\n\n try {\n await this.enforcer.removePolicy(permission);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n }\n\n private async addConditionalPermissions(\n conditionalPermissions: RoleConditionalPolicyDecision<PermissionInfo>[],\n ): Promise<void> {\n for (const condition of conditionalPermissions) {\n const auditorMeta = {\n policies: [condition],\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: ConditionEvents.CONDITION_WRITE,\n severityLevel: 'medium',\n meta: {\n actionType: ActionType.CREATE,\n source: this.id,\n },\n });\n try {\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n condition.roleEntityRef,\n );\n const err = await validateSource(this.id, metadata);\n if (err) {\n throw err;\n }\n await this.conditionStorage.createCondition(condition);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({ error, meta: auditorMeta });\n }\n }\n }\n\n private async removeConditionalPermissions(\n conditionalPermissions: RoleConditionalPolicyDecision<PermissionInfo>[],\n ): Promise<void> {\n for (const conditionalPermission of conditionalPermissions) {\n const auditorMeta = {\n policies: [conditionalPermission],\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: ConditionEvents.CONDITION_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.DELETE, source: this.id },\n });\n try {\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n conditionalPermission.roleEntityRef,\n );\n const err = await validateSource(this.id, metadata);\n if (err) {\n throw err;\n }\n await this.conditionStorage.deleteCondition(conditionalPermission.id);\n await auditorEvent.success({ meta: auditorMeta });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: auditorMeta,\n });\n }\n }\n }\n\n private async getProviderRoles(): Promise<string[]> {\n const currentRoles = await this.roleMetadataStorage.filterRoleMetadata(\n this.id,\n );\n return currentRoles.map(meta => meta.roleEntityRef);\n }\n}\n\nexport async function connectRBACProviders(\n providers: RBACProvider[],\n enforcer: EnforcerDelegate,\n roleMetadataStorage: RoleMetadataStorage,\n conditionStorage: ConditionalStorage,\n logger: LoggerService,\n auditor: AuditorService,\n) {\n await Promise.all(\n providers.map(async provider => {\n try {\n const connection = new Connection(\n provider.getProviderName(),\n enforcer,\n roleMetadataStorage,\n conditionStorage,\n logger,\n auditor,\n );\n return provider.connect(connection);\n } catch (error) {\n throw new Error(\n `Unable to connect provider ${provider.getProviderName()}, ${error}`,\n );\n }\n }),\n );\n}\n"],"names":["transformRolesGroupToLowercase","typedPoliciesToString","newEnforcer","newModelFromString","MODEL","StringAdapter","isEqual","validateGroupingPolicy","RoleEvents","ActionType","transformArrayToPolicy","PermissionEvents","validatePolicy","validateSource","ConditionEvents"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ var memberList = require('./member-list.cjs.js');
|
|
|
5
5
|
var ancestorSearchFactory = require('./ancestor-search-factory.cjs.js');
|
|
6
6
|
|
|
7
7
|
class BackstageRoleManager {
|
|
8
|
-
constructor(catalogApi, logger, catalogDBClient, rbacDBClient, config, auth) {
|
|
8
|
+
constructor(catalogApi, logger, catalogDBClient, rbacDBClient, config, auth, defaultPermissionReader) {
|
|
9
9
|
this.catalogApi = catalogApi;
|
|
10
10
|
this.logger = logger;
|
|
11
11
|
this.catalogDBClient = catalogDBClient;
|
|
@@ -15,6 +15,7 @@ class BackstageRoleManager {
|
|
|
15
15
|
this.allRoles = /* @__PURE__ */ new Map();
|
|
16
16
|
const rbacConfig = this.config.getOptionalConfig("permission.rbac");
|
|
17
17
|
this.maxDepth = rbacConfig?.getOptionalNumber("maxDepth");
|
|
18
|
+
this.defaultRoleRef = defaultPermissionReader.readRole();
|
|
18
19
|
if (this.maxDepth !== undefined && this.maxDepth < 0) {
|
|
19
20
|
throw new Error(
|
|
20
21
|
"Max Depth for RBAC group hierarchy must be greater than or equal to zero"
|
|
@@ -23,6 +24,7 @@ class BackstageRoleManager {
|
|
|
23
24
|
}
|
|
24
25
|
allRoles;
|
|
25
26
|
maxDepth;
|
|
27
|
+
defaultRoleRef;
|
|
26
28
|
/**
|
|
27
29
|
* clear clears all stored data and resets the role manager to the initial state.
|
|
28
30
|
*/
|
|
@@ -187,7 +189,9 @@ class BackstageRoleManager {
|
|
|
187
189
|
memo.getNodes(),
|
|
188
190
|
this.rbacDBClient
|
|
189
191
|
);
|
|
190
|
-
|
|
192
|
+
const roles = currentRole.getRoles();
|
|
193
|
+
if (this.defaultRoleRef) roles.push(this.defaultRoleRef);
|
|
194
|
+
return Promise.resolve(roles);
|
|
191
195
|
}
|
|
192
196
|
const allRoles = [];
|
|
193
197
|
for (const value of this.allRoles.values()) {
|
|
@@ -195,6 +199,7 @@ class BackstageRoleManager {
|
|
|
195
199
|
allRoles.push(value.name);
|
|
196
200
|
}
|
|
197
201
|
}
|
|
202
|
+
if (this.defaultRoleRef) allRoles.push(this.defaultRoleRef);
|
|
198
203
|
return Promise.resolve(allRoles);
|
|
199
204
|
}
|
|
200
205
|
return [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-manager.cjs.js","sources":["../../src/role-manager/role-manager.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 { AuthService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport type { Config } from '@backstage/config';\n\nimport { RoleManager } from 'casbin';\nimport { Knex } from 'knex';\n\nimport { AncestorSearchMemo, ASMGroup } from './ancestor-search-memo';\nimport { RoleMemberList } from './member-list';\nimport { AncestorSearchFactory } from './ancestor-search-factory';\n\nexport class BackstageRoleManager implements RoleManager {\n private allRoles: Map<string, RoleMemberList>;\n private maxDepth?: number;\n constructor(\n private readonly catalogApi: CatalogApi,\n private readonly logger: LoggerService,\n private readonly catalogDBClient: Knex,\n private readonly rbacDBClient: Knex,\n private readonly config: Config,\n private readonly auth: AuthService,\n ) {\n this.allRoles = new Map<string, RoleMemberList>();\n const rbacConfig = this.config.getOptionalConfig('permission.rbac');\n this.maxDepth = rbacConfig?.getOptionalNumber('maxDepth');\n if (this.maxDepth !== undefined && this.maxDepth! < 0) {\n throw new Error(\n 'Max Depth for RBAC group hierarchy must be greater than or equal to zero',\n );\n }\n }\n\n /**\n * clear clears all stored data and resets the role manager to the initial state.\n */\n async clear(): Promise<void> {\n // do nothing\n }\n\n /**\n * addLink adds the inheritance link between name1 and role: name2.\n * aka name1 inherits role: name2.\n * The link that is established is based on the defined grouping policies that are added by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be assigned to a role.\n * @param name2 The role that will be created or updated.\n * @param _domain Unimplemented prefix to the role.\n */\n async addLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.addMember(name1);\n }\n }\n\n /**\n * deleteLink deletes the inheritance link between name1 and role: name2.\n * aka name1 does not inherit role: name2 any more.\n * The link that is deleted is based on the defined grouping policies that are removed by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be removed from assignment of a role.\n * @param name2 The role that will be deleted or updated.\n * @param _domain Unimplemented.\n */\n async deleteLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.deleteMember(name1);\n\n // Clean up in the event that there are no more members in the role\n if (role1.getMembers().length === 0) {\n this.allRoles.delete(name2);\n }\n }\n }\n\n /**\n * hasLink determines whether name1 inherits role: name2.\n * Before this check is called in the background by the enforcer,\n * we filter out all roles that the user is not connected to\n * directly or indirectly through the use of retrieving roles through\n * enforcer.getRolesForUser and apply those roles to a tempEnforcer.\n *\n * This means that hasLink will almost always be true in the event that a user\n * is assigned to a role (either directly or indirectly)\n *\n * In the event that a user or group is not assigned to a role and instead\n * are assigned directly to permissions, then name2 will become either that\n * user or group through the filtering. In this case we will build the graph\n * if necessary for name2 group presence or evaulate based on the names matching.\n * @param name1 The user that we are authorizing.\n * @param name2 The name of the role that we are checking against.\n * @param domain Unimplemented.\n * @returns True if the user is directly or indirectly attached to the role.\n */\n async hasLink(\n name1: string,\n name2: string,\n ...domain: string[]\n ): Promise<boolean> {\n if (domain.length > 0) {\n throw new Error('domain argument is not supported.');\n }\n\n // Name2 can be an empty string in the event that there is not a role associated with the user\n // This happens because of the filtering of the roles reduces the number of roles that we iterate through.\n if (name2.length === 0) {\n return false;\n }\n\n if (name1 === name2) {\n return true;\n }\n\n // name1 is always user in our case.\n // name2 is user or group.\n // user(name1) couldn't inherit user(name2).\n // We can use this fact for optimization.\n const { kind } = parseEntityRef(name2);\n if (kind.toLocaleLowerCase() === 'user') {\n return false;\n }\n\n // if it is a group, then we will have to build the graph,\n if (kind.toLocaleLowerCase() === 'group') {\n const memo = await AncestorSearchFactory.createAncestorSearchMemo(\n name1,\n this.config,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n\n await memo.buildUserGraph();\n memo.debugNodesAndEdges(this.logger, name1);\n\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n return false;\n }\n\n return memo.hasEntityRef(name2);\n }\n\n return true;\n }\n\n /**\n * syncedHasLink determines whether role: name1 inherits role: name2.\n * domain is a prefix to the roles.\n */\n syncedHasLink?(\n _name1: string,\n _name2: string,\n ..._domain: string[]\n ): boolean {\n throw new Error('Method \"syncedHasLink\" not implemented.');\n }\n\n /**\n * getRoles gets the roles that a subject inherits.\n *\n * name - is a string entity reference, for example: user:default/tom, role:default/dev,\n * so format is <kind>:<namespace>/<entity-name>.\n * GetRoles method supports only two kind values: 'user' and 'role'.\n *\n * domain - is a prefix to the roles, unused parameter.\n *\n * If name's kind === 'user' we return all inherited roles from groups and roles directly assigned to the user.\n * if name's kind === 'role' we return empty array, because we don't support role inheritance.\n * Case kind === 'group' - should not happen, because:\n * 1) Method getRoles returns only role entity references, so casbin engine doesn't call this\n * method again to ask about name with kind \"group\".\n * 2) We implemented getRoles method only to use:\n * 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * so name argument can be only with kind 'user' or 'role'.\n *\n * Info: when we call 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * then casbin engine executes 'getRoles' method few times.\n * Firstly casbin asks about roles for 'userEntityRef'.\n * Let's imagine, that 'getRoles' returned two roles for userEntityRef.\n * Then casbin calls 'getRoles' two more times to\n * find parent roles. But we return empty array for each such call,\n * because we don't support role inheritance and we notify casbin about end of the role sub-tree.\n */\n async getRoles(name: string, ..._domain: string[]): Promise<string[]> {\n const { kind } = parseEntityRef(name);\n if (kind === 'user') {\n const memo = await AncestorSearchFactory.createAncestorSearchMemo(\n name,\n this.config,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n await memo.buildUserGraph();\n memo.debugNodesAndEdges(this.logger, name);\n\n // Account for the user not being in the graph (this can happen during direct assignment to roles)\n memo.setNode(name);\n\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n return Promise.resolve([]);\n }\n\n if (this.isPGClient()) {\n const currentRole = new RoleMemberList(name);\n await currentRole.buildRoles(\n currentRole,\n memo.getNodes(),\n this.rbacDBClient,\n );\n return Promise.resolve(currentRole.getRoles());\n }\n\n const allRoles: string[] = [];\n for (const value of this.allRoles.values()) {\n if (this.hasMember(value, memo)) {\n allRoles.push(value.name);\n }\n }\n\n return Promise.resolve(allRoles);\n }\n\n return [];\n }\n\n /**\n * getUsers gets the users that inherits a subject.\n * domain is an unreferenced parameter here, may be used in other implementations.\n */\n async getUsers(_name: string, ..._domain: string[]): Promise<string[]> {\n throw new Error('Method \"getUsers\" not implemented.');\n }\n\n /**\n * printRoles prints all the roles to log.\n */\n async printRoles(): Promise<void> {\n // do nothing\n }\n\n /**\n * getOrCreateRole will get a role if it has already been cached\n * or it will create a new role to be cached.\n * This cache is a simple tree that is used to quickly compare\n * users and groups to roles.\n * @param name The user or group whose cache we will be getting / creating.\n * @returns The cached role as a RoleList.\n */\n private getOrCreateRole(name: string): RoleMemberList {\n const role = this.allRoles.get(name);\n if (role) {\n return role;\n }\n const newRole = new RoleMemberList(name);\n this.allRoles.set(name, newRole);\n\n return newRole;\n }\n\n /**\n * isPGClient checks what the current database client is at them time.\n * This is to ensure that we are querying the database in the event of postgres\n * or using in memory cache for better sqlite3.\n * @returns True if the database client is pg.\n */\n isPGClient(): boolean {\n const client = this.rbacDBClient.client.config.client;\n return client === 'pg';\n }\n\n /**\n * hasMember checks if the members from a particular role is associated with the user\n * that the AncestorSearchMemo graph is built for.\n * @param role The role that we are getting the members from.\n * @param memo The user graph that we are comparing members with.\n * @returns True if a member from the role is also associated with the user.\n */\n private hasMember(\n role: RoleMemberList | undefined,\n memo: AncestorSearchMemo<ASMGroup>,\n ): boolean {\n if (role === undefined) {\n return false;\n }\n\n for (const member of role.getMembers()) {\n if (memo.hasEntityRef(member)) {\n return true;\n }\n }\n return false;\n }\n}\n"],"names":["parseEntityRef","AncestorSearchFactory","RoleMemberList"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"role-manager.cjs.js","sources":["../../src/role-manager/role-manager.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 { AuthService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport type { Config } from '@backstage/config';\n\nimport { RoleManager } from 'casbin';\nimport { Knex } from 'knex';\n\nimport { AncestorSearchMemo, ASMGroup } from './ancestor-search-memo';\nimport { RoleMemberList } from './member-list';\nimport { AncestorSearchFactory } from './ancestor-search-factory';\nimport { DefaultPermissionsReader } from '../default-permissions/default-permissions';\n\nexport class BackstageRoleManager implements RoleManager {\n private allRoles: Map<string, RoleMemberList>;\n private maxDepth?: number;\n private defaultRoleRef?: string;\n constructor(\n private readonly catalogApi: CatalogApi,\n private readonly logger: LoggerService,\n private readonly catalogDBClient: Knex,\n private readonly rbacDBClient: Knex,\n private readonly config: Config,\n private readonly auth: AuthService,\n defaultPermissionReader: DefaultPermissionsReader,\n ) {\n this.allRoles = new Map<string, RoleMemberList>();\n const rbacConfig = this.config.getOptionalConfig('permission.rbac');\n this.maxDepth = rbacConfig?.getOptionalNumber('maxDepth');\n this.defaultRoleRef = defaultPermissionReader.readRole();\n if (this.maxDepth !== undefined && this.maxDepth! < 0) {\n throw new Error(\n 'Max Depth for RBAC group hierarchy must be greater than or equal to zero',\n );\n }\n }\n\n /**\n * clear clears all stored data and resets the role manager to the initial state.\n */\n async clear(): Promise<void> {\n // do nothing\n }\n\n /**\n * addLink adds the inheritance link between name1 and role: name2.\n * aka name1 inherits role: name2.\n * The link that is established is based on the defined grouping policies that are added by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be assigned to a role.\n * @param name2 The role that will be created or updated.\n * @param _domain Unimplemented prefix to the role.\n */\n async addLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.addMember(name1);\n }\n }\n\n /**\n * deleteLink deletes the inheritance link between name1 and role: name2.\n * aka name1 does not inherit role: name2 any more.\n * The link that is deleted is based on the defined grouping policies that are removed by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be removed from assignment of a role.\n * @param name2 The role that will be deleted or updated.\n * @param _domain Unimplemented.\n */\n async deleteLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.deleteMember(name1);\n\n // Clean up in the event that there are no more members in the role\n if (role1.getMembers().length === 0) {\n this.allRoles.delete(name2);\n }\n }\n }\n\n /**\n * hasLink determines whether name1 inherits role: name2.\n * Before this check is called in the background by the enforcer,\n * we filter out all roles that the user is not connected to\n * directly or indirectly through the use of retrieving roles through\n * enforcer.getRolesForUser and apply those roles to a tempEnforcer.\n *\n * This means that hasLink will almost always be true in the event that a user\n * is assigned to a role (either directly or indirectly)\n *\n * In the event that a user or group is not assigned to a role and instead\n * are assigned directly to permissions, then name2 will become either that\n * user or group through the filtering. In this case we will build the graph\n * if necessary for name2 group presence or evaulate based on the names matching.\n * @param name1 The user that we are authorizing.\n * @param name2 The name of the role that we are checking against.\n * @param domain Unimplemented.\n * @returns True if the user is directly or indirectly attached to the role.\n */\n async hasLink(\n name1: string,\n name2: string,\n ...domain: string[]\n ): Promise<boolean> {\n if (domain.length > 0) {\n throw new Error('domain argument is not supported.');\n }\n\n // Name2 can be an empty string in the event that there is not a role associated with the user\n // This happens because of the filtering of the roles reduces the number of roles that we iterate through.\n if (name2.length === 0) {\n return false;\n }\n\n if (name1 === name2) {\n return true;\n }\n\n // name1 is always user in our case.\n // name2 is user or group.\n // user(name1) couldn't inherit user(name2).\n // We can use this fact for optimization.\n const { kind } = parseEntityRef(name2);\n if (kind.toLocaleLowerCase() === 'user') {\n return false;\n }\n\n // if it is a group, then we will have to build the graph,\n if (kind.toLocaleLowerCase() === 'group') {\n const memo = await AncestorSearchFactory.createAncestorSearchMemo(\n name1,\n this.config,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n\n await memo.buildUserGraph();\n memo.debugNodesAndEdges(this.logger, name1);\n\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n return false;\n }\n\n return memo.hasEntityRef(name2);\n }\n\n return true;\n }\n\n /**\n * syncedHasLink determines whether role: name1 inherits role: name2.\n * domain is a prefix to the roles.\n */\n syncedHasLink?(\n _name1: string,\n _name2: string,\n ..._domain: string[]\n ): boolean {\n throw new Error('Method \"syncedHasLink\" not implemented.');\n }\n\n /**\n * getRoles gets the roles that a subject inherits.\n *\n * name - is a string entity reference, for example: user:default/tom, role:default/dev,\n * so format is <kind>:<namespace>/<entity-name>.\n * GetRoles method supports only two kind values: 'user' and 'role'.\n *\n * domain - is a prefix to the roles, unused parameter.\n *\n * If name's kind === 'user' we return all inherited roles from groups and roles directly assigned to the user.\n * if name's kind === 'role' we return empty array, because we don't support role inheritance.\n * Case kind === 'group' - should not happen, because:\n * 1) Method getRoles returns only role entity references, so casbin engine doesn't call this\n * method again to ask about name with kind \"group\".\n * 2) We implemented getRoles method only to use:\n * 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * so name argument can be only with kind 'user' or 'role'.\n *\n * Info: when we call 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * then casbin engine executes 'getRoles' method few times.\n * Firstly casbin asks about roles for 'userEntityRef'.\n * Let's imagine, that 'getRoles' returned two roles for userEntityRef.\n * Then casbin calls 'getRoles' two more times to\n * find parent roles. But we return empty array for each such call,\n * because we don't support role inheritance and we notify casbin about end of the role sub-tree.\n */\n async getRoles(name: string, ..._domain: string[]): Promise<string[]> {\n const { kind } = parseEntityRef(name);\n if (kind === 'user') {\n const memo = await AncestorSearchFactory.createAncestorSearchMemo(\n name,\n this.config,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n await memo.buildUserGraph();\n memo.debugNodesAndEdges(this.logger, name);\n\n // Account for the user not being in the graph (this can happen during direct assignment to roles)\n memo.setNode(name);\n\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n return Promise.resolve([]);\n }\n\n if (this.isPGClient()) {\n const currentRole = new RoleMemberList(name);\n await currentRole.buildRoles(\n currentRole,\n memo.getNodes(),\n this.rbacDBClient,\n );\n const roles = currentRole.getRoles();\n if (this.defaultRoleRef) roles.push(this.defaultRoleRef);\n return Promise.resolve(roles);\n }\n\n const allRoles: string[] = [];\n for (const value of this.allRoles.values()) {\n if (this.hasMember(value, memo)) {\n allRoles.push(value.name);\n }\n }\n\n if (this.defaultRoleRef) allRoles.push(this.defaultRoleRef);\n return Promise.resolve(allRoles);\n }\n\n return [];\n }\n\n /**\n * getUsers gets the users that inherits a subject.\n * domain is an unreferenced parameter here, may be used in other implementations.\n */\n async getUsers(_name: string, ..._domain: string[]): Promise<string[]> {\n throw new Error('Method \"getUsers\" not implemented.');\n }\n\n /**\n * printRoles prints all the roles to log.\n */\n async printRoles(): Promise<void> {\n // do nothing\n }\n\n /**\n * getOrCreateRole will get a role if it has already been cached\n * or it will create a new role to be cached.\n * This cache is a simple tree that is used to quickly compare\n * users and groups to roles.\n * @param name The user or group whose cache we will be getting / creating.\n * @returns The cached role as a RoleList.\n */\n private getOrCreateRole(name: string): RoleMemberList {\n const role = this.allRoles.get(name);\n if (role) {\n return role;\n }\n const newRole = new RoleMemberList(name);\n this.allRoles.set(name, newRole);\n\n return newRole;\n }\n\n /**\n * isPGClient checks what the current database client is at them time.\n * This is to ensure that we are querying the database in the event of postgres\n * or using in memory cache for better sqlite3.\n * @returns True if the database client is pg.\n */\n isPGClient(): boolean {\n const client = this.rbacDBClient.client.config.client;\n return client === 'pg';\n }\n\n /**\n * hasMember checks if the members from a particular role is associated with the user\n * that the AncestorSearchMemo graph is built for.\n * @param role The role that we are getting the members from.\n * @param memo The user graph that we are comparing members with.\n * @returns True if a member from the role is also associated with the user.\n */\n private hasMember(\n role: RoleMemberList | undefined,\n memo: AncestorSearchMemo<ASMGroup>,\n ): boolean {\n if (role === undefined) {\n return false;\n }\n\n for (const member of role.getMembers()) {\n if (memo.hasEntityRef(member)) {\n return true;\n }\n }\n return false;\n }\n}\n"],"names":["parseEntityRef","AncestorSearchFactory","RoleMemberList"],"mappings":"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"}
|
|
@@ -53,6 +53,15 @@ class PoliciesServer {
|
|
|
53
53
|
async serve() {
|
|
54
54
|
const router$1 = await router.createRouter(this.options);
|
|
55
55
|
const { logger, auditor, auth, permissionsRegistry } = this.options;
|
|
56
|
+
const defRoleMeta = this.roleMetadata.getCachedDefaultRoleMetadata();
|
|
57
|
+
let defRole;
|
|
58
|
+
if (defRoleMeta) {
|
|
59
|
+
defRole = {
|
|
60
|
+
name: defRoleMeta.roleEntityRef,
|
|
61
|
+
memberReferences: [],
|
|
62
|
+
metadata: roleMetadata.daoToMetadata(defRoleMeta)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
56
65
|
const isPluginEnabled = this.options.config.getOptionalBoolean("permission.enabled");
|
|
57
66
|
if (!isPluginEnabled) {
|
|
58
67
|
return router$1;
|
|
@@ -285,6 +294,9 @@ class PoliciesServer {
|
|
|
285
294
|
}
|
|
286
295
|
const roles = await this.enforcer.getGroupingPolicy();
|
|
287
296
|
const body = await this.transformRoleArray(conditionsFilter, ...roles);
|
|
297
|
+
if (defRole) {
|
|
298
|
+
body.push(defRole);
|
|
299
|
+
}
|
|
288
300
|
response.json(body);
|
|
289
301
|
}
|
|
290
302
|
);
|
|
@@ -302,11 +314,16 @@ class PoliciesServer {
|
|
|
302
314
|
conditionsFilter = transformConditions(decision.conditions);
|
|
303
315
|
}
|
|
304
316
|
const roleEntityRef = this.getEntityReference(request, true);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
317
|
+
let body;
|
|
318
|
+
if (defRole && roleEntityRef === defRole.name) {
|
|
319
|
+
body = [defRole];
|
|
320
|
+
} else {
|
|
321
|
+
const role = await this.enforcer.getFilteredGroupingPolicy(
|
|
322
|
+
1,
|
|
323
|
+
roleEntityRef
|
|
324
|
+
);
|
|
325
|
+
body = await this.transformRoleArray(conditionsFilter, ...role);
|
|
326
|
+
}
|
|
310
327
|
if (body.length !== 0) {
|
|
311
328
|
response.json(body);
|
|
312
329
|
} else {
|
|
@@ -430,7 +447,7 @@ class PoliciesServer {
|
|
|
430
447
|
if (err) {
|
|
431
448
|
throw new errors.NotAllowedError(`Unable to edit role: ${err.message}`);
|
|
432
449
|
}
|
|
433
|
-
if (!helper.matches(oldMetadata, conditionsFilter)) {
|
|
450
|
+
if (!helper.matches(roleMetadata.daoToMetadata(oldMetadata), conditionsFilter)) {
|
|
434
451
|
throw new errors.NotAllowedError();
|
|
435
452
|
}
|
|
436
453
|
if (lodash.isEqual(oldRole, newRole) && helper.deepSortedEqual(oldMetadata, newMetadata, [
|
|
@@ -512,7 +529,7 @@ class PoliciesServer {
|
|
|
512
529
|
}
|
|
513
530
|
const roleEntityRef = this.getEntityReference(request, true);
|
|
514
531
|
const currentMetadata = await this.roleMetadata.findRoleMetadata(roleEntityRef);
|
|
515
|
-
if (!helper.matches(currentMetadata, conditionsFilter)) {
|
|
532
|
+
if (!currentMetadata || !helper.matches(roleMetadata.daoToMetadata(currentMetadata), conditionsFilter)) {
|
|
516
533
|
throw new errors.NotAllowedError();
|
|
517
534
|
}
|
|
518
535
|
const err = await policiesValidation.validateSource("rest", currentMetadata);
|
|
@@ -682,10 +699,10 @@ class PoliciesServer {
|
|
|
682
699
|
...condition,
|
|
683
700
|
permissionMapping: condition.permissionMapping.map((pm) => pm.action)
|
|
684
701
|
};
|
|
685
|
-
const roleMetadata = await this.roleMetadata.findRoleMetadata(
|
|
702
|
+
const roleMetadata$1 = await this.roleMetadata.findRoleMetadata(
|
|
686
703
|
conditionToDelete.roleEntityRef
|
|
687
704
|
);
|
|
688
|
-
if (!helper.matches(roleMetadata, conditionsFilter)) {
|
|
705
|
+
if (!roleMetadata$1 || !helper.matches(roleMetadata.daoToMetadata(roleMetadata$1), conditionsFilter)) {
|
|
689
706
|
throw new errors.NotAllowedError();
|
|
690
707
|
}
|
|
691
708
|
await this.conditionalStorage.deleteCondition(id);
|
|
@@ -714,10 +731,10 @@ class PoliciesServer {
|
|
|
714
731
|
if (!condition) {
|
|
715
732
|
throw new errors.NotFoundError(`Condition with id ${id} was not found`);
|
|
716
733
|
}
|
|
717
|
-
const roleMetadata = await this.roleMetadata.findRoleMetadata(
|
|
734
|
+
const roleMetadata$1 = await this.roleMetadata.findRoleMetadata(
|
|
718
735
|
condition.roleEntityRef
|
|
719
736
|
);
|
|
720
|
-
if (!helper.matches(roleMetadata, conditionsFilter)) {
|
|
737
|
+
if (!roleMetadata$1 || !helper.matches(roleMetadata.daoToMetadata(roleMetadata$1), conditionsFilter)) {
|
|
721
738
|
throw new errors.NotAllowedError();
|
|
722
739
|
}
|
|
723
740
|
const roleConditionPolicy = request.body;
|
|
@@ -896,7 +913,7 @@ class PoliciesServer {
|
|
|
896
913
|
const metadata = await this.roleMetadata.findRoleMetadata(
|
|
897
914
|
policy.entityReference
|
|
898
915
|
);
|
|
899
|
-
if (!helper.matches(metadata, filter)) {
|
|
916
|
+
if (!metadata || !helper.matches(roleMetadata.daoToMetadata(metadata), filter)) {
|
|
900
917
|
throw new errors.NotAllowedError();
|
|
901
918
|
}
|
|
902
919
|
let action = errorMessage ? "edit" : "delete";
|