@backstage-community/plugin-rbac-backend 7.9.0 → 7.10.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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @backstage-community/plugin-rbac-backend
2
2
 
3
+ ## 7.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 133eae6: Add support for loading conditional permissions from a remote provider (fix #6412)
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [133eae6]
12
+ - @backstage-community/plugin-rbac-node@1.19.0
13
+
14
+ ## 7.9.1
15
+
16
+ ### Patch Changes
17
+
18
+ - d737494: Backstage version bump to v1.48.5
19
+ - Updated dependencies [d737494]
20
+ - @backstage-community/plugin-rbac-common@1.24.1
21
+ - @backstage-community/plugin-rbac-node@1.18.1
22
+
3
23
  ## 7.9.0
4
24
 
5
25
  ### Minor Changes
@@ -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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"}
@@ -74,6 +74,7 @@ class PolicyBuilder {
74
74
  rbacProviders,
75
75
  enforcerDelegate$1,
76
76
  roleMetadataStorage,
77
+ conditionStorage,
77
78
  env.logger,
78
79
  env.auditor
79
80
  );
@@ -1 +1 @@
1
- {"version":3,"file":"policy-builder.cjs.js","sources":["../../src/service/policy-builder.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DatabaseManager } from '@backstage/backend-defaults/database';\nimport type {\n AuditorService,\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\nimport type { PermissionEvaluator } from '@backstage/plugin-permission-common';\n\nimport { newEnforcer, newModelFromString } from 'casbin';\nimport type { Router } from 'express';\n\nimport type {\n PluginIdProvider,\n RBACProvider,\n} from '@backstage-community/plugin-rbac-node';\n\nimport { CasbinDBAdapterFactory } from '../database/casbin-adapter-factory';\nimport { DataBaseConditionalStorage } from '../database/conditional-storage';\nimport { migrate } from '../database/migration';\nimport { DataBaseRoleMetadataStorage } from '../database/role-metadata';\nimport { AllowAllPolicy } from '../policies/allow-all-policy';\nimport { RBACPermissionPolicy } from '../policies/permission-policy';\nimport { connectRBACProviders } from '../providers/connect-providers';\nimport { BackstageRoleManager } from '../role-manager/role-manager';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { MODEL } from './permission-model';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { PoliciesServer } from './policies-rest-api';\nimport { policyEntityPermissions } from '@backstage-community/plugin-rbac-common';\nimport { rules } from '../permissions';\nimport { permissionMetadataResourceRef } from '../permissions/resource';\nimport { PermissionDependentPluginDatabaseStore } from '../database/extra-permission-enabled-plugins-storage';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\nimport { PolicyExtensionPoint } from '@backstage/plugin-permission-node/alpha';\n\n/**\n * @public\n */\nexport type EnvOptions = {\n config: Config;\n logger: LoggerService;\n discovery: DiscoveryService;\n permissions: PermissionEvaluator;\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n lifecycle: LifecycleService;\n permissionsRegistry: PermissionsRegistryService;\n policy: PolicyExtensionPoint;\n};\n\n/**\n * @public\n */\nexport type RBACRouterOptions = {\n config: Config;\n logger: LoggerService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n auditor: AuditorService;\n};\n\n/**\n * @public\n */\nexport class PolicyBuilder {\n public static async build(\n env: EnvOptions,\n pluginIdProvider: PluginIdProvider = { getPluginIds: () => [] },\n rbacProviders?: Array<RBACProvider>,\n ): Promise<Router> {\n const databaseManager = DatabaseManager.fromConfig(env.config).forPlugin(\n 'permission',\n { logger: env.logger, lifecycle: env.lifecycle },\n );\n\n const databaseClient = await databaseManager.getClient();\n\n const adapter = await new CasbinDBAdapterFactory(\n env.config,\n databaseClient,\n ).createAdapter();\n\n const enf = await newEnforcer(newModelFromString(MODEL), adapter);\n await enf.loadPolicy();\n enf.enableAutoSave(true);\n\n const catalogClient = new CatalogClient({ discoveryApi: env.discovery });\n const catalogDBClient = await DatabaseManager.fromConfig(env.config)\n .forPlugin('catalog', { logger: env.logger, lifecycle: env.lifecycle })\n .getClient();\n\n const rm = new BackstageRoleManager(\n catalogClient,\n env.logger,\n catalogDBClient,\n databaseClient,\n env.config,\n env.auth,\n );\n enf.setRoleManager(rm);\n enf.enableAutoBuildRoleLinks(false);\n await enf.buildRoleLinks();\n\n await migrate(databaseManager);\n\n const conditionStorage = new DataBaseConditionalStorage(databaseClient);\n\n const roleMetadataStorage = new DataBaseRoleMetadataStorage(databaseClient);\n const enforcerDelegate = new EnforcerDelegate(\n enf,\n env.auditor,\n conditionStorage,\n roleMetadataStorage,\n databaseClient,\n );\n\n env.permissionsRegistry.addResourceType({\n resourceRef: permissionMetadataResourceRef,\n getResources: resourceRefs =>\n Promise.all(\n resourceRefs.map(ref => {\n return roleMetadataStorage.findRoleMetadata(ref);\n }),\n ),\n permissions: policyEntityPermissions,\n rules: Object.values(rules),\n });\n\n if (rbacProviders) {\n await connectRBACProviders(\n rbacProviders,\n enforcerDelegate,\n roleMetadataStorage,\n env.logger,\n env.auditor,\n );\n }\n\n const extraPluginsIdStorage = new PermissionDependentPluginDatabaseStore(\n databaseClient,\n );\n const extendablePluginIdProvider = new ExtendablePluginIdProvider(\n extraPluginsIdStorage,\n pluginIdProvider,\n env.config,\n );\n await extendablePluginIdProvider.handleConflictedPluginIds();\n const pluginPermMetaData = new PluginPermissionMetadataCollector({\n deps: {\n discovery: env.discovery,\n pluginIdProvider: extendablePluginIdProvider,\n logger: env.logger,\n config: env.config,\n },\n });\n\n const isPluginEnabled = env.config.getOptionalBoolean('permission.enabled');\n if (isPluginEnabled) {\n env.logger.info('RBAC backend plugin was enabled');\n\n env.policy.setPolicy(\n await RBACPermissionPolicy.build(\n env.logger,\n env.auditor,\n env.config,\n conditionStorage,\n enforcerDelegate,\n roleMetadataStorage,\n databaseClient,\n pluginPermMetaData,\n env.auth,\n ),\n );\n } else {\n env.logger.warn(\n 'RBAC backend plugin was disabled by application config permission.enabled: false',\n );\n\n env.policy.setPolicy(new AllowAllPolicy());\n }\n\n const options: RBACRouterOptions = {\n config: env.config,\n logger: env.logger,\n auth: env.auth,\n httpAuth: env.httpAuth,\n permissions: env.permissions,\n permissionsRegistry: env.permissionsRegistry,\n auditor: env.auditor,\n };\n\n const server = new PoliciesServer(\n options,\n enforcerDelegate,\n conditionStorage,\n pluginPermMetaData,\n roleMetadataStorage,\n extraPluginsIdStorage,\n extendablePluginIdProvider,\n rbacProviders,\n );\n return server.serve();\n }\n}\n"],"names":["DatabaseManager","CasbinDBAdapterFactory","newEnforcer","newModelFromString","MODEL","catalogClient","CatalogClient","BackstageRoleManager","migrate","DataBaseConditionalStorage","DataBaseRoleMetadataStorage","enforcerDelegate","EnforcerDelegate","permissionMetadataResourceRef","policyEntityPermissions","rules","connectRBACProviders","PermissionDependentPluginDatabaseStore","ExtendablePluginIdProvider","PluginPermissionMetadataCollector","RBACPermissionPolicy","AllowAllPolicy","PoliciesServer"],"mappings":"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"}
1
+ {"version":3,"file":"policy-builder.cjs.js","sources":["../../src/service/policy-builder.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DatabaseManager } from '@backstage/backend-defaults/database';\nimport type {\n AuditorService,\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\nimport type { PermissionEvaluator } from '@backstage/plugin-permission-common';\n\nimport { newEnforcer, newModelFromString } from 'casbin';\nimport type { Router } from 'express';\n\nimport type {\n PluginIdProvider,\n RBACProvider,\n} from '@backstage-community/plugin-rbac-node';\n\nimport { CasbinDBAdapterFactory } from '../database/casbin-adapter-factory';\nimport { DataBaseConditionalStorage } from '../database/conditional-storage';\nimport { migrate } from '../database/migration';\nimport { DataBaseRoleMetadataStorage } from '../database/role-metadata';\nimport { AllowAllPolicy } from '../policies/allow-all-policy';\nimport { RBACPermissionPolicy } from '../policies/permission-policy';\nimport { connectRBACProviders } from '../providers/connect-providers';\nimport { BackstageRoleManager } from '../role-manager/role-manager';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { MODEL } from './permission-model';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { PoliciesServer } from './policies-rest-api';\nimport { policyEntityPermissions } from '@backstage-community/plugin-rbac-common';\nimport { rules } from '../permissions';\nimport { permissionMetadataResourceRef } from '../permissions/resource';\nimport { PermissionDependentPluginDatabaseStore } from '../database/extra-permission-enabled-plugins-storage';\nimport { ExtendablePluginIdProvider } from './extendable-id-provider';\nimport { PolicyExtensionPoint } from '@backstage/plugin-permission-node/alpha';\n\n/**\n * @public\n */\nexport type EnvOptions = {\n config: Config;\n logger: LoggerService;\n discovery: DiscoveryService;\n permissions: PermissionEvaluator;\n auth: AuthService;\n httpAuth: HttpAuthService;\n auditor: AuditorService;\n lifecycle: LifecycleService;\n permissionsRegistry: PermissionsRegistryService;\n policy: PolicyExtensionPoint;\n};\n\n/**\n * @public\n */\nexport type RBACRouterOptions = {\n config: Config;\n logger: LoggerService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n auditor: AuditorService;\n};\n\n/**\n * @public\n */\nexport class PolicyBuilder {\n public static async build(\n env: EnvOptions,\n pluginIdProvider: PluginIdProvider = { getPluginIds: () => [] },\n rbacProviders?: Array<RBACProvider>,\n ): Promise<Router> {\n const databaseManager = DatabaseManager.fromConfig(env.config).forPlugin(\n 'permission',\n { logger: env.logger, lifecycle: env.lifecycle },\n );\n\n const databaseClient = await databaseManager.getClient();\n\n const adapter = await new CasbinDBAdapterFactory(\n env.config,\n databaseClient,\n ).createAdapter();\n\n const enf = await newEnforcer(newModelFromString(MODEL), adapter);\n await enf.loadPolicy();\n enf.enableAutoSave(true);\n\n const catalogClient = new CatalogClient({ discoveryApi: env.discovery });\n const catalogDBClient = await DatabaseManager.fromConfig(env.config)\n .forPlugin('catalog', { logger: env.logger, lifecycle: env.lifecycle })\n .getClient();\n\n const rm = new BackstageRoleManager(\n catalogClient,\n env.logger,\n catalogDBClient,\n databaseClient,\n env.config,\n env.auth,\n );\n enf.setRoleManager(rm);\n enf.enableAutoBuildRoleLinks(false);\n await enf.buildRoleLinks();\n\n await migrate(databaseManager);\n\n const conditionStorage = new DataBaseConditionalStorage(databaseClient);\n\n const roleMetadataStorage = new DataBaseRoleMetadataStorage(databaseClient);\n const enforcerDelegate = new EnforcerDelegate(\n enf,\n env.auditor,\n conditionStorage,\n roleMetadataStorage,\n databaseClient,\n );\n\n env.permissionsRegistry.addResourceType({\n resourceRef: permissionMetadataResourceRef,\n getResources: resourceRefs =>\n Promise.all(\n resourceRefs.map(ref => {\n return roleMetadataStorage.findRoleMetadata(ref);\n }),\n ),\n permissions: policyEntityPermissions,\n rules: Object.values(rules),\n });\n\n if (rbacProviders) {\n await connectRBACProviders(\n rbacProviders,\n enforcerDelegate,\n roleMetadataStorage,\n conditionStorage,\n env.logger,\n env.auditor,\n );\n }\n\n const extraPluginsIdStorage = new PermissionDependentPluginDatabaseStore(\n databaseClient,\n );\n const extendablePluginIdProvider = new ExtendablePluginIdProvider(\n extraPluginsIdStorage,\n pluginIdProvider,\n env.config,\n );\n await extendablePluginIdProvider.handleConflictedPluginIds();\n const pluginPermMetaData = new PluginPermissionMetadataCollector({\n deps: {\n discovery: env.discovery,\n pluginIdProvider: extendablePluginIdProvider,\n logger: env.logger,\n config: env.config,\n },\n });\n\n const isPluginEnabled = env.config.getOptionalBoolean('permission.enabled');\n if (isPluginEnabled) {\n env.logger.info('RBAC backend plugin was enabled');\n\n env.policy.setPolicy(\n await RBACPermissionPolicy.build(\n env.logger,\n env.auditor,\n env.config,\n conditionStorage,\n enforcerDelegate,\n roleMetadataStorage,\n databaseClient,\n pluginPermMetaData,\n env.auth,\n ),\n );\n } else {\n env.logger.warn(\n 'RBAC backend plugin was disabled by application config permission.enabled: false',\n );\n\n env.policy.setPolicy(new AllowAllPolicy());\n }\n\n const options: RBACRouterOptions = {\n config: env.config,\n logger: env.logger,\n auth: env.auth,\n httpAuth: env.httpAuth,\n permissions: env.permissions,\n permissionsRegistry: env.permissionsRegistry,\n auditor: env.auditor,\n };\n\n const server = new PoliciesServer(\n options,\n enforcerDelegate,\n conditionStorage,\n pluginPermMetaData,\n roleMetadataStorage,\n extraPluginsIdStorage,\n extendablePluginIdProvider,\n rbacProviders,\n );\n return server.serve();\n }\n}\n"],"names":["DatabaseManager","CasbinDBAdapterFactory","newEnforcer","newModelFromString","MODEL","catalogClient","CatalogClient","BackstageRoleManager","migrate","DataBaseConditionalStorage","DataBaseRoleMetadataStorage","enforcerDelegate","EnforcerDelegate","permissionMetadataResourceRef","policyEntityPermissions","rules","connectRBACProviders","PermissionDependentPluginDatabaseStore","ExtendablePluginIdProvider","PluginPermissionMetadataCollector","RBACPermissionPolicy","AllowAllPolicy","PoliciesServer"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-rbac-backend",
3
- "version": "7.9.0",
3
+ "version": "7.10.0",
4
4
  "main": "dist/index.cjs.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -36,8 +36,8 @@
36
36
  "postpack": "backstage-cli package postpack"
37
37
  },
38
38
  "dependencies": {
39
- "@backstage-community/plugin-rbac-common": "^1.24.0",
40
- "@backstage-community/plugin-rbac-node": "^1.18.0",
39
+ "@backstage-community/plugin-rbac-common": "^1.24.1",
40
+ "@backstage-community/plugin-rbac-node": "^1.19.0",
41
41
  "@backstage/backend-defaults": "^0.15.2",
42
42
  "@backstage/backend-plugin-api": "^1.7.0",
43
43
  "@backstage/catalog-client": "^1.13.0",