@backstage-community/plugin-rbac-backend 5.6.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/admin-permissions/admin-creation.cjs.js +41 -27
  3. package/dist/admin-permissions/admin-creation.cjs.js.map +1 -1
  4. package/dist/auditor/auditor.cjs.js +65 -0
  5. package/dist/auditor/auditor.cjs.js.map +1 -0
  6. package/dist/auditor/rest-interceptor.cjs.js +130 -0
  7. package/dist/auditor/rest-interceptor.cjs.js.map +1 -0
  8. package/dist/file-permissions/csv-file-watcher.cjs.js +90 -92
  9. package/dist/file-permissions/csv-file-watcher.cjs.js.map +1 -1
  10. package/dist/file-permissions/yaml-conditional-file-watcher.cjs.js +40 -51
  11. package/dist/file-permissions/yaml-conditional-file-watcher.cjs.js.map +1 -1
  12. package/dist/helper.cjs.js +22 -19
  13. package/dist/helper.cjs.js.map +1 -1
  14. package/dist/index.d.ts +2 -1
  15. package/dist/plugin.cjs.js +3 -0
  16. package/dist/plugin.cjs.js.map +1 -1
  17. package/dist/policies/permission-policy.cjs.js +32 -70
  18. package/dist/policies/permission-policy.cjs.js.map +1 -1
  19. package/dist/providers/connect-providers.cjs.js +75 -68
  20. package/dist/providers/connect-providers.cjs.js.map +1 -1
  21. package/dist/service/enforcer-delegate.cjs.js +8 -10
  22. package/dist/service/enforcer-delegate.cjs.js.map +1 -1
  23. package/dist/service/policies-rest-api.cjs.js +449 -519
  24. package/dist/service/policies-rest-api.cjs.js.map +1 -1
  25. package/dist/service/policy-builder.cjs.js +4 -10
  26. package/dist/service/policy-builder.cjs.js.map +1 -1
  27. package/package.json +2 -3
  28. package/dist/audit-log/audit-logger.cjs.js +0 -114
  29. package/dist/audit-log/audit-logger.cjs.js.map +0 -1
  30. package/dist/audit-log/rest-errors-interceptor.cjs.js +0 -100
  31. package/dist/audit-log/rest-errors-interceptor.cjs.js.map +0 -1
@@ -3,7 +3,7 @@
3
3
  var casbin = require('casbin');
4
4
  var sync = require('csv-parse/sync');
5
5
  var lodash = require('lodash');
6
- var auditLogger = require('../audit-log/audit-logger.cjs.js');
6
+ var auditor = require('../auditor/auditor.cjs.js');
7
7
  var helper = require('../helper.cjs.js');
8
8
  var permissionModel = require('../service/permission-model.cjs.js');
9
9
  var policiesValidation = require('../validation/policies-validation.cjs.js');
@@ -12,11 +12,11 @@ var lowercaseFileAdapter = require('./lowercase-file-adapter.cjs.js');
12
12
 
13
13
  const CSV_PERMISSION_POLICY_FILE_AUTHOR = "csv permission policy file";
14
14
  class CSVFileWatcher extends fileWatcher.AbstractFileWatcher {
15
- constructor(filePath, allowReload, logger, enforcer, roleMetadataStorage, auditLogger) {
15
+ constructor(filePath, allowReload, logger, enforcer, roleMetadataStorage, auditor) {
16
16
  super(filePath, allowReload, logger);
17
17
  this.enforcer = enforcer;
18
18
  this.roleMetadataStorage = roleMetadataStorage;
19
- this.auditLogger = auditLogger;
19
+ this.auditor = auditor;
20
20
  this.currentContent = [];
21
21
  this.csvFilePolicies = {
22
22
  addedPolicies: [],
@@ -164,23 +164,21 @@ class CSVFileWatcher extends fileWatcher.AbstractFileWatcher {
164
164
  * addPermissionPolicies will add the new permission policies that are present in the CSV file.
165
165
  */
166
166
  async addPermissionPolicies() {
167
+ const auditorEvent = await this.auditor.createEvent({
168
+ eventId: auditor.PermissionEvents.POLICY_WRITE,
169
+ severityLevel: "medium",
170
+ meta: { actionType: auditor.ActionType.CREATE, source: "csv-file" }
171
+ });
167
172
  try {
168
173
  await this.enforcer.addPolicies(this.csvFilePolicies.addedPolicies);
169
- await this.auditLogger.auditLog({
170
- actorId: auditLogger.RBAC_BACKEND,
171
- message: `Created policies`,
172
- eventName: auditLogger.PermissionEvents.CREATE_POLICY,
173
- metadata: {
174
- policies: this.csvFilePolicies.addedPolicies,
175
- source: "csv-file"
176
- },
177
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
178
- status: "succeeded"
174
+ await auditorEvent.success({
175
+ meta: { policies: this.csvFilePolicies.addedPolicies }
179
176
  });
180
177
  } catch (e) {
181
- this.logger.warn(
182
- `Failed to add or update policies ${this.csvFilePolicies.addedPolicies} after modification ${this.filePath}. Cause: ${e}`
183
- );
178
+ await auditorEvent.fail({
179
+ meta: { policies: this.csvFilePolicies.addedPolicies },
180
+ error: e
181
+ });
184
182
  }
185
183
  this.csvFilePolicies.addedPolicies = [];
186
184
  }
@@ -188,25 +186,21 @@ class CSVFileWatcher extends fileWatcher.AbstractFileWatcher {
188
186
  * removePermissionPolicies will remove the permission policies that are no longer present in the CSV file.
189
187
  */
190
188
  async removePermissionPolicies() {
189
+ const auditorEvent = await this.auditor.createEvent({
190
+ eventId: auditor.PermissionEvents.POLICY_WRITE,
191
+ severityLevel: "medium",
192
+ meta: { actionType: auditor.ActionType.DELETE, source: "csv-file" }
193
+ });
191
194
  try {
192
195
  await this.enforcer.removePolicies(this.csvFilePolicies.removedPolicies);
193
- await this.auditLogger.auditLog({
194
- actorId: auditLogger.RBAC_BACKEND,
195
- message: `Deleted policies`,
196
- eventName: auditLogger.PermissionEvents.DELETE_POLICY,
197
- metadata: {
198
- policies: this.csvFilePolicies.removedPolicies,
199
- source: "csv-file"
200
- },
201
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
202
- status: "succeeded"
196
+ await auditorEvent.success({
197
+ meta: { policies: this.csvFilePolicies.removedPolicies }
203
198
  });
204
199
  } catch (e) {
205
- this.logger.warn(
206
- `Failed to remove policies ${JSON.stringify(
207
- this.csvFilePolicies.removedPolicies
208
- )} after modification ${this.filePath}. Cause: ${e}`
209
- );
200
+ await auditorEvent.fail({
201
+ meta: { policies: this.csvFilePolicies.removedPolicies },
202
+ error: e
203
+ });
210
204
  }
211
205
  this.csvFilePolicies.removedPolicies = [];
212
206
  }
@@ -214,47 +208,58 @@ class CSVFileWatcher extends fileWatcher.AbstractFileWatcher {
214
208
  * addRoles will add the new roles that are present in the CSV file.
215
209
  */
216
210
  async addRoles() {
217
- const addedPolicies = [];
218
- const updatedPolicies = [];
211
+ const changedPolicies = {
212
+ addedPolicies: [],
213
+ updatedPolicies: [],
214
+ failedPolicies: []
215
+ };
216
+ const auditorEvent = await this.auditor.createEvent({
217
+ eventId: auditor.RoleEvents.ROLE_WRITE,
218
+ severityLevel: "medium",
219
+ meta: { actionType: auditor.ActionType.CREATE_OR_UPDATE, source: "csv-file" }
220
+ });
219
221
  for (const [key, value] of this.csvFilePolicies.addedGroupPolicies) {
220
222
  const groupPolicies = value.map((member) => {
221
223
  return [member, key];
222
224
  });
225
+ const roleMetadata = {
226
+ source: "csv-file",
227
+ roleEntityRef: key,
228
+ author: CSV_PERMISSION_POLICY_FILE_AUTHOR,
229
+ modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR
230
+ };
223
231
  try {
224
- const roleMetadata = {
225
- source: "csv-file",
226
- roleEntityRef: key,
227
- author: CSV_PERMISSION_POLICY_FILE_AUTHOR,
228
- modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR
229
- };
230
232
  const currentMetadata = await this.roleMetadataStorage.findRoleMetadata(
231
233
  roleMetadata.roleEntityRef
232
234
  );
233
235
  await this.enforcer.addGroupingPolicies(groupPolicies, roleMetadata);
234
- const eventName = currentMetadata ? auditLogger.RoleEvents.UPDATE_ROLE : auditLogger.RoleEvents.CREATE_ROLE;
235
- if (eventName === auditLogger.RoleEvents.UPDATE_ROLE) {
236
- updatedPolicies.push(...groupPolicies);
236
+ if (currentMetadata) {
237
+ changedPolicies.updatedPolicies.push(...groupPolicies);
237
238
  } else {
238
- addedPolicies.push(...groupPolicies);
239
+ changedPolicies.addedPolicies.push(...groupPolicies);
239
240
  }
240
241
  } catch (e) {
241
- this.logger.warn(
242
- `Failed to add or update group policy ${groupPolicies} after modification ${this.filePath}. Cause: ${e}`
243
- );
242
+ changedPolicies.failedPolicies.push({
243
+ error: e,
244
+ policies: groupPolicies
245
+ });
244
246
  }
245
247
  }
246
- if (updatedPolicies.length > 0)
247
- await this.logRoleEvent(
248
- auditLogger.RoleEvents.UPDATE_ROLE,
249
- "Updated roles",
250
- updatedPolicies
251
- );
252
- if (addedPolicies.length > 0)
253
- await this.logRoleEvent(
254
- auditLogger.RoleEvents.CREATE_ROLE,
255
- "Created roles",
256
- addedPolicies
257
- );
248
+ if (changedPolicies.failedPolicies.length > 0) {
249
+ await auditorEvent.fail({
250
+ error: new Error(
251
+ `Failed to add or update group policies after modification ${this.filePath}.`
252
+ ),
253
+ meta: { ...changedPolicies }
254
+ });
255
+ } else {
256
+ await auditorEvent.success({
257
+ meta: {
258
+ addedPolicies: changedPolicies.addedPolicies,
259
+ updatedPolicies: changedPolicies.updatedPolicies
260
+ }
261
+ });
262
+ }
258
263
  this.csvFilePolicies.addedGroupPolicies = /* @__PURE__ */ new Map();
259
264
  }
260
265
  /**
@@ -264,39 +269,42 @@ class CSVFileWatcher extends fileWatcher.AbstractFileWatcher {
264
269
  */
265
270
  async removeRoles() {
266
271
  for (const [key, value] of this.csvFilePolicies.removedGroupPolicies) {
267
- const isUpdate = await this.enforcer.getFilteredGroupingPolicy(1, key);
272
+ const oldGroupingPolicies = await this.enforcer.getFilteredGroupingPolicy(
273
+ 1,
274
+ key
275
+ );
268
276
  const groupPolicies = value.map((member) => {
269
277
  return [member, key];
270
278
  });
279
+ const roleMetadata = {
280
+ source: "csv-file",
281
+ roleEntityRef: key,
282
+ author: CSV_PERMISSION_POLICY_FILE_AUTHOR,
283
+ modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR
284
+ };
285
+ const isUpdate = oldGroupingPolicies.length > 1 && oldGroupingPolicies.length !== groupPolicies.length;
286
+ const actionType = isUpdate ? auditor.ActionType.UPDATE : auditor.ActionType.DELETE;
287
+ const meta = {
288
+ ...roleMetadata,
289
+ members: value
290
+ };
291
+ const auditorEvent = await this.auditor.createEvent({
292
+ eventId: auditor.RoleEvents.ROLE_WRITE,
293
+ severityLevel: "medium",
294
+ meta: { actionType, source: meta.source }
295
+ });
271
296
  try {
272
- const roleMetadata = {
273
- source: "csv-file",
274
- roleEntityRef: key,
275
- author: CSV_PERMISSION_POLICY_FILE_AUTHOR,
276
- modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR
277
- };
278
297
  await this.enforcer.removeGroupingPolicies(
279
298
  groupPolicies,
280
299
  roleMetadata,
281
- isUpdate.length > 1 && isUpdate.length !== groupPolicies.length
300
+ isUpdate
282
301
  );
283
- const isRolePresent = await this.roleMetadataStorage.findRoleMetadata(
284
- roleMetadata.roleEntityRef
285
- );
286
- const eventName = isRolePresent ? auditLogger.RoleEvents.UPDATE_ROLE : auditLogger.RoleEvents.DELETE_ROLE;
287
- const message = isRolePresent ? "Updated role: deleted members" : "Deleted role";
288
- await this.auditLogger.auditLog({
289
- actorId: auditLogger.RBAC_BACKEND,
290
- message,
291
- eventName,
292
- metadata: { ...roleMetadata, members: value },
293
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
294
- status: "succeeded"
295
- });
302
+ await auditorEvent.success({ meta });
296
303
  } catch (e) {
297
- this.logger.warn(
298
- `Failed to remove group policy ${groupPolicies} after modification ${this.filePath}. Cause: ${e}`
299
- );
304
+ await auditorEvent.fail({
305
+ meta,
306
+ error: e
307
+ });
300
308
  }
301
309
  }
302
310
  this.csvFilePolicies.removedGroupPolicies = /* @__PURE__ */ new Map();
@@ -443,16 +451,6 @@ class CSVFileWatcher extends fileWatcher.AbstractFileWatcher {
443
451
  }
444
452
  groupPolicyMap.get(key)?.push(value);
445
453
  }
446
- async logRoleEvent(eventName, message, groupingPolicies) {
447
- await this.auditLogger.auditLog({
448
- actorId: auditLogger.RBAC_BACKEND,
449
- message,
450
- eventName,
451
- metadata: { groupingPolicies, source: "csv-file" },
452
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
453
- status: "succeeded"
454
- });
455
- }
456
454
  }
457
455
 
458
456
  exports.CSVFileWatcher = CSVFileWatcher;
@@ -1 +1 @@
1
- {"version":3,"file":"csv-file-watcher.cjs.js","sources":["../../src/file-permissions/csv-file-watcher.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 { LoggerService } from '@backstage/backend-plugin-api';\n\nimport type { AuditLogger } from '@janus-idp/backstage-plugin-audit-log-node';\nimport { Enforcer, newEnforcer, newModelFromString } from 'casbin';\nimport { parse } from 'csv-parse/sync';\nimport { difference } from 'lodash';\n\nimport {\n HANDLE_RBAC_DATA_STAGE,\n PermissionAuditInfo,\n PermissionEvents,\n RBAC_BACKEND,\n RoleAuditInfo,\n RoleEvents,\n RolesAuditInfo,\n} from '../audit-log/audit-logger';\nimport {\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport {\n mergeRoleMetadata,\n metadataStringToPolicy,\n policyToString,\n transformArrayToPolicy,\n transformPolicyGroupToLowercase,\n} from '../helper';\nimport { EnforcerDelegate } from '../service/enforcer-delegate';\nimport { MODEL } from '../service/permission-model';\nimport {\n checkForDuplicateGroupPolicies,\n checkForDuplicatePolicies,\n validateGroupingPolicy,\n validatePolicy,\n validateSource,\n} from '../validation/policies-validation';\nimport { AbstractFileWatcher } from './file-watcher';\nimport { LowercaseFileAdapter } from './lowercase-file-adapter';\n\nexport const CSV_PERMISSION_POLICY_FILE_AUTHOR = 'csv permission policy file';\n\ntype CSVFilePolicies = {\n addedPolicies: string[][];\n removedPolicies: string[][];\n addedGroupPolicies: Map<string, string[]>;\n removedGroupPolicies: Map<string, string[]>;\n};\n\nexport class CSVFileWatcher extends AbstractFileWatcher<string[][]> {\n private currentContent: string[][];\n private csvFilePolicies: CSVFilePolicies;\n\n constructor(\n filePath: string | undefined,\n allowReload: boolean,\n logger: LoggerService,\n private readonly enforcer: EnforcerDelegate,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly auditLogger: AuditLogger,\n ) {\n super(filePath, allowReload, logger);\n this.currentContent = [];\n this.csvFilePolicies = {\n addedPolicies: [],\n removedPolicies: [],\n addedGroupPolicies: new Map<string, string[]>(),\n removedGroupPolicies: new Map<string, string[]>(),\n };\n }\n\n /**\n * parse is used to parse the current contents of the CSV file.\n * @returns The CSV file parsed into a string[][].\n */\n parse(): string[][] {\n const content = this.getCurrentContents();\n const data = parse(content, {\n skip_empty_lines: true,\n relax_column_count: true,\n trim: true,\n });\n\n for (const policy of data) {\n transformPolicyGroupToLowercase(policy);\n }\n\n return data;\n }\n\n /**\n * initialize will initialize the CSV file by loading all of the permission policies and roles into\n * the enforcer.\n * First, we will remove all roles and permission policies if they do not exist in the temporary file enforcer.\n * Next, we will add all roles and permission polices if they are new to the CSV file\n * Finally, we will set the file to be watched if allow reload is set\n * @param csvFileName The name of the csvFile\n * @param allowReload Whether or not we will allow reloads of the CSV file\n */\n async initialize(): Promise<void> {\n if (!this.filePath) {\n return;\n }\n let content: string[][] = [];\n // If the file is set load the file contents\n content = this.parse();\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new LowercaseFileAdapter(this.filePath),\n );\n\n // Check for any old policies that will need to be removed\n await this.filterPoliciesAndRoles(\n this.enforcer,\n tempEnforcer,\n this.csvFilePolicies.removedPolicies,\n this.csvFilePolicies.removedGroupPolicies,\n true,\n );\n\n await this.filterPoliciesAndRoles(\n tempEnforcer,\n this.enforcer,\n this.csvFilePolicies.addedPolicies,\n this.csvFilePolicies.addedGroupPolicies,\n );\n\n await this.migrateLegacyMetadata(tempEnforcer);\n\n // We pass current here because this is during initialization and it has not changed yet\n await this.updatePolicies(content);\n\n if (this.allowReload) {\n this.watchFile();\n }\n }\n\n // Check for policies that might need to be updated\n // This will involve update \"legacy\" source in the role metadata if it exist in both the\n // temp enforcer (csv file) and a role metadata storage.\n // We will update role metadata with the new source \"csv-file\"\n private async migrateLegacyMetadata(tempEnforcer: Enforcer) {\n let legacyRolesMetadata =\n await this.roleMetadataStorage.filterRoleMetadata('legacy');\n const legacyRoles = legacyRolesMetadata.map(meta => meta.roleEntityRef);\n if (legacyRoles.length > 0) {\n const legacyGroupPolicies = await tempEnforcer.getFilteredGroupingPolicy(\n 1,\n ...legacyRoles,\n );\n const legacyPolicies = await tempEnforcer.getFilteredPolicy(\n 0,\n ...legacyRoles,\n );\n const legacyRolesFromFile = new Set([\n ...legacyGroupPolicies.map(gp => gp[1]),\n ...legacyPolicies.map(p => p[0]),\n ]);\n legacyRolesMetadata = legacyRolesMetadata.filter(meta =>\n legacyRolesFromFile.has(meta.roleEntityRef),\n );\n for (const legacyRoleMeta of legacyRolesMetadata) {\n const nonLegacyRole = mergeRoleMetadata(legacyRoleMeta, {\n modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n source: 'csv-file',\n roleEntityRef: legacyRoleMeta.roleEntityRef,\n });\n await this.roleMetadataStorage.updateRoleMetadata(\n nonLegacyRole,\n legacyRoleMeta.roleEntityRef,\n );\n }\n }\n }\n\n /**\n * onChange is called whenever there is a change to the CSV file.\n * It will parse the current and new contents of the CSV file and process the roles and permission policies present.\n * Afterwards, it will find the difference between the current and new contents of the CSV file\n * and sort them into added / removed, permission policies / roles.\n * It will finally call updatePolicies with the new content.\n */\n async onChange(): Promise<void> {\n const newContent = this.parse();\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new LowercaseFileAdapter(this.filePath!),\n );\n\n const currentFlatContent = this.currentContent.flatMap(data => {\n return policyToString(data);\n });\n const newFlatContent = newContent.flatMap(data => {\n return policyToString(data);\n });\n\n await this.findFileContentDiff(\n currentFlatContent,\n newFlatContent,\n tempEnforcer,\n );\n\n await this.updatePolicies(newContent);\n }\n\n /**\n * updatePolicies is used to update all of the permission policies and roles within a CSV file.\n * It will check the number of added and removed permissions policies and roles and call the appropriate\n * methods for these.\n * It will also update the current contents of the CSV file to the most recent\n * @param newContent The new content present in the CSV file\n */\n private async updatePolicies(newContent: string[][]): Promise<void> {\n this.currentContent = newContent;\n\n if (this.csvFilePolicies.addedPolicies.length > 0)\n await this.addPermissionPolicies();\n if (this.csvFilePolicies.removedPolicies.length > 0)\n await this.removePermissionPolicies();\n if (this.csvFilePolicies.addedGroupPolicies.size > 0) await this.addRoles();\n if (this.csvFilePolicies.removedGroupPolicies.size > 0)\n await this.removeRoles();\n }\n\n /**\n * addPermissionPolicies will add the new permission policies that are present in the CSV file.\n */\n private async addPermissionPolicies(): Promise<void> {\n try {\n await this.enforcer.addPolicies(this.csvFilePolicies.addedPolicies);\n\n await this.auditLogger.auditLog<PermissionAuditInfo>({\n actorId: RBAC_BACKEND,\n message: `Created policies`,\n eventName: PermissionEvents.CREATE_POLICY,\n metadata: {\n policies: this.csvFilePolicies.addedPolicies,\n source: 'csv-file',\n },\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'succeeded',\n });\n } catch (e) {\n this.logger.warn(\n `Failed to add or update policies ${this.csvFilePolicies.addedPolicies} after modification ${this.filePath}. Cause: ${e}`,\n );\n }\n\n this.csvFilePolicies.addedPolicies = [];\n }\n\n /**\n * removePermissionPolicies will remove the permission policies that are no longer present in the CSV file.\n */\n private async removePermissionPolicies(): Promise<void> {\n try {\n await this.enforcer.removePolicies(this.csvFilePolicies.removedPolicies);\n\n await this.auditLogger.auditLog<PermissionAuditInfo>({\n actorId: RBAC_BACKEND,\n message: `Deleted policies`,\n eventName: PermissionEvents.DELETE_POLICY,\n metadata: {\n policies: this.csvFilePolicies.removedPolicies,\n source: 'csv-file',\n },\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'succeeded',\n });\n } catch (e) {\n this.logger.warn(\n `Failed to remove policies ${JSON.stringify(\n this.csvFilePolicies.removedPolicies,\n )} after modification ${this.filePath}. Cause: ${e}`,\n );\n }\n this.csvFilePolicies.removedPolicies = [];\n }\n\n /**\n * addRoles will add the new roles that are present in the CSV file.\n */\n private async addRoles(): Promise<void> {\n const addedPolicies: string[][] = [];\n const updatedPolicies: string[][] = [];\n\n for (const [key, value] of this.csvFilePolicies.addedGroupPolicies) {\n const groupPolicies = value.map(member => {\n return [member, key];\n });\n\n try {\n const roleMetadata: RoleMetadataDao = {\n source: 'csv-file',\n roleEntityRef: key,\n author: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n };\n\n const currentMetadata = await this.roleMetadataStorage.findRoleMetadata(\n roleMetadata.roleEntityRef,\n );\n\n await this.enforcer.addGroupingPolicies(groupPolicies, roleMetadata);\n const eventName = currentMetadata\n ? RoleEvents.UPDATE_ROLE\n : RoleEvents.CREATE_ROLE;\n\n if (eventName === RoleEvents.UPDATE_ROLE) {\n updatedPolicies.push(...groupPolicies);\n } else {\n addedPolicies.push(...groupPolicies);\n }\n } catch (e) {\n this.logger.warn(\n `Failed to add or update group policy ${groupPolicies} after modification ${this.filePath}. Cause: ${e}`,\n );\n }\n }\n\n if (updatedPolicies.length > 0)\n await this.logRoleEvent(\n RoleEvents.UPDATE_ROLE,\n 'Updated roles',\n updatedPolicies,\n );\n\n if (addedPolicies.length > 0)\n await this.logRoleEvent(\n RoleEvents.CREATE_ROLE,\n 'Created roles',\n addedPolicies,\n );\n\n this.csvFilePolicies.addedGroupPolicies = new Map<string, string[]>();\n }\n\n /**\n * removeRoles will remove the roles that are no longer present in the CSV file.\n * If the role exists with multiple groups and or users, we will update it role information.\n * Otherwise, we will remove the role completely.\n */\n private async removeRoles(): Promise<void> {\n for (const [key, value] of this.csvFilePolicies.removedGroupPolicies) {\n // This requires knowledge of whether or not it is an update\n const isUpdate = await this.enforcer.getFilteredGroupingPolicy(1, key);\n\n const groupPolicies = value.map(member => {\n return [member, key];\n });\n\n try {\n const roleMetadata: RoleMetadataDao = {\n source: 'csv-file',\n roleEntityRef: key,\n author: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n };\n\n await this.enforcer.removeGroupingPolicies(\n groupPolicies,\n roleMetadata,\n isUpdate.length > 1 && isUpdate.length !== groupPolicies.length,\n );\n\n const isRolePresent = await this.roleMetadataStorage.findRoleMetadata(\n roleMetadata.roleEntityRef,\n );\n const eventName = isRolePresent\n ? RoleEvents.UPDATE_ROLE\n : RoleEvents.DELETE_ROLE;\n const message = isRolePresent\n ? 'Updated role: deleted members'\n : 'Deleted role';\n await this.auditLogger.auditLog<RoleAuditInfo>({\n actorId: RBAC_BACKEND,\n message,\n eventName,\n metadata: { ...roleMetadata, members: value },\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'succeeded',\n });\n } catch (e) {\n this.logger.warn(\n `Failed to remove group policy ${groupPolicies} after modification ${this.filePath}. Cause: ${e}`,\n );\n }\n }\n\n this.csvFilePolicies.removedGroupPolicies = new Map<string, string[]>();\n }\n\n async cleanUpRolesAndPolicies(): Promise<void> {\n const roleMetadatas =\n await this.roleMetadataStorage.filterRoleMetadata('csv-file');\n const fileRoles = roleMetadatas.map(meta => meta.roleEntityRef);\n\n if (fileRoles.length > 0) {\n for (const fileRole of fileRoles) {\n const filteredPolicies = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n fileRole,\n );\n for (const groupPolicy of filteredPolicies) {\n this.addGroupPolicyToMap(\n this.csvFilePolicies.removedGroupPolicies,\n groupPolicy[1],\n groupPolicy[0],\n );\n }\n this.csvFilePolicies.removedPolicies.push(\n ...(await this.enforcer.getFilteredPolicy(0, fileRole)),\n );\n }\n }\n await this.removePermissionPolicies();\n await this.removeRoles();\n }\n\n async filterPoliciesAndRoles(\n enforcerOne: Enforcer | EnforcerDelegate,\n enforcerTwo: Enforcer | EnforcerDelegate,\n policies: string[][],\n groupPolicies: Map<string, string[]>,\n remove?: boolean,\n ) {\n // Check for any policies that need to be edited by comparing policies from\n // one enforcer to the other\n const policiesToEdit = await enforcerOne.getPolicy();\n const groupPoliciesToEdit = await enforcerOne.getGroupingPolicy();\n\n for (const policy of policiesToEdit) {\n if (\n !(await enforcerTwo.hasPolicy(...policy)) &&\n (await this.validateAddedPolicy(\n policy,\n enforcerOne as Enforcer,\n remove,\n ))\n ) {\n policies.push(policy);\n }\n }\n\n for (const groupPolicy of groupPoliciesToEdit) {\n if (\n !(await enforcerTwo.hasGroupingPolicy(...groupPolicy)) &&\n (await this.validateAddedGroupPolicy(\n groupPolicy,\n enforcerOne as Enforcer,\n remove,\n ))\n ) {\n this.addGroupPolicyToMap(groupPolicies, groupPolicy[1], groupPolicy[0]);\n }\n }\n }\n\n async validateAddedPolicy(\n policy: string[],\n tempEnforcer: Enforcer,\n remove?: boolean,\n ): Promise<boolean> {\n const transformedPolicy = transformArrayToPolicy(policy);\n const metadata = await this.roleMetadataStorage.findRoleMetadata(policy[0]);\n\n if (remove) {\n return metadata?.source === 'csv-file';\n }\n\n let err = validatePolicy(transformedPolicy);\n if (err) {\n this.logger.warn(\n `Failed to validate policy from file ${this.filePath}. Cause: ${err.message}`,\n );\n return false;\n }\n\n err = await validateSource('csv-file', metadata);\n if (err) {\n this.logger.warn(\n `Unable to add policy ${policy} from file ${this.filePath}. Cause: ${err.message}`,\n );\n return false;\n }\n\n err = await checkForDuplicatePolicies(tempEnforcer, policy, this.filePath!);\n if (err) {\n this.logger.warn(err.message);\n return false;\n }\n\n return true;\n }\n\n async validateAddedGroupPolicy(\n groupPolicy: string[],\n tempEnforcer: Enforcer,\n remove?: boolean,\n ): Promise<boolean> {\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n groupPolicy[1],\n );\n\n if (remove) {\n return metadata?.source === 'csv-file';\n }\n\n let err = await validateGroupingPolicy(groupPolicy, metadata, 'csv-file');\n if (err) {\n this.logger.warn(\n `${err.message}, error originates from file ${this.filePath}`,\n );\n return false;\n }\n\n err = await checkForDuplicateGroupPolicies(\n tempEnforcer,\n groupPolicy,\n this.filePath!,\n );\n if (err) {\n this.logger.warn(err.message);\n return false;\n }\n\n return true;\n }\n\n async findFileContentDiff(\n currentFlatContent: string[],\n newFlatContent: string[],\n tempEnforcer: Enforcer,\n ) {\n const diffRemoved = difference(currentFlatContent, newFlatContent); // policy was removed\n const diffAdded = difference(newFlatContent, currentFlatContent); // policy was added\n\n await this.migrateLegacyMetadata(tempEnforcer);\n\n if (diffRemoved.length === 0 && diffAdded.length === 0) {\n return;\n }\n\n diffRemoved.forEach(policy => {\n const convertedPolicy = metadataStringToPolicy(policy);\n if (convertedPolicy[0] === 'p') {\n convertedPolicy.splice(0, 1);\n this.csvFilePolicies.removedPolicies.push(convertedPolicy);\n } else if (convertedPolicy[0] === 'g') {\n convertedPolicy.splice(0, 1);\n this.addGroupPolicyToMap(\n this.csvFilePolicies.removedGroupPolicies,\n convertedPolicy[1],\n convertedPolicy[0],\n );\n }\n });\n\n for (const policy of diffAdded) {\n const convertedPolicy = metadataStringToPolicy(policy);\n if (convertedPolicy[0] === 'p') {\n convertedPolicy.splice(0, 1);\n if (await this.validateAddedPolicy(convertedPolicy, tempEnforcer))\n this.csvFilePolicies.addedPolicies.push(convertedPolicy);\n } else if (convertedPolicy[0] === 'g') {\n convertedPolicy.splice(0, 1);\n if (await this.validateAddedGroupPolicy(convertedPolicy, tempEnforcer))\n this.addGroupPolicyToMap(\n this.csvFilePolicies.addedGroupPolicies,\n convertedPolicy[1],\n convertedPolicy[0],\n );\n }\n }\n }\n\n addGroupPolicyToMap(\n groupPolicyMap: Map<string, string[]>,\n key: string,\n value: string,\n ) {\n if (!groupPolicyMap.has(key)) {\n groupPolicyMap.set(key, []);\n }\n groupPolicyMap.get(key)?.push(value);\n }\n\n async logRoleEvent(\n eventName: 'CreateRole' | 'UpdateRole',\n message: string,\n groupingPolicies: string[][],\n ) {\n await this.auditLogger.auditLog<RolesAuditInfo>({\n actorId: RBAC_BACKEND,\n message,\n eventName,\n metadata: { groupingPolicies, source: 'csv-file' },\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'succeeded',\n });\n }\n}\n"],"names":["AbstractFileWatcher","parse","transformPolicyGroupToLowercase","newEnforcer","newModelFromString","MODEL","LowercaseFileAdapter","mergeRoleMetadata","policyToString","RBAC_BACKEND","PermissionEvents","HANDLE_RBAC_DATA_STAGE","RoleEvents","transformArrayToPolicy","validatePolicy","validateSource","checkForDuplicatePolicies","validateGroupingPolicy","checkForDuplicateGroupPolicies","difference","metadataStringToPolicy"],"mappings":";;;;;;;;;;;;AAsDO,MAAM,iCAAoC,GAAA;AAS1C,MAAM,uBAAuBA,+BAAgC,CAAA;AAAA,EAIlE,YACE,QACA,EAAA,WAAA,EACA,MACiB,EAAA,QAAA,EACA,qBACA,WACjB,EAAA;AACA,IAAM,KAAA,CAAA,QAAA,EAAU,aAAa,MAAM,CAAA;AAJlB,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,mBAAA,GAAA,mBAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAGjB,IAAA,IAAA,CAAK,iBAAiB,EAAC;AACvB,IAAA,IAAA,CAAK,eAAkB,GAAA;AAAA,MACrB,eAAe,EAAC;AAAA,MAChB,iBAAiB,EAAC;AAAA,MAClB,kBAAA,sBAAwB,GAAsB,EAAA;AAAA,MAC9C,oBAAA,sBAA0B,GAAsB;AAAA,KAClD;AAAA;AACF,EAnBQ,cAAA;AAAA,EACA,eAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBR,KAAoB,GAAA;AAClB,IAAM,MAAA,OAAA,GAAU,KAAK,kBAAmB,EAAA;AACxC,IAAM,MAAA,IAAA,GAAOC,WAAM,OAAS,EAAA;AAAA,MAC1B,gBAAkB,EAAA,IAAA;AAAA,MAClB,kBAAoB,EAAA,IAAA;AAAA,MACpB,IAAM,EAAA;AAAA,KACP,CAAA;AAED,IAAA,KAAA,MAAW,UAAU,IAAM,EAAA;AACzB,MAAAC,sCAAA,CAAgC,MAAM,CAAA;AAAA;AAGxC,IAAO,OAAA,IAAA;AAAA;AACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,UAA4B,GAAA;AAChC,IAAI,IAAA,CAAC,KAAK,QAAU,EAAA;AAClB,MAAA;AAAA;AAEF,IAAA,IAAI,UAAsB,EAAC;AAE3B,IAAA,OAAA,GAAU,KAAK,KAAM,EAAA;AAErB,IAAA,MAAM,eAAe,MAAMC,kBAAA;AAAA,MACzBC,0BAAmBC,qBAAK,CAAA;AAAA,MACxB,IAAIC,yCAAqB,CAAA,IAAA,CAAK,QAAQ;AAAA,KACxC;AAGA,IAAA,MAAM,IAAK,CAAA,sBAAA;AAAA,MACT,IAAK,CAAA,QAAA;AAAA,MACL,YAAA;AAAA,MACA,KAAK,eAAgB,CAAA,eAAA;AAAA,MACrB,KAAK,eAAgB,CAAA,oBAAA;AAAA,MACrB;AAAA,KACF;AAEA,IAAA,MAAM,IAAK,CAAA,sBAAA;AAAA,MACT,YAAA;AAAA,MACA,IAAK,CAAA,QAAA;AAAA,MACL,KAAK,eAAgB,CAAA,aAAA;AAAA,MACrB,KAAK,eAAgB,CAAA;AAAA,KACvB;AAEA,IAAM,MAAA,IAAA,CAAK,sBAAsB,YAAY,CAAA;AAG7C,IAAM,MAAA,IAAA,CAAK,eAAe,OAAO,CAAA;AAEjC,IAAA,IAAI,KAAK,WAAa,EAAA;AACpB,MAAA,IAAA,CAAK,SAAU,EAAA;AAAA;AACjB;AACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,sBAAsB,YAAwB,EAAA;AAC1D,IAAA,IAAI,mBACF,GAAA,MAAM,IAAK,CAAA,mBAAA,CAAoB,mBAAmB,QAAQ,CAAA;AAC5D,IAAA,MAAM,WAAc,GAAA,mBAAA,CAAoB,GAAI,CAAA,CAAA,IAAA,KAAQ,KAAK,aAAa,CAAA;AACtE,IAAI,IAAA,WAAA,CAAY,SAAS,CAAG,EAAA;AAC1B,MAAM,MAAA,mBAAA,GAAsB,MAAM,YAAa,CAAA,yBAAA;AAAA,QAC7C,CAAA;AAAA,QACA,GAAG;AAAA,OACL;AACA,MAAM,MAAA,cAAA,GAAiB,MAAM,YAAa,CAAA,iBAAA;AAAA,QACxC,CAAA;AAAA,QACA,GAAG;AAAA,OACL;AACA,MAAM,MAAA,mBAAA,uBAA0B,GAAI,CAAA;AAAA,QAClC,GAAG,mBAAoB,CAAA,GAAA,CAAI,CAAM,EAAA,KAAA,EAAA,CAAG,CAAC,CAAC,CAAA;AAAA,QACtC,GAAG,cAAe,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,CAAC,CAAC;AAAA,OAChC,CAAA;AACD,MAAA,mBAAA,GAAsB,mBAAoB,CAAA,MAAA;AAAA,QAAO,CAC/C,IAAA,KAAA,mBAAA,CAAoB,GAAI,CAAA,IAAA,CAAK,aAAa;AAAA,OAC5C;AACA,MAAA,KAAA,MAAW,kBAAkB,mBAAqB,EAAA;AAChD,QAAM,MAAA,aAAA,GAAgBC,yBAAkB,cAAgB,EAAA;AAAA,UACtD,UAAY,EAAA,iCAAA;AAAA,UACZ,MAAQ,EAAA,UAAA;AAAA,UACR,eAAe,cAAe,CAAA;AAAA,SAC/B,CAAA;AACD,QAAA,MAAM,KAAK,mBAAoB,CAAA,kBAAA;AAAA,UAC7B,aAAA;AAAA,UACA,cAAe,CAAA;AAAA,SACjB;AAAA;AACF;AACF;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAA0B,GAAA;AAC9B,IAAM,MAAA,UAAA,GAAa,KAAK,KAAM,EAAA;AAE9B,IAAA,MAAM,eAAe,MAAMJ,kBAAA;AAAA,MACzBC,0BAAmBC,qBAAK,CAAA;AAAA,MACxB,IAAIC,yCAAqB,CAAA,IAAA,CAAK,QAAS;AAAA,KACzC;AAEA,IAAA,MAAM,kBAAqB,GAAA,IAAA,CAAK,cAAe,CAAA,OAAA,CAAQ,CAAQ,IAAA,KAAA;AAC7D,MAAA,OAAOE,sBAAe,IAAI,CAAA;AAAA,KAC3B,CAAA;AACD,IAAM,MAAA,cAAA,GAAiB,UAAW,CAAA,OAAA,CAAQ,CAAQ,IAAA,KAAA;AAChD,MAAA,OAAOA,sBAAe,IAAI,CAAA;AAAA,KAC3B,CAAA;AAED,IAAA,MAAM,IAAK,CAAA,mBAAA;AAAA,MACT,kBAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAM,MAAA,IAAA,CAAK,eAAe,UAAU,CAAA;AAAA;AACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,eAAe,UAAuC,EAAA;AAClE,IAAA,IAAA,CAAK,cAAiB,GAAA,UAAA;AAEtB,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,aAAA,CAAc,MAAS,GAAA,CAAA;AAC9C,MAAA,MAAM,KAAK,qBAAsB,EAAA;AACnC,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,eAAA,CAAgB,MAAS,GAAA,CAAA;AAChD,MAAA,MAAM,KAAK,wBAAyB,EAAA;AACtC,IAAA,IAAI,KAAK,eAAgB,CAAA,kBAAA,CAAmB,OAAO,CAAG,EAAA,MAAM,KAAK,QAAS,EAAA;AAC1E,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,oBAAA,CAAqB,IAAO,GAAA,CAAA;AACnD,MAAA,MAAM,KAAK,WAAY,EAAA;AAAA;AAC3B;AAAA;AAAA;AAAA,EAKA,MAAc,qBAAuC,GAAA;AACnD,IAAI,IAAA;AACF,MAAA,MAAM,IAAK,CAAA,QAAA,CAAS,WAAY,CAAA,IAAA,CAAK,gBAAgB,aAAa,CAAA;AAElE,MAAM,MAAA,IAAA,CAAK,YAAY,QAA8B,CAAA;AAAA,QACnD,OAAS,EAAAC,wBAAA;AAAA,QACT,OAAS,EAAA,CAAA,gBAAA,CAAA;AAAA,QACT,WAAWC,4BAAiB,CAAA,aAAA;AAAA,QAC5B,QAAU,EAAA;AAAA,UACR,QAAA,EAAU,KAAK,eAAgB,CAAA,aAAA;AAAA,UAC/B,MAAQ,EAAA;AAAA,SACV;AAAA,QACA,KAAO,EAAAC,kCAAA;AAAA,QACP,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,CAAA,iCAAA,EAAoC,KAAK,eAAgB,CAAA,aAAa,uBAAuB,IAAK,CAAA,QAAQ,YAAY,CAAC,CAAA;AAAA,OACzH;AAAA;AAGF,IAAK,IAAA,CAAA,eAAA,CAAgB,gBAAgB,EAAC;AAAA;AACxC;AAAA;AAAA;AAAA,EAKA,MAAc,wBAA0C,GAAA;AACtD,IAAI,IAAA;AACF,MAAA,MAAM,IAAK,CAAA,QAAA,CAAS,cAAe,CAAA,IAAA,CAAK,gBAAgB,eAAe,CAAA;AAEvE,MAAM,MAAA,IAAA,CAAK,YAAY,QAA8B,CAAA;AAAA,QACnD,OAAS,EAAAF,wBAAA;AAAA,QACT,OAAS,EAAA,CAAA,gBAAA,CAAA;AAAA,QACT,WAAWC,4BAAiB,CAAA,aAAA;AAAA,QAC5B,QAAU,EAAA;AAAA,UACR,QAAA,EAAU,KAAK,eAAgB,CAAA,eAAA;AAAA,UAC/B,MAAQ,EAAA;AAAA,SACV;AAAA,QACA,KAAO,EAAAC,kCAAA;AAAA,QACP,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,6BAA6B,IAAK,CAAA,SAAA;AAAA,UAChC,KAAK,eAAgB,CAAA;AAAA,SACtB,CAAA,oBAAA,EAAuB,IAAK,CAAA,QAAQ,YAAY,CAAC,CAAA;AAAA,OACpD;AAAA;AAEF,IAAK,IAAA,CAAA,eAAA,CAAgB,kBAAkB,EAAC;AAAA;AAC1C;AAAA;AAAA;AAAA,EAKA,MAAc,QAA0B,GAAA;AACtC,IAAA,MAAM,gBAA4B,EAAC;AACnC,IAAA,MAAM,kBAA8B,EAAC;AAErC,IAAA,KAAA,MAAW,CAAC,GAAK,EAAA,KAAK,CAAK,IAAA,IAAA,CAAK,gBAAgB,kBAAoB,EAAA;AAClE,MAAM,MAAA,aAAA,GAAgB,KAAM,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AACxC,QAAO,OAAA,CAAC,QAAQ,GAAG,CAAA;AAAA,OACpB,CAAA;AAED,MAAI,IAAA;AACF,QAAA,MAAM,YAAgC,GAAA;AAAA,UACpC,MAAQ,EAAA,UAAA;AAAA,UACR,aAAe,EAAA,GAAA;AAAA,UACf,MAAQ,EAAA,iCAAA;AAAA,UACR,UAAY,EAAA;AAAA,SACd;AAEA,QAAM,MAAA,eAAA,GAAkB,MAAM,IAAA,CAAK,mBAAoB,CAAA,gBAAA;AAAA,UACrD,YAAa,CAAA;AAAA,SACf;AAEA,QAAA,MAAM,IAAK,CAAA,QAAA,CAAS,mBAAoB,CAAA,aAAA,EAAe,YAAY,CAAA;AACnE,QAAA,MAAM,SAAY,GAAA,eAAA,GACdC,sBAAW,CAAA,WAAA,GACXA,sBAAW,CAAA,WAAA;AAEf,QAAI,IAAA,SAAA,KAAcA,uBAAW,WAAa,EAAA;AACxC,UAAgB,eAAA,CAAA,IAAA,CAAK,GAAG,aAAa,CAAA;AAAA,SAChC,MAAA;AACL,UAAc,aAAA,CAAA,IAAA,CAAK,GAAG,aAAa,CAAA;AAAA;AACrC,eACO,CAAG,EAAA;AACV,QAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,UACV,wCAAwC,aAAa,CAAA,oBAAA,EAAuB,IAAK,CAAA,QAAQ,YAAY,CAAC,CAAA;AAAA,SACxG;AAAA;AACF;AAGF,IAAA,IAAI,gBAAgB,MAAS,GAAA,CAAA;AAC3B,MAAA,MAAM,IAAK,CAAA,YAAA;AAAA,QACTA,sBAAW,CAAA,WAAA;AAAA,QACX,eAAA;AAAA,QACA;AAAA,OACF;AAEF,IAAA,IAAI,cAAc,MAAS,GAAA,CAAA;AACzB,MAAA,MAAM,IAAK,CAAA,YAAA;AAAA,QACTA,sBAAW,CAAA,WAAA;AAAA,QACX,eAAA;AAAA,QACA;AAAA,OACF;AAEF,IAAK,IAAA,CAAA,eAAA,CAAgB,kBAAqB,mBAAA,IAAI,GAAsB,EAAA;AAAA;AACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,WAA6B,GAAA;AACzC,IAAA,KAAA,MAAW,CAAC,GAAK,EAAA,KAAK,CAAK,IAAA,IAAA,CAAK,gBAAgB,oBAAsB,EAAA;AAEpE,MAAA,MAAM,WAAW,MAAM,IAAA,CAAK,QAAS,CAAA,yBAAA,CAA0B,GAAG,GAAG,CAAA;AAErE,MAAM,MAAA,aAAA,GAAgB,KAAM,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AACxC,QAAO,OAAA,CAAC,QAAQ,GAAG,CAAA;AAAA,OACpB,CAAA;AAED,MAAI,IAAA;AACF,QAAA,MAAM,YAAgC,GAAA;AAAA,UACpC,MAAQ,EAAA,UAAA;AAAA,UACR,aAAe,EAAA,GAAA;AAAA,UACf,MAAQ,EAAA,iCAAA;AAAA,UACR,UAAY,EAAA;AAAA,SACd;AAEA,QAAA,MAAM,KAAK,QAAS,CAAA,sBAAA;AAAA,UAClB,aAAA;AAAA,UACA,YAAA;AAAA,UACA,QAAS,CAAA,MAAA,GAAS,CAAK,IAAA,QAAA,CAAS,WAAW,aAAc,CAAA;AAAA,SAC3D;AAEA,QAAM,MAAA,aAAA,GAAgB,MAAM,IAAA,CAAK,mBAAoB,CAAA,gBAAA;AAAA,UACnD,YAAa,CAAA;AAAA,SACf;AACA,QAAA,MAAM,SAAY,GAAA,aAAA,GACdA,sBAAW,CAAA,WAAA,GACXA,sBAAW,CAAA,WAAA;AACf,QAAM,MAAA,OAAA,GAAU,gBACZ,+BACA,GAAA,cAAA;AACJ,QAAM,MAAA,IAAA,CAAK,YAAY,QAAwB,CAAA;AAAA,UAC7C,OAAS,EAAAH,wBAAA;AAAA,UACT,OAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAU,EAAA,EAAE,GAAG,YAAA,EAAc,SAAS,KAAM,EAAA;AAAA,UAC5C,KAAO,EAAAE,kCAAA;AAAA,UACP,MAAQ,EAAA;AAAA,SACT,CAAA;AAAA,eACM,CAAG,EAAA;AACV,QAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,UACV,iCAAiC,aAAa,CAAA,oBAAA,EAAuB,IAAK,CAAA,QAAQ,YAAY,CAAC,CAAA;AAAA,SACjG;AAAA;AACF;AAGF,IAAK,IAAA,CAAA,eAAA,CAAgB,oBAAuB,mBAAA,IAAI,GAAsB,EAAA;AAAA;AACxE,EAEA,MAAM,uBAAyC,GAAA;AAC7C,IAAA,MAAM,aACJ,GAAA,MAAM,IAAK,CAAA,mBAAA,CAAoB,mBAAmB,UAAU,CAAA;AAC9D,IAAA,MAAM,SAAY,GAAA,aAAA,CAAc,GAAI,CAAA,CAAA,IAAA,KAAQ,KAAK,aAAa,CAAA;AAE9D,IAAI,IAAA,SAAA,CAAU,SAAS,CAAG,EAAA;AACxB,MAAA,KAAA,MAAW,YAAY,SAAW,EAAA;AAChC,QAAM,MAAA,gBAAA,GAAmB,MAAM,IAAA,CAAK,QAAS,CAAA,yBAAA;AAAA,UAC3C,CAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,KAAA,MAAW,eAAe,gBAAkB,EAAA;AAC1C,UAAK,IAAA,CAAA,mBAAA;AAAA,YACH,KAAK,eAAgB,CAAA,oBAAA;AAAA,YACrB,YAAY,CAAC,CAAA;AAAA,YACb,YAAY,CAAC;AAAA,WACf;AAAA;AAEF,QAAA,IAAA,CAAK,gBAAgB,eAAgB,CAAA,IAAA;AAAA,UACnC,GAAI,MAAM,IAAA,CAAK,QAAS,CAAA,iBAAA,CAAkB,GAAG,QAAQ;AAAA,SACvD;AAAA;AACF;AAEF,IAAA,MAAM,KAAK,wBAAyB,EAAA;AACpC,IAAA,MAAM,KAAK,WAAY,EAAA;AAAA;AACzB,EAEA,MAAM,sBACJ,CAAA,WAAA,EACA,WACA,EAAA,QAAA,EACA,eACA,MACA,EAAA;AAGA,IAAM,MAAA,cAAA,GAAiB,MAAM,WAAA,CAAY,SAAU,EAAA;AACnD,IAAM,MAAA,mBAAA,GAAsB,MAAM,WAAA,CAAY,iBAAkB,EAAA;AAEhE,IAAA,KAAA,MAAW,UAAU,cAAgB,EAAA;AACnC,MACE,IAAA,CAAE,MAAM,WAAY,CAAA,SAAA,CAAU,GAAG,MAAM,CAAA,IACtC,MAAM,IAAK,CAAA,mBAAA;AAAA,QACV,MAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OAEF,EAAA;AACA,QAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAAA;AACtB;AAGF,IAAA,KAAA,MAAW,eAAe,mBAAqB,EAAA;AAC7C,MACE,IAAA,CAAE,MAAM,WAAY,CAAA,iBAAA,CAAkB,GAAG,WAAW,CAAA,IACnD,MAAM,IAAK,CAAA,wBAAA;AAAA,QACV,WAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OAEF,EAAA;AACA,QAAA,IAAA,CAAK,oBAAoB,aAAe,EAAA,WAAA,CAAY,CAAC,CAAG,EAAA,WAAA,CAAY,CAAC,CAAC,CAAA;AAAA;AACxE;AACF;AACF,EAEA,MAAM,mBAAA,CACJ,MACA,EAAA,YAAA,EACA,MACkB,EAAA;AAClB,IAAM,MAAA,iBAAA,GAAoBE,8BAAuB,MAAM,CAAA;AACvD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,oBAAoB,gBAAiB,CAAA,MAAA,CAAO,CAAC,CAAC,CAAA;AAE1E,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,OAAO,UAAU,MAAW,KAAA,UAAA;AAAA;AAG9B,IAAI,IAAA,GAAA,GAAMC,kCAAe,iBAAiB,CAAA;AAC1C,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,CAAuC,oCAAA,EAAA,IAAA,CAAK,QAAQ,CAAA,SAAA,EAAY,IAAI,OAAO,CAAA;AAAA,OAC7E;AACA,MAAO,OAAA,KAAA;AAAA;AAGT,IAAM,GAAA,GAAA,MAAMC,iCAAe,CAAA,UAAA,EAAY,QAAQ,CAAA;AAC/C,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,wBAAwB,MAAM,CAAA,WAAA,EAAc,KAAK,QAAQ,CAAA,SAAA,EAAY,IAAI,OAAO,CAAA;AAAA,OAClF;AACA,MAAO,OAAA,KAAA;AAAA;AAGT,IAAA,GAAA,GAAM,MAAMC,4CAAA,CAA0B,YAAc,EAAA,MAAA,EAAQ,KAAK,QAAS,CAAA;AAC1E,IAAA,IAAI,GAAK,EAAA;AACP,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA;AAC5B,MAAO,OAAA,KAAA;AAAA;AAGT,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,wBAAA,CACJ,WACA,EAAA,YAAA,EACA,MACkB,EAAA;AAClB,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,mBAAoB,CAAA,gBAAA;AAAA,MAC9C,YAAY,CAAC;AAAA,KACf;AAEA,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,OAAO,UAAU,MAAW,KAAA,UAAA;AAAA;AAG9B,IAAA,IAAI,GAAM,GAAA,MAAMC,yCAAuB,CAAA,WAAA,EAAa,UAAU,UAAU,CAAA;AACxE,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,CAAG,EAAA,GAAA,CAAI,OAAO,CAAA,6BAAA,EAAgC,KAAK,QAAQ,CAAA;AAAA,OAC7D;AACA,MAAO,OAAA,KAAA;AAAA;AAGT,IAAA,GAAA,GAAM,MAAMC,iDAAA;AAAA,MACV,YAAA;AAAA,MACA,WAAA;AAAA,MACA,IAAK,CAAA;AAAA,KACP;AACA,IAAA,IAAI,GAAK,EAAA;AACP,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA;AAC5B,MAAO,OAAA,KAAA;AAAA;AAGT,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,mBAAA,CACJ,kBACA,EAAA,cAAA,EACA,YACA,EAAA;AACA,IAAM,MAAA,WAAA,GAAcC,iBAAW,CAAA,kBAAA,EAAoB,cAAc,CAAA;AACjE,IAAM,MAAA,SAAA,GAAYA,iBAAW,CAAA,cAAA,EAAgB,kBAAkB,CAAA;AAE/D,IAAM,MAAA,IAAA,CAAK,sBAAsB,YAAY,CAAA;AAE7C,IAAA,IAAI,WAAY,CAAA,MAAA,KAAW,CAAK,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AACtD,MAAA;AAAA;AAGF,IAAA,WAAA,CAAY,QAAQ,CAAU,MAAA,KAAA;AAC5B,MAAM,MAAA,eAAA,GAAkBC,8BAAuB,MAAM,CAAA;AACrD,MAAI,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AAC9B,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAK,IAAA,CAAA,eAAA,CAAgB,eAAgB,CAAA,IAAA,CAAK,eAAe,CAAA;AAAA,OAChD,MAAA,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AACrC,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAK,IAAA,CAAA,mBAAA;AAAA,UACH,KAAK,eAAgB,CAAA,oBAAA;AAAA,UACrB,gBAAgB,CAAC,CAAA;AAAA,UACjB,gBAAgB,CAAC;AAAA,SACnB;AAAA;AACF,KACD,CAAA;AAED,IAAA,KAAA,MAAW,UAAU,SAAW,EAAA;AAC9B,MAAM,MAAA,eAAA,GAAkBA,8BAAuB,MAAM,CAAA;AACrD,MAAI,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AAC9B,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAA,IAAI,MAAM,IAAA,CAAK,mBAAoB,CAAA,eAAA,EAAiB,YAAY,CAAA;AAC9D,UAAK,IAAA,CAAA,eAAA,CAAgB,aAAc,CAAA,IAAA,CAAK,eAAe,CAAA;AAAA,OAChD,MAAA,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AACrC,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAA,IAAI,MAAM,IAAA,CAAK,wBAAyB,CAAA,eAAA,EAAiB,YAAY,CAAA;AACnE,UAAK,IAAA,CAAA,mBAAA;AAAA,YACH,KAAK,eAAgB,CAAA,kBAAA;AAAA,YACrB,gBAAgB,CAAC,CAAA;AAAA,YACjB,gBAAgB,CAAC;AAAA,WACnB;AAAA;AACJ;AACF;AACF,EAEA,mBAAA,CACE,cACA,EAAA,GAAA,EACA,KACA,EAAA;AACA,IAAA,IAAI,CAAC,cAAA,CAAe,GAAI,CAAA,GAAG,CAAG,EAAA;AAC5B,MAAe,cAAA,CAAA,GAAA,CAAI,GAAK,EAAA,EAAE,CAAA;AAAA;AAE5B,IAAA,cAAA,CAAe,GAAI,CAAA,GAAG,CAAG,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA;AACrC,EAEA,MAAM,YAAA,CACJ,SACA,EAAA,OAAA,EACA,gBACA,EAAA;AACA,IAAM,MAAA,IAAA,CAAK,YAAY,QAAyB,CAAA;AAAA,MAC9C,OAAS,EAAAX,wBAAA;AAAA,MACT,OAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAU,EAAA,EAAE,gBAAkB,EAAA,MAAA,EAAQ,UAAW,EAAA;AAAA,MACjD,KAAO,EAAAE,kCAAA;AAAA,MACP,MAAQ,EAAA;AAAA,KACT,CAAA;AAAA;AAEL;;;;;"}
1
+ {"version":3,"file":"csv-file-watcher.cjs.js","sources":["../../src/file-permissions/csv-file-watcher.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 { Enforcer, newEnforcer, newModelFromString } from 'casbin';\nimport { parse } from 'csv-parse/sync';\nimport { difference } from 'lodash';\n\nimport { ActionType, PermissionEvents, RoleEvents } from '../auditor/auditor';\nimport {\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport {\n mergeRoleMetadata,\n metadataStringToPolicy,\n policyToString,\n transformArrayToPolicy,\n transformPolicyGroupToLowercase,\n} from '../helper';\nimport { EnforcerDelegate } from '../service/enforcer-delegate';\nimport { MODEL } from '../service/permission-model';\nimport {\n checkForDuplicateGroupPolicies,\n checkForDuplicatePolicies,\n validateGroupingPolicy,\n validatePolicy,\n validateSource,\n} from '../validation/policies-validation';\nimport { AbstractFileWatcher } from './file-watcher';\nimport { LowercaseFileAdapter } from './lowercase-file-adapter';\n\nexport const CSV_PERMISSION_POLICY_FILE_AUTHOR = 'csv permission policy file';\n\ntype CSVFilePolicies = {\n addedPolicies: string[][];\n removedPolicies: string[][];\n addedGroupPolicies: Map<string, string[]>;\n removedGroupPolicies: Map<string, string[]>;\n};\n\nexport class CSVFileWatcher extends AbstractFileWatcher<string[][]> {\n private currentContent: string[][];\n private csvFilePolicies: CSVFilePolicies;\n\n constructor(\n filePath: string | undefined,\n allowReload: boolean,\n logger: LoggerService,\n private readonly enforcer: EnforcerDelegate,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly auditor: AuditorService,\n ) {\n super(filePath, allowReload, logger);\n this.currentContent = [];\n this.csvFilePolicies = {\n addedPolicies: [],\n removedPolicies: [],\n addedGroupPolicies: new Map<string, string[]>(),\n removedGroupPolicies: new Map<string, string[]>(),\n };\n }\n\n /**\n * parse is used to parse the current contents of the CSV file.\n * @returns The CSV file parsed into a string[][].\n */\n parse(): string[][] {\n const content = this.getCurrentContents();\n const data = parse(content, {\n skip_empty_lines: true,\n relax_column_count: true,\n trim: true,\n });\n\n for (const policy of data) {\n transformPolicyGroupToLowercase(policy);\n }\n\n return data;\n }\n\n /**\n * initialize will initialize the CSV file by loading all of the permission policies and roles into\n * the enforcer.\n * First, we will remove all roles and permission policies if they do not exist in the temporary file enforcer.\n * Next, we will add all roles and permission polices if they are new to the CSV file\n * Finally, we will set the file to be watched if allow reload is set\n * @param csvFileName The name of the csvFile\n * @param allowReload Whether or not we will allow reloads of the CSV file\n */\n async initialize(): Promise<void> {\n if (!this.filePath) {\n return;\n }\n let content: string[][] = [];\n // If the file is set load the file contents\n content = this.parse();\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new LowercaseFileAdapter(this.filePath),\n );\n\n // Check for any old policies that will need to be removed\n await this.filterPoliciesAndRoles(\n this.enforcer,\n tempEnforcer,\n this.csvFilePolicies.removedPolicies,\n this.csvFilePolicies.removedGroupPolicies,\n true,\n );\n\n await this.filterPoliciesAndRoles(\n tempEnforcer,\n this.enforcer,\n this.csvFilePolicies.addedPolicies,\n this.csvFilePolicies.addedGroupPolicies,\n );\n\n await this.migrateLegacyMetadata(tempEnforcer);\n\n // We pass current here because this is during initialization and it has not changed yet\n await this.updatePolicies(content);\n\n if (this.allowReload) {\n this.watchFile();\n }\n }\n\n // Check for policies that might need to be updated\n // This will involve update \"legacy\" source in the role metadata if it exist in both the\n // temp enforcer (csv file) and a role metadata storage.\n // We will update role metadata with the new source \"csv-file\"\n private async migrateLegacyMetadata(tempEnforcer: Enforcer) {\n let legacyRolesMetadata =\n await this.roleMetadataStorage.filterRoleMetadata('legacy');\n const legacyRoles = legacyRolesMetadata.map(meta => meta.roleEntityRef);\n if (legacyRoles.length > 0) {\n const legacyGroupPolicies = await tempEnforcer.getFilteredGroupingPolicy(\n 1,\n ...legacyRoles,\n );\n const legacyPolicies = await tempEnforcer.getFilteredPolicy(\n 0,\n ...legacyRoles,\n );\n const legacyRolesFromFile = new Set([\n ...legacyGroupPolicies.map(gp => gp[1]),\n ...legacyPolicies.map(p => p[0]),\n ]);\n legacyRolesMetadata = legacyRolesMetadata.filter(meta =>\n legacyRolesFromFile.has(meta.roleEntityRef),\n );\n for (const legacyRoleMeta of legacyRolesMetadata) {\n const nonLegacyRole = mergeRoleMetadata(legacyRoleMeta, {\n modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n source: 'csv-file',\n roleEntityRef: legacyRoleMeta.roleEntityRef,\n });\n await this.roleMetadataStorage.updateRoleMetadata(\n nonLegacyRole,\n legacyRoleMeta.roleEntityRef,\n );\n }\n }\n }\n\n /**\n * onChange is called whenever there is a change to the CSV file.\n * It will parse the current and new contents of the CSV file and process the roles and permission policies present.\n * Afterwards, it will find the difference between the current and new contents of the CSV file\n * and sort them into added / removed, permission policies / roles.\n * It will finally call updatePolicies with the new content.\n */\n async onChange(): Promise<void> {\n const newContent = this.parse();\n\n const tempEnforcer = await newEnforcer(\n newModelFromString(MODEL),\n new LowercaseFileAdapter(this.filePath!),\n );\n\n const currentFlatContent = this.currentContent.flatMap(data => {\n return policyToString(data);\n });\n const newFlatContent = newContent.flatMap(data => {\n return policyToString(data);\n });\n\n await this.findFileContentDiff(\n currentFlatContent,\n newFlatContent,\n tempEnforcer,\n );\n\n await this.updatePolicies(newContent);\n }\n\n /**\n * updatePolicies is used to update all of the permission policies and roles within a CSV file.\n * It will check the number of added and removed permissions policies and roles and call the appropriate\n * methods for these.\n * It will also update the current contents of the CSV file to the most recent\n * @param newContent The new content present in the CSV file\n */\n private async updatePolicies(newContent: string[][]): Promise<void> {\n this.currentContent = newContent;\n\n if (this.csvFilePolicies.addedPolicies.length > 0)\n await this.addPermissionPolicies();\n if (this.csvFilePolicies.removedPolicies.length > 0)\n await this.removePermissionPolicies();\n if (this.csvFilePolicies.addedGroupPolicies.size > 0) await this.addRoles();\n if (this.csvFilePolicies.removedGroupPolicies.size > 0)\n await this.removeRoles();\n }\n\n /**\n * addPermissionPolicies will add the new permission policies that are present in the CSV file.\n */\n private async addPermissionPolicies(): Promise<void> {\n const auditorEvent = await this.auditor.createEvent({\n eventId: PermissionEvents.POLICY_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.CREATE, source: 'csv-file' },\n });\n\n try {\n await this.enforcer.addPolicies(this.csvFilePolicies.addedPolicies);\n await auditorEvent.success({\n meta: { policies: this.csvFilePolicies.addedPolicies },\n });\n } catch (e) {\n await auditorEvent.fail({\n meta: { policies: this.csvFilePolicies.addedPolicies },\n error: e,\n });\n }\n\n this.csvFilePolicies.addedPolicies = [];\n }\n\n /**\n * removePermissionPolicies will remove the permission policies that are no longer present in the CSV file.\n */\n private async removePermissionPolicies(): Promise<void> {\n const auditorEvent = await this.auditor.createEvent({\n eventId: PermissionEvents.POLICY_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.DELETE, source: 'csv-file' },\n });\n\n try {\n await this.enforcer.removePolicies(this.csvFilePolicies.removedPolicies);\n await auditorEvent.success({\n meta: { policies: this.csvFilePolicies.removedPolicies },\n });\n } catch (e) {\n await auditorEvent.fail({\n meta: { policies: this.csvFilePolicies.removedPolicies },\n error: e,\n });\n }\n\n this.csvFilePolicies.removedPolicies = [];\n }\n\n /**\n * addRoles will add the new roles that are present in the CSV file.\n */\n private async addRoles(): Promise<void> {\n const changedPolicies: {\n addedPolicies: string[][];\n updatedPolicies: string[][];\n failedPolicies: { error: string; policies: string[][] }[];\n } = {\n addedPolicies: [],\n updatedPolicies: [],\n failedPolicies: [],\n };\n\n const auditorEvent = await this.auditor.createEvent({\n eventId: RoleEvents.ROLE_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.CREATE_OR_UPDATE, source: 'csv-file' },\n });\n\n for (const [key, value] of this.csvFilePolicies.addedGroupPolicies) {\n const groupPolicies = value.map(member => {\n return [member, key];\n });\n\n const roleMetadata: RoleMetadataDao = {\n source: 'csv-file',\n roleEntityRef: key,\n author: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n };\n\n try {\n const currentMetadata = await this.roleMetadataStorage.findRoleMetadata(\n roleMetadata.roleEntityRef,\n );\n\n await this.enforcer.addGroupingPolicies(groupPolicies, roleMetadata);\n\n if (currentMetadata) {\n changedPolicies.updatedPolicies.push(...groupPolicies);\n } else {\n changedPolicies.addedPolicies.push(...groupPolicies);\n }\n } catch (e) {\n changedPolicies.failedPolicies.push({\n error: e,\n policies: groupPolicies,\n });\n }\n }\n\n if (changedPolicies.failedPolicies.length > 0) {\n await auditorEvent.fail({\n error: new Error(\n `Failed to add or update group policies after modification ${this.filePath}.`,\n ),\n meta: { ...changedPolicies },\n });\n } else {\n await auditorEvent.success({\n meta: {\n addedPolicies: changedPolicies.addedPolicies,\n updatedPolicies: changedPolicies.updatedPolicies,\n },\n });\n }\n\n this.csvFilePolicies.addedGroupPolicies = new Map<string, string[]>();\n }\n\n /**\n * removeRoles will remove the roles that are no longer present in the CSV file.\n * If the role exists with multiple groups and or users, we will update it role information.\n * Otherwise, we will remove the role completely.\n */\n private async removeRoles(): Promise<void> {\n for (const [key, value] of this.csvFilePolicies.removedGroupPolicies) {\n // This requires knowledge of whether or not it is an update\n const oldGroupingPolicies = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n key,\n );\n const groupPolicies = value.map(member => {\n return [member, key];\n });\n\n const roleMetadata: RoleMetadataDao = {\n source: 'csv-file',\n roleEntityRef: key,\n author: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n modifiedBy: CSV_PERMISSION_POLICY_FILE_AUTHOR,\n };\n const isUpdate =\n oldGroupingPolicies.length > 1 &&\n oldGroupingPolicies.length !== groupPolicies.length;\n const actionType = isUpdate ? ActionType.UPDATE : ActionType.DELETE;\n\n const meta = {\n ...roleMetadata,\n members: value,\n };\n const auditorEvent = await this.auditor.createEvent({\n eventId: RoleEvents.ROLE_WRITE,\n severityLevel: 'medium',\n meta: { actionType, source: meta.source },\n });\n\n try {\n await this.enforcer.removeGroupingPolicies(\n groupPolicies,\n roleMetadata,\n isUpdate,\n );\n await auditorEvent.success({ meta });\n } catch (e) {\n await auditorEvent.fail({\n meta,\n error: e,\n });\n }\n }\n\n this.csvFilePolicies.removedGroupPolicies = new Map<string, string[]>();\n }\n\n async cleanUpRolesAndPolicies(): Promise<void> {\n const roleMetadatas =\n await this.roleMetadataStorage.filterRoleMetadata('csv-file');\n const fileRoles = roleMetadatas.map(meta => meta.roleEntityRef);\n\n if (fileRoles.length > 0) {\n for (const fileRole of fileRoles) {\n const filteredPolicies = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n fileRole,\n );\n for (const groupPolicy of filteredPolicies) {\n this.addGroupPolicyToMap(\n this.csvFilePolicies.removedGroupPolicies,\n groupPolicy[1],\n groupPolicy[0],\n );\n }\n this.csvFilePolicies.removedPolicies.push(\n ...(await this.enforcer.getFilteredPolicy(0, fileRole)),\n );\n }\n }\n await this.removePermissionPolicies();\n await this.removeRoles();\n }\n\n async filterPoliciesAndRoles(\n enforcerOne: Enforcer | EnforcerDelegate,\n enforcerTwo: Enforcer | EnforcerDelegate,\n policies: string[][],\n groupPolicies: Map<string, string[]>,\n remove?: boolean,\n ) {\n // Check for any policies that need to be edited by comparing policies from\n // one enforcer to the other\n const policiesToEdit = await enforcerOne.getPolicy();\n const groupPoliciesToEdit = await enforcerOne.getGroupingPolicy();\n\n for (const policy of policiesToEdit) {\n if (\n !(await enforcerTwo.hasPolicy(...policy)) &&\n (await this.validateAddedPolicy(\n policy,\n enforcerOne as Enforcer,\n remove,\n ))\n ) {\n policies.push(policy);\n }\n }\n\n for (const groupPolicy of groupPoliciesToEdit) {\n if (\n !(await enforcerTwo.hasGroupingPolicy(...groupPolicy)) &&\n (await this.validateAddedGroupPolicy(\n groupPolicy,\n enforcerOne as Enforcer,\n remove,\n ))\n ) {\n this.addGroupPolicyToMap(groupPolicies, groupPolicy[1], groupPolicy[0]);\n }\n }\n }\n\n async validateAddedPolicy(\n policy: string[],\n tempEnforcer: Enforcer,\n remove?: boolean,\n ): Promise<boolean> {\n const transformedPolicy = transformArrayToPolicy(policy);\n const metadata = await this.roleMetadataStorage.findRoleMetadata(policy[0]);\n\n if (remove) {\n return metadata?.source === 'csv-file';\n }\n\n let err = validatePolicy(transformedPolicy);\n if (err) {\n this.logger.warn(\n `Failed to validate policy from file ${this.filePath}. Cause: ${err.message}`,\n );\n return false;\n }\n\n err = await validateSource('csv-file', metadata);\n if (err) {\n this.logger.warn(\n `Unable to add policy ${policy} from file ${this.filePath}. Cause: ${err.message}`,\n );\n return false;\n }\n\n err = await checkForDuplicatePolicies(tempEnforcer, policy, this.filePath!);\n if (err) {\n this.logger.warn(err.message);\n return false;\n }\n\n return true;\n }\n\n async validateAddedGroupPolicy(\n groupPolicy: string[],\n tempEnforcer: Enforcer,\n remove?: boolean,\n ): Promise<boolean> {\n const metadata = await this.roleMetadataStorage.findRoleMetadata(\n groupPolicy[1],\n );\n\n if (remove) {\n return metadata?.source === 'csv-file';\n }\n\n let err = await validateGroupingPolicy(groupPolicy, metadata, 'csv-file');\n if (err) {\n this.logger.warn(\n `${err.message}, error originates from file ${this.filePath}`,\n );\n return false;\n }\n\n err = await checkForDuplicateGroupPolicies(\n tempEnforcer,\n groupPolicy,\n this.filePath!,\n );\n if (err) {\n this.logger.warn(err.message);\n return false;\n }\n\n return true;\n }\n\n async findFileContentDiff(\n currentFlatContent: string[],\n newFlatContent: string[],\n tempEnforcer: Enforcer,\n ) {\n const diffRemoved = difference(currentFlatContent, newFlatContent); // policy was removed\n const diffAdded = difference(newFlatContent, currentFlatContent); // policy was added\n\n await this.migrateLegacyMetadata(tempEnforcer);\n\n if (diffRemoved.length === 0 && diffAdded.length === 0) {\n return;\n }\n\n diffRemoved.forEach(policy => {\n const convertedPolicy = metadataStringToPolicy(policy);\n if (convertedPolicy[0] === 'p') {\n convertedPolicy.splice(0, 1);\n this.csvFilePolicies.removedPolicies.push(convertedPolicy);\n } else if (convertedPolicy[0] === 'g') {\n convertedPolicy.splice(0, 1);\n this.addGroupPolicyToMap(\n this.csvFilePolicies.removedGroupPolicies,\n convertedPolicy[1],\n convertedPolicy[0],\n );\n }\n });\n\n for (const policy of diffAdded) {\n const convertedPolicy = metadataStringToPolicy(policy);\n if (convertedPolicy[0] === 'p') {\n convertedPolicy.splice(0, 1);\n if (await this.validateAddedPolicy(convertedPolicy, tempEnforcer))\n this.csvFilePolicies.addedPolicies.push(convertedPolicy);\n } else if (convertedPolicy[0] === 'g') {\n convertedPolicy.splice(0, 1);\n if (await this.validateAddedGroupPolicy(convertedPolicy, tempEnforcer))\n this.addGroupPolicyToMap(\n this.csvFilePolicies.addedGroupPolicies,\n convertedPolicy[1],\n convertedPolicy[0],\n );\n }\n }\n }\n\n addGroupPolicyToMap(\n groupPolicyMap: Map<string, string[]>,\n key: string,\n value: string,\n ) {\n if (!groupPolicyMap.has(key)) {\n groupPolicyMap.set(key, []);\n }\n groupPolicyMap.get(key)?.push(value);\n }\n}\n"],"names":["AbstractFileWatcher","parse","transformPolicyGroupToLowercase","newEnforcer","newModelFromString","MODEL","LowercaseFileAdapter","mergeRoleMetadata","policyToString","PermissionEvents","ActionType","RoleEvents","transformArrayToPolicy","validatePolicy","validateSource","checkForDuplicatePolicies","validateGroupingPolicy","checkForDuplicateGroupPolicies","difference","metadataStringToPolicy"],"mappings":";;;;;;;;;;;;AAgDO,MAAM,iCAAoC,GAAA;AAS1C,MAAM,uBAAuBA,+BAAgC,CAAA;AAAA,EAIlE,YACE,QACA,EAAA,WAAA,EACA,MACiB,EAAA,QAAA,EACA,qBACA,OACjB,EAAA;AACA,IAAM,KAAA,CAAA,QAAA,EAAU,aAAa,MAAM,CAAA;AAJlB,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,mBAAA,GAAA,mBAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGjB,IAAA,IAAA,CAAK,iBAAiB,EAAC;AACvB,IAAA,IAAA,CAAK,eAAkB,GAAA;AAAA,MACrB,eAAe,EAAC;AAAA,MAChB,iBAAiB,EAAC;AAAA,MAClB,kBAAA,sBAAwB,GAAsB,EAAA;AAAA,MAC9C,oBAAA,sBAA0B,GAAsB;AAAA,KAClD;AAAA;AACF,EAnBQ,cAAA;AAAA,EACA,eAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBR,KAAoB,GAAA;AAClB,IAAM,MAAA,OAAA,GAAU,KAAK,kBAAmB,EAAA;AACxC,IAAM,MAAA,IAAA,GAAOC,WAAM,OAAS,EAAA;AAAA,MAC1B,gBAAkB,EAAA,IAAA;AAAA,MAClB,kBAAoB,EAAA,IAAA;AAAA,MACpB,IAAM,EAAA;AAAA,KACP,CAAA;AAED,IAAA,KAAA,MAAW,UAAU,IAAM,EAAA;AACzB,MAAAC,sCAAA,CAAgC,MAAM,CAAA;AAAA;AAGxC,IAAO,OAAA,IAAA;AAAA;AACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,UAA4B,GAAA;AAChC,IAAI,IAAA,CAAC,KAAK,QAAU,EAAA;AAClB,MAAA;AAAA;AAEF,IAAA,IAAI,UAAsB,EAAC;AAE3B,IAAA,OAAA,GAAU,KAAK,KAAM,EAAA;AAErB,IAAA,MAAM,eAAe,MAAMC,kBAAA;AAAA,MACzBC,0BAAmBC,qBAAK,CAAA;AAAA,MACxB,IAAIC,yCAAqB,CAAA,IAAA,CAAK,QAAQ;AAAA,KACxC;AAGA,IAAA,MAAM,IAAK,CAAA,sBAAA;AAAA,MACT,IAAK,CAAA,QAAA;AAAA,MACL,YAAA;AAAA,MACA,KAAK,eAAgB,CAAA,eAAA;AAAA,MACrB,KAAK,eAAgB,CAAA,oBAAA;AAAA,MACrB;AAAA,KACF;AAEA,IAAA,MAAM,IAAK,CAAA,sBAAA;AAAA,MACT,YAAA;AAAA,MACA,IAAK,CAAA,QAAA;AAAA,MACL,KAAK,eAAgB,CAAA,aAAA;AAAA,MACrB,KAAK,eAAgB,CAAA;AAAA,KACvB;AAEA,IAAM,MAAA,IAAA,CAAK,sBAAsB,YAAY,CAAA;AAG7C,IAAM,MAAA,IAAA,CAAK,eAAe,OAAO,CAAA;AAEjC,IAAA,IAAI,KAAK,WAAa,EAAA;AACpB,MAAA,IAAA,CAAK,SAAU,EAAA;AAAA;AACjB;AACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,sBAAsB,YAAwB,EAAA;AAC1D,IAAA,IAAI,mBACF,GAAA,MAAM,IAAK,CAAA,mBAAA,CAAoB,mBAAmB,QAAQ,CAAA;AAC5D,IAAA,MAAM,WAAc,GAAA,mBAAA,CAAoB,GAAI,CAAA,CAAA,IAAA,KAAQ,KAAK,aAAa,CAAA;AACtE,IAAI,IAAA,WAAA,CAAY,SAAS,CAAG,EAAA;AAC1B,MAAM,MAAA,mBAAA,GAAsB,MAAM,YAAa,CAAA,yBAAA;AAAA,QAC7C,CAAA;AAAA,QACA,GAAG;AAAA,OACL;AACA,MAAM,MAAA,cAAA,GAAiB,MAAM,YAAa,CAAA,iBAAA;AAAA,QACxC,CAAA;AAAA,QACA,GAAG;AAAA,OACL;AACA,MAAM,MAAA,mBAAA,uBAA0B,GAAI,CAAA;AAAA,QAClC,GAAG,mBAAoB,CAAA,GAAA,CAAI,CAAM,EAAA,KAAA,EAAA,CAAG,CAAC,CAAC,CAAA;AAAA,QACtC,GAAG,cAAe,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,CAAC,CAAC;AAAA,OAChC,CAAA;AACD,MAAA,mBAAA,GAAsB,mBAAoB,CAAA,MAAA;AAAA,QAAO,CAC/C,IAAA,KAAA,mBAAA,CAAoB,GAAI,CAAA,IAAA,CAAK,aAAa;AAAA,OAC5C;AACA,MAAA,KAAA,MAAW,kBAAkB,mBAAqB,EAAA;AAChD,QAAM,MAAA,aAAA,GAAgBC,yBAAkB,cAAgB,EAAA;AAAA,UACtD,UAAY,EAAA,iCAAA;AAAA,UACZ,MAAQ,EAAA,UAAA;AAAA,UACR,eAAe,cAAe,CAAA;AAAA,SAC/B,CAAA;AACD,QAAA,MAAM,KAAK,mBAAoB,CAAA,kBAAA;AAAA,UAC7B,aAAA;AAAA,UACA,cAAe,CAAA;AAAA,SACjB;AAAA;AACF;AACF;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAA0B,GAAA;AAC9B,IAAM,MAAA,UAAA,GAAa,KAAK,KAAM,EAAA;AAE9B,IAAA,MAAM,eAAe,MAAMJ,kBAAA;AAAA,MACzBC,0BAAmBC,qBAAK,CAAA;AAAA,MACxB,IAAIC,yCAAqB,CAAA,IAAA,CAAK,QAAS;AAAA,KACzC;AAEA,IAAA,MAAM,kBAAqB,GAAA,IAAA,CAAK,cAAe,CAAA,OAAA,CAAQ,CAAQ,IAAA,KAAA;AAC7D,MAAA,OAAOE,sBAAe,IAAI,CAAA;AAAA,KAC3B,CAAA;AACD,IAAM,MAAA,cAAA,GAAiB,UAAW,CAAA,OAAA,CAAQ,CAAQ,IAAA,KAAA;AAChD,MAAA,OAAOA,sBAAe,IAAI,CAAA;AAAA,KAC3B,CAAA;AAED,IAAA,MAAM,IAAK,CAAA,mBAAA;AAAA,MACT,kBAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAM,MAAA,IAAA,CAAK,eAAe,UAAU,CAAA;AAAA;AACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,eAAe,UAAuC,EAAA;AAClE,IAAA,IAAA,CAAK,cAAiB,GAAA,UAAA;AAEtB,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,aAAA,CAAc,MAAS,GAAA,CAAA;AAC9C,MAAA,MAAM,KAAK,qBAAsB,EAAA;AACnC,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,eAAA,CAAgB,MAAS,GAAA,CAAA;AAChD,MAAA,MAAM,KAAK,wBAAyB,EAAA;AACtC,IAAA,IAAI,KAAK,eAAgB,CAAA,kBAAA,CAAmB,OAAO,CAAG,EAAA,MAAM,KAAK,QAAS,EAAA;AAC1E,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,oBAAA,CAAqB,IAAO,GAAA,CAAA;AACnD,MAAA,MAAM,KAAK,WAAY,EAAA;AAAA;AAC3B;AAAA;AAAA;AAAA,EAKA,MAAc,qBAAuC,GAAA;AACnD,IAAA,MAAM,YAAe,GAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,WAAY,CAAA;AAAA,MAClD,SAASC,wBAAiB,CAAA,YAAA;AAAA,MAC1B,aAAe,EAAA,QAAA;AAAA,MACf,MAAM,EAAE,UAAA,EAAYC,kBAAW,CAAA,MAAA,EAAQ,QAAQ,UAAW;AAAA,KAC3D,CAAA;AAED,IAAI,IAAA;AACF,MAAA,MAAM,IAAK,CAAA,QAAA,CAAS,WAAY,CAAA,IAAA,CAAK,gBAAgB,aAAa,CAAA;AAClE,MAAA,MAAM,aAAa,OAAQ,CAAA;AAAA,QACzB,IAAM,EAAA,EAAE,QAAU,EAAA,IAAA,CAAK,gBAAgB,aAAc;AAAA,OACtD,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAA,MAAM,aAAa,IAAK,CAAA;AAAA,QACtB,IAAM,EAAA,EAAE,QAAU,EAAA,IAAA,CAAK,gBAAgB,aAAc,EAAA;AAAA,QACrD,KAAO,EAAA;AAAA,OACR,CAAA;AAAA;AAGH,IAAK,IAAA,CAAA,eAAA,CAAgB,gBAAgB,EAAC;AAAA;AACxC;AAAA;AAAA;AAAA,EAKA,MAAc,wBAA0C,GAAA;AACtD,IAAA,MAAM,YAAe,GAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,WAAY,CAAA;AAAA,MAClD,SAASD,wBAAiB,CAAA,YAAA;AAAA,MAC1B,aAAe,EAAA,QAAA;AAAA,MACf,MAAM,EAAE,UAAA,EAAYC,kBAAW,CAAA,MAAA,EAAQ,QAAQ,UAAW;AAAA,KAC3D,CAAA;AAED,IAAI,IAAA;AACF,MAAA,MAAM,IAAK,CAAA,QAAA,CAAS,cAAe,CAAA,IAAA,CAAK,gBAAgB,eAAe,CAAA;AACvE,MAAA,MAAM,aAAa,OAAQ,CAAA;AAAA,QACzB,IAAM,EAAA,EAAE,QAAU,EAAA,IAAA,CAAK,gBAAgB,eAAgB;AAAA,OACxD,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAA,MAAM,aAAa,IAAK,CAAA;AAAA,QACtB,IAAM,EAAA,EAAE,QAAU,EAAA,IAAA,CAAK,gBAAgB,eAAgB,EAAA;AAAA,QACvD,KAAO,EAAA;AAAA,OACR,CAAA;AAAA;AAGH,IAAK,IAAA,CAAA,eAAA,CAAgB,kBAAkB,EAAC;AAAA;AAC1C;AAAA;AAAA;AAAA,EAKA,MAAc,QAA0B,GAAA;AACtC,IAAA,MAAM,eAIF,GAAA;AAAA,MACF,eAAe,EAAC;AAAA,MAChB,iBAAiB,EAAC;AAAA,MAClB,gBAAgB;AAAC,KACnB;AAEA,IAAA,MAAM,YAAe,GAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,WAAY,CAAA;AAAA,MAClD,SAASC,kBAAW,CAAA,UAAA;AAAA,MACpB,aAAe,EAAA,QAAA;AAAA,MACf,MAAM,EAAE,UAAA,EAAYD,kBAAW,CAAA,gBAAA,EAAkB,QAAQ,UAAW;AAAA,KACrE,CAAA;AAED,IAAA,KAAA,MAAW,CAAC,GAAK,EAAA,KAAK,CAAK,IAAA,IAAA,CAAK,gBAAgB,kBAAoB,EAAA;AAClE,MAAM,MAAA,aAAA,GAAgB,KAAM,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AACxC,QAAO,OAAA,CAAC,QAAQ,GAAG,CAAA;AAAA,OACpB,CAAA;AAED,MAAA,MAAM,YAAgC,GAAA;AAAA,QACpC,MAAQ,EAAA,UAAA;AAAA,QACR,aAAe,EAAA,GAAA;AAAA,QACf,MAAQ,EAAA,iCAAA;AAAA,QACR,UAAY,EAAA;AAAA,OACd;AAEA,MAAI,IAAA;AACF,QAAM,MAAA,eAAA,GAAkB,MAAM,IAAA,CAAK,mBAAoB,CAAA,gBAAA;AAAA,UACrD,YAAa,CAAA;AAAA,SACf;AAEA,QAAA,MAAM,IAAK,CAAA,QAAA,CAAS,mBAAoB,CAAA,aAAA,EAAe,YAAY,CAAA;AAEnE,QAAA,IAAI,eAAiB,EAAA;AACnB,UAAgB,eAAA,CAAA,eAAA,CAAgB,IAAK,CAAA,GAAG,aAAa,CAAA;AAAA,SAChD,MAAA;AACL,UAAgB,eAAA,CAAA,aAAA,CAAc,IAAK,CAAA,GAAG,aAAa,CAAA;AAAA;AACrD,eACO,CAAG,EAAA;AACV,QAAA,eAAA,CAAgB,eAAe,IAAK,CAAA;AAAA,UAClC,KAAO,EAAA,CAAA;AAAA,UACP,QAAU,EAAA;AAAA,SACX,CAAA;AAAA;AACH;AAGF,IAAI,IAAA,eAAA,CAAgB,cAAe,CAAA,MAAA,GAAS,CAAG,EAAA;AAC7C,MAAA,MAAM,aAAa,IAAK,CAAA;AAAA,QACtB,OAAO,IAAI,KAAA;AAAA,UACT,CAAA,0DAAA,EAA6D,KAAK,QAAQ,CAAA,CAAA;AAAA,SAC5E;AAAA,QACA,IAAA,EAAM,EAAE,GAAG,eAAgB;AAAA,OAC5B,CAAA;AAAA,KACI,MAAA;AACL,MAAA,MAAM,aAAa,OAAQ,CAAA;AAAA,QACzB,IAAM,EAAA;AAAA,UACJ,eAAe,eAAgB,CAAA,aAAA;AAAA,UAC/B,iBAAiB,eAAgB,CAAA;AAAA;AACnC,OACD,CAAA;AAAA;AAGH,IAAK,IAAA,CAAA,eAAA,CAAgB,kBAAqB,mBAAA,IAAI,GAAsB,EAAA;AAAA;AACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,WAA6B,GAAA;AACzC,IAAA,KAAA,MAAW,CAAC,GAAK,EAAA,KAAK,CAAK,IAAA,IAAA,CAAK,gBAAgB,oBAAsB,EAAA;AAEpE,MAAM,MAAA,mBAAA,GAAsB,MAAM,IAAA,CAAK,QAAS,CAAA,yBAAA;AAAA,QAC9C,CAAA;AAAA,QACA;AAAA,OACF;AACA,MAAM,MAAA,aAAA,GAAgB,KAAM,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AACxC,QAAO,OAAA,CAAC,QAAQ,GAAG,CAAA;AAAA,OACpB,CAAA;AAED,MAAA,MAAM,YAAgC,GAAA;AAAA,QACpC,MAAQ,EAAA,UAAA;AAAA,QACR,aAAe,EAAA,GAAA;AAAA,QACf,MAAQ,EAAA,iCAAA;AAAA,QACR,UAAY,EAAA;AAAA,OACd;AACA,MAAA,MAAM,WACJ,mBAAoB,CAAA,MAAA,GAAS,CAC7B,IAAA,mBAAA,CAAoB,WAAW,aAAc,CAAA,MAAA;AAC/C,MAAA,MAAM,UAAa,GAAA,QAAA,GAAWA,kBAAW,CAAA,MAAA,GAASA,kBAAW,CAAA,MAAA;AAE7D,MAAA,MAAM,IAAO,GAAA;AAAA,QACX,GAAG,YAAA;AAAA,QACH,OAAS,EAAA;AAAA,OACX;AACA,MAAA,MAAM,YAAe,GAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,WAAY,CAAA;AAAA,QAClD,SAASC,kBAAW,CAAA,UAAA;AAAA,QACpB,aAAe,EAAA,QAAA;AAAA,QACf,IAAM,EAAA,EAAE,UAAY,EAAA,MAAA,EAAQ,KAAK,MAAO;AAAA,OACzC,CAAA;AAED,MAAI,IAAA;AACF,QAAA,MAAM,KAAK,QAAS,CAAA,sBAAA;AAAA,UAClB,aAAA;AAAA,UACA,YAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,MAAM,YAAa,CAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,CAAA;AAAA,eAC5B,CAAG,EAAA;AACV,QAAA,MAAM,aAAa,IAAK,CAAA;AAAA,UACtB,IAAA;AAAA,UACA,KAAO,EAAA;AAAA,SACR,CAAA;AAAA;AACH;AAGF,IAAK,IAAA,CAAA,eAAA,CAAgB,oBAAuB,mBAAA,IAAI,GAAsB,EAAA;AAAA;AACxE,EAEA,MAAM,uBAAyC,GAAA;AAC7C,IAAA,MAAM,aACJ,GAAA,MAAM,IAAK,CAAA,mBAAA,CAAoB,mBAAmB,UAAU,CAAA;AAC9D,IAAA,MAAM,SAAY,GAAA,aAAA,CAAc,GAAI,CAAA,CAAA,IAAA,KAAQ,KAAK,aAAa,CAAA;AAE9D,IAAI,IAAA,SAAA,CAAU,SAAS,CAAG,EAAA;AACxB,MAAA,KAAA,MAAW,YAAY,SAAW,EAAA;AAChC,QAAM,MAAA,gBAAA,GAAmB,MAAM,IAAA,CAAK,QAAS,CAAA,yBAAA;AAAA,UAC3C,CAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,KAAA,MAAW,eAAe,gBAAkB,EAAA;AAC1C,UAAK,IAAA,CAAA,mBAAA;AAAA,YACH,KAAK,eAAgB,CAAA,oBAAA;AAAA,YACrB,YAAY,CAAC,CAAA;AAAA,YACb,YAAY,CAAC;AAAA,WACf;AAAA;AAEF,QAAA,IAAA,CAAK,gBAAgB,eAAgB,CAAA,IAAA;AAAA,UACnC,GAAI,MAAM,IAAA,CAAK,QAAS,CAAA,iBAAA,CAAkB,GAAG,QAAQ;AAAA,SACvD;AAAA;AACF;AAEF,IAAA,MAAM,KAAK,wBAAyB,EAAA;AACpC,IAAA,MAAM,KAAK,WAAY,EAAA;AAAA;AACzB,EAEA,MAAM,sBACJ,CAAA,WAAA,EACA,WACA,EAAA,QAAA,EACA,eACA,MACA,EAAA;AAGA,IAAM,MAAA,cAAA,GAAiB,MAAM,WAAA,CAAY,SAAU,EAAA;AACnD,IAAM,MAAA,mBAAA,GAAsB,MAAM,WAAA,CAAY,iBAAkB,EAAA;AAEhE,IAAA,KAAA,MAAW,UAAU,cAAgB,EAAA;AACnC,MACE,IAAA,CAAE,MAAM,WAAY,CAAA,SAAA,CAAU,GAAG,MAAM,CAAA,IACtC,MAAM,IAAK,CAAA,mBAAA;AAAA,QACV,MAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OAEF,EAAA;AACA,QAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAAA;AACtB;AAGF,IAAA,KAAA,MAAW,eAAe,mBAAqB,EAAA;AAC7C,MACE,IAAA,CAAE,MAAM,WAAY,CAAA,iBAAA,CAAkB,GAAG,WAAW,CAAA,IACnD,MAAM,IAAK,CAAA,wBAAA;AAAA,QACV,WAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OAEF,EAAA;AACA,QAAA,IAAA,CAAK,oBAAoB,aAAe,EAAA,WAAA,CAAY,CAAC,CAAG,EAAA,WAAA,CAAY,CAAC,CAAC,CAAA;AAAA;AACxE;AACF;AACF,EAEA,MAAM,mBAAA,CACJ,MACA,EAAA,YAAA,EACA,MACkB,EAAA;AAClB,IAAM,MAAA,iBAAA,GAAoBC,8BAAuB,MAAM,CAAA;AACvD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,oBAAoB,gBAAiB,CAAA,MAAA,CAAO,CAAC,CAAC,CAAA;AAE1E,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,OAAO,UAAU,MAAW,KAAA,UAAA;AAAA;AAG9B,IAAI,IAAA,GAAA,GAAMC,kCAAe,iBAAiB,CAAA;AAC1C,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,CAAuC,oCAAA,EAAA,IAAA,CAAK,QAAQ,CAAA,SAAA,EAAY,IAAI,OAAO,CAAA;AAAA,OAC7E;AACA,MAAO,OAAA,KAAA;AAAA;AAGT,IAAM,GAAA,GAAA,MAAMC,iCAAe,CAAA,UAAA,EAAY,QAAQ,CAAA;AAC/C,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,wBAAwB,MAAM,CAAA,WAAA,EAAc,KAAK,QAAQ,CAAA,SAAA,EAAY,IAAI,OAAO,CAAA;AAAA,OAClF;AACA,MAAO,OAAA,KAAA;AAAA;AAGT,IAAA,GAAA,GAAM,MAAMC,4CAAA,CAA0B,YAAc,EAAA,MAAA,EAAQ,KAAK,QAAS,CAAA;AAC1E,IAAA,IAAI,GAAK,EAAA;AACP,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA;AAC5B,MAAO,OAAA,KAAA;AAAA;AAGT,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,wBAAA,CACJ,WACA,EAAA,YAAA,EACA,MACkB,EAAA;AAClB,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,mBAAoB,CAAA,gBAAA;AAAA,MAC9C,YAAY,CAAC;AAAA,KACf;AAEA,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,OAAO,UAAU,MAAW,KAAA,UAAA;AAAA;AAG9B,IAAA,IAAI,GAAM,GAAA,MAAMC,yCAAuB,CAAA,WAAA,EAAa,UAAU,UAAU,CAAA;AACxE,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,QACV,CAAG,EAAA,GAAA,CAAI,OAAO,CAAA,6BAAA,EAAgC,KAAK,QAAQ,CAAA;AAAA,OAC7D;AACA,MAAO,OAAA,KAAA;AAAA;AAGT,IAAA,GAAA,GAAM,MAAMC,iDAAA;AAAA,MACV,YAAA;AAAA,MACA,WAAA;AAAA,MACA,IAAK,CAAA;AAAA,KACP;AACA,IAAA,IAAI,GAAK,EAAA;AACP,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA;AAC5B,MAAO,OAAA,KAAA;AAAA;AAGT,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,mBAAA,CACJ,kBACA,EAAA,cAAA,EACA,YACA,EAAA;AACA,IAAM,MAAA,WAAA,GAAcC,iBAAW,CAAA,kBAAA,EAAoB,cAAc,CAAA;AACjE,IAAM,MAAA,SAAA,GAAYA,iBAAW,CAAA,cAAA,EAAgB,kBAAkB,CAAA;AAE/D,IAAM,MAAA,IAAA,CAAK,sBAAsB,YAAY,CAAA;AAE7C,IAAA,IAAI,WAAY,CAAA,MAAA,KAAW,CAAK,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AACtD,MAAA;AAAA;AAGF,IAAA,WAAA,CAAY,QAAQ,CAAU,MAAA,KAAA;AAC5B,MAAM,MAAA,eAAA,GAAkBC,8BAAuB,MAAM,CAAA;AACrD,MAAI,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AAC9B,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAK,IAAA,CAAA,eAAA,CAAgB,eAAgB,CAAA,IAAA,CAAK,eAAe,CAAA;AAAA,OAChD,MAAA,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AACrC,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAK,IAAA,CAAA,mBAAA;AAAA,UACH,KAAK,eAAgB,CAAA,oBAAA;AAAA,UACrB,gBAAgB,CAAC,CAAA;AAAA,UACjB,gBAAgB,CAAC;AAAA,SACnB;AAAA;AACF,KACD,CAAA;AAED,IAAA,KAAA,MAAW,UAAU,SAAW,EAAA;AAC9B,MAAM,MAAA,eAAA,GAAkBA,8BAAuB,MAAM,CAAA;AACrD,MAAI,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AAC9B,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAA,IAAI,MAAM,IAAA,CAAK,mBAAoB,CAAA,eAAA,EAAiB,YAAY,CAAA;AAC9D,UAAK,IAAA,CAAA,eAAA,CAAgB,aAAc,CAAA,IAAA,CAAK,eAAe,CAAA;AAAA,OAChD,MAAA,IAAA,eAAA,CAAgB,CAAC,CAAA,KAAM,GAAK,EAAA;AACrC,QAAgB,eAAA,CAAA,MAAA,CAAO,GAAG,CAAC,CAAA;AAC3B,QAAA,IAAI,MAAM,IAAA,CAAK,wBAAyB,CAAA,eAAA,EAAiB,YAAY,CAAA;AACnE,UAAK,IAAA,CAAA,mBAAA;AAAA,YACH,KAAK,eAAgB,CAAA,kBAAA;AAAA,YACrB,gBAAgB,CAAC,CAAA;AAAA,YACjB,gBAAgB,CAAC;AAAA,WACnB;AAAA;AACJ;AACF;AACF,EAEA,mBAAA,CACE,cACA,EAAA,GAAA,EACA,KACA,EAAA;AACA,IAAA,IAAI,CAAC,cAAA,CAAe,GAAI,CAAA,GAAG,CAAG,EAAA;AAC5B,MAAe,cAAA,CAAA,GAAA,CAAI,GAAK,EAAA,EAAE,CAAA;AAAA;AAE5B,IAAA,cAAA,CAAe,GAAI,CAAA,GAAG,CAAG,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA;AAEvC;;;;;"}
@@ -3,7 +3,7 @@
3
3
  var yaml = require('js-yaml');
4
4
  var lodash = require('lodash');
5
5
  var fs = require('fs');
6
- var auditLogger = require('../audit-log/audit-logger.cjs.js');
6
+ var auditor = require('../auditor/auditor.cjs.js');
7
7
  var helper = require('../helper.cjs.js');
8
8
  var conditionValidation = require('../validation/condition-validation.cjs.js');
9
9
  var fileWatcher = require('./file-watcher.cjs.js');
@@ -14,10 +14,10 @@ var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
14
14
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
15
15
 
16
16
  class YamlConditinalPoliciesFileWatcher extends fileWatcher.AbstractFileWatcher {
17
- constructor(filePath, allowReload, logger, conditionalStorage, auditLogger, auth, pluginMetadataCollector, roleMetadataStorage, roleEventEmitter) {
17
+ constructor(filePath, allowReload, logger, conditionalStorage, auditor, auth, pluginMetadataCollector, roleMetadataStorage, roleEventEmitter) {
18
18
  super(filePath, allowReload, logger);
19
19
  this.conditionalStorage = conditionalStorage;
20
- this.auditLogger = auditLogger;
20
+ this.auditor = auditor;
21
21
  this.auth = auth;
22
22
  this.pluginMetadataCollector = pluginMetadataCollector;
23
23
  this.roleMetadataStorage = roleMetadataStorage;
@@ -34,12 +34,13 @@ class YamlConditinalPoliciesFileWatcher extends fileWatcher.AbstractFileWatcher
34
34
  }
35
35
  const fileExists = fs__default.default.existsSync(this.filePath);
36
36
  if (!fileExists) {
37
- const err = new Error(`File '${this.filePath}' was not found`);
38
- this.handleError(
39
- err.message,
40
- err,
41
- auditLogger.ConditionEvents.CONDITIONAL_POLICIES_FILE_NOT_FOUND
42
- );
37
+ const auditorEvent = await this.auditor.createEvent({
38
+ eventId: auditor.ConditionEvents.CONDITIONAL_POLICIES_FILE_NOT_FOUND,
39
+ severityLevel: "medium"
40
+ });
41
+ await auditorEvent.fail({
42
+ error: new Error(`File '${this.filePath}' was not found`)
43
+ });
43
44
  return;
44
45
  }
45
46
  this.roleEventEmitter.on("roleAdded", this.onChange.bind(this));
@@ -98,11 +99,13 @@ class YamlConditinalPoliciesFileWatcher extends fileWatcher.AbstractFileWatcher
98
99
  };
99
100
  await this.handleFileChanges();
100
101
  } catch (error) {
101
- await this.handleError(
102
- `Error handling changes from conditional policies file ${this.filePath}`,
103
- error,
104
- auditLogger.ConditionEvents.CHANGE_CONDITIONAL_POLICIES_FILE_ERROR
105
- );
102
+ const auditorEvent = await this.auditor.createEvent({
103
+ eventId: auditor.ConditionEvents.CONDITIONAL_POLICIES_FILE_CHANGE,
104
+ severityLevel: "medium"
105
+ });
106
+ await auditorEvent.fail({
107
+ error
108
+ });
106
109
  }
107
110
  }
108
111
  /**
@@ -124,34 +127,36 @@ class YamlConditinalPoliciesFileWatcher extends fileWatcher.AbstractFileWatcher
124
127
  await this.addConditions();
125
128
  }
126
129
  async addConditions() {
127
- try {
128
- for (const condition of this.conditionsDiff.addedConditions) {
130
+ for (const condition of this.conditionsDiff.addedConditions) {
131
+ const auditorEvent = await this.auditor.createEvent({
132
+ eventId: auditor.ConditionEvents.CONDITION_WRITE,
133
+ severityLevel: "medium",
134
+ meta: { actionType: auditor.ActionType.CREATE }
135
+ });
136
+ try {
129
137
  const conditionToCreate = await helper.processConditionMapping(
130
138
  condition,
131
139
  this.pluginMetadataCollector,
132
140
  this.auth
133
141
  );
134
142
  await this.conditionalStorage.createCondition(conditionToCreate);
135
- await this.auditLogger.auditLog({
136
- message: `Created conditional permission policy`,
137
- eventName: auditLogger.ConditionEvents.CREATE_CONDITION,
138
- metadata: { condition },
139
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
140
- status: "succeeded"
143
+ await auditorEvent.success({
144
+ meta: { condition }
141
145
  });
146
+ } catch (error) {
147
+ await auditorEvent.fail({ error, meta: { condition } });
142
148
  }
143
- } catch (error) {
144
- await this.handleError(
145
- "Failed to create condition",
146
- error,
147
- auditLogger.ConditionEvents.CREATE_CONDITION_ERROR
148
- );
149
149
  }
150
150
  this.conditionsDiff.addedConditions = [];
151
151
  }
152
152
  async removeConditions() {
153
- try {
154
- for (const condition of this.conditionsDiff.removedConditions) {
153
+ for (const condition of this.conditionsDiff.removedConditions) {
154
+ const auditorEvent = await this.auditor.createEvent({
155
+ eventId: auditor.ConditionEvents.CONDITION_WRITE,
156
+ severityLevel: "medium",
157
+ meta: { actionType: auditor.ActionType.DELETE }
158
+ });
159
+ try {
155
160
  const conditionToDelete = (await this.conditionalStorage.filterConditions(
156
161
  condition.roleEntityRef,
157
162
  condition.pluginId,
@@ -159,32 +164,16 @@ class YamlConditinalPoliciesFileWatcher extends fileWatcher.AbstractFileWatcher
159
164
  condition.permissionMapping
160
165
  ))[0];
161
166
  await this.conditionalStorage.deleteCondition(conditionToDelete.id);
162
- await this.auditLogger.auditLog({
163
- message: `Deleted conditional permission policy`,
164
- eventName: auditLogger.ConditionEvents.DELETE_CONDITION,
165
- metadata: { condition },
166
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
167
- status: "succeeded"
167
+ await auditorEvent.success({ meta: { condition } });
168
+ } catch (error) {
169
+ await auditorEvent.fail({
170
+ error,
171
+ meta: { condition }
168
172
  });
169
173
  }
170
- } catch (error) {
171
- await this.handleError(
172
- "Failed to delete condition by id",
173
- error,
174
- auditLogger.ConditionEvents.DELETE_CONDITION_ERROR
175
- );
176
174
  }
177
175
  this.conditionsDiff.removedConditions = [];
178
176
  }
179
- async handleError(message, error, event) {
180
- await this.auditLogger.auditLog({
181
- message,
182
- eventName: event,
183
- stage: auditLogger.HANDLE_RBAC_DATA_STAGE,
184
- status: "failed",
185
- errors: [error]
186
- });
187
- }
188
177
  async cleanUpConditionalPolicies() {
189
178
  const csvFileRoles = await this.roleMetadataStorage.filterRoleMetadata("csv-file");
190
179
  const existedFileConds = (await this.conditionalStorage.filterConditions(
@@ -1 +1 @@
1
- {"version":3,"file":"yaml-conditional-file-watcher.cjs.js","sources":["../../src/file-permissions/yaml-conditional-file-watcher.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';\n\nimport type { AuditLogger } from '@janus-idp/backstage-plugin-audit-log-node';\nimport yaml from 'js-yaml';\nimport { omit } from 'lodash';\n\nimport type {\n PermissionAction,\n RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\n\nimport fs from 'fs';\n\nimport {\n ConditionAuditInfo,\n ConditionEvents,\n HANDLE_RBAC_DATA_STAGE,\n} from '../audit-log/audit-logger';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport { RoleMetadataStorage } from '../database/role-metadata';\nimport { deepSortEqual, processConditionMapping } from '../helper';\nimport { RoleEventEmitter, RoleEvents } from '../service/enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from '../service/plugin-endpoints';\nimport { validateRoleCondition } from '../validation/condition-validation';\nimport { AbstractFileWatcher } from './file-watcher';\n\ntype ConditionalPoliciesDiff = {\n addedConditions: RoleConditionalPolicyDecision<PermissionAction>[];\n removedConditions: RoleConditionalPolicyDecision<PermissionAction>[];\n};\n\nexport class YamlConditinalPoliciesFileWatcher extends AbstractFileWatcher<\n RoleConditionalPolicyDecision<PermissionAction>[]\n> {\n private conditionsDiff: ConditionalPoliciesDiff;\n\n constructor(\n filePath: string | undefined,\n allowReload: boolean,\n logger: LoggerService,\n private readonly conditionalStorage: ConditionalStorage,\n private readonly auditLogger: AuditLogger,\n private readonly auth: AuthService,\n private readonly pluginMetadataCollector: PluginPermissionMetadataCollector,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly roleEventEmitter: RoleEventEmitter<RoleEvents>,\n ) {\n super(filePath, allowReload, logger);\n\n this.conditionsDiff = {\n addedConditions: [],\n removedConditions: [],\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.filePath) {\n return;\n }\n const fileExists = fs.existsSync(this.filePath);\n if (!fileExists) {\n const err = new Error(`File '${this.filePath}' was not found`);\n this.handleError(\n err.message,\n err,\n ConditionEvents.CONDITIONAL_POLICIES_FILE_NOT_FOUND,\n );\n return;\n }\n\n this.roleEventEmitter.on('roleAdded', this.onChange.bind(this));\n await this.onChange();\n\n if (this.allowReload) {\n this.watchFile();\n }\n }\n\n async onChange(): Promise<void> {\n try {\n const newConds = this.parse().filter(c => c);\n\n const addedConds: RoleConditionalPolicyDecision<PermissionAction>[] = [];\n const removedConds: RoleConditionalPolicyDecision<PermissionAction>[] =\n [];\n\n const csvFileRoles =\n await this.roleMetadataStorage.filterRoleMetadata('csv-file');\n const existedFileConds = (\n await this.conditionalStorage.filterConditions(\n csvFileRoles.map(role => role.roleEntityRef),\n )\n ).map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n });\n\n // Find added conditions\n for (const condition of newConds) {\n const roleMetadata = csvFileRoles.find(\n role => condition.roleEntityRef === role.roleEntityRef,\n );\n if (!roleMetadata) {\n this.logger.warn(\n `skip to add condition for role '${condition.roleEntityRef}'. The role either does not exist or was not created from a CSV file.`,\n );\n continue;\n }\n if (roleMetadata.source !== 'csv-file') {\n this.logger.warn(\n `skip to add condition for role '${condition.roleEntityRef}'. Role is not from csv-file`,\n );\n continue;\n }\n\n const existingCondition = existedFileConds.find(c =>\n deepSortEqual(omit(c, ['id']), omit(condition, ['id'])),\n );\n\n if (!existingCondition) {\n addedConds.push(condition);\n }\n }\n\n // Find removed conditions\n for (const condition of existedFileConds) {\n if (\n !newConds.find(c =>\n deepSortEqual(omit(c, ['id']), omit(condition, ['id'])),\n )\n ) {\n removedConds.push(condition);\n }\n }\n\n this.conditionsDiff = {\n addedConditions: addedConds,\n removedConditions: removedConds,\n };\n\n await this.handleFileChanges();\n } catch (error) {\n await this.handleError(\n `Error handling changes from conditional policies file ${this.filePath}`,\n error,\n ConditionEvents.CHANGE_CONDITIONAL_POLICIES_FILE_ERROR,\n );\n }\n }\n\n /**\n * Reads the current contents of the file and parses it.\n * @returns parsed data.\n */\n parse(): RoleConditionalPolicyDecision<PermissionAction>[] {\n const fileContents = this.getCurrentContents();\n const data = yaml.loadAll(\n fileContents,\n ) as RoleConditionalPolicyDecision<PermissionAction>[];\n\n for (const condition of data) {\n validateRoleCondition(condition);\n }\n\n return data;\n }\n\n private async handleFileChanges(): Promise<void> {\n await this.removeConditions();\n await this.addConditions();\n }\n\n private async addConditions(): Promise<void> {\n try {\n for (const condition of this.conditionsDiff.addedConditions) {\n const conditionToCreate = await processConditionMapping(\n condition,\n this.pluginMetadataCollector,\n this.auth,\n );\n\n await this.conditionalStorage.createCondition(conditionToCreate);\n\n await this.auditLogger.auditLog<ConditionAuditInfo>({\n message: `Created conditional permission policy`,\n eventName: ConditionEvents.CREATE_CONDITION,\n metadata: { condition },\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'succeeded',\n });\n }\n } catch (error) {\n await this.handleError(\n 'Failed to create condition',\n error,\n ConditionEvents.CREATE_CONDITION_ERROR,\n );\n }\n this.conditionsDiff.addedConditions = [];\n }\n\n private async removeConditions(): Promise<void> {\n try {\n for (const condition of this.conditionsDiff.removedConditions) {\n const conditionToDelete = (\n await this.conditionalStorage.filterConditions(\n condition.roleEntityRef,\n condition.pluginId,\n condition.resourceType,\n condition.permissionMapping,\n )\n )[0];\n await this.conditionalStorage.deleteCondition(conditionToDelete.id!);\n\n await this.auditLogger.auditLog<ConditionAuditInfo>({\n message: `Deleted conditional permission policy`,\n eventName: ConditionEvents.DELETE_CONDITION,\n metadata: { condition },\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'succeeded',\n });\n }\n } catch (error) {\n await this.handleError(\n 'Failed to delete condition by id',\n error,\n ConditionEvents.DELETE_CONDITION_ERROR,\n );\n }\n\n this.conditionsDiff.removedConditions = [];\n }\n\n private async handleError(\n message: string,\n error: unknown,\n event: string,\n ): Promise<void> {\n await this.auditLogger.auditLog({\n message,\n eventName: event,\n stage: HANDLE_RBAC_DATA_STAGE,\n status: 'failed',\n errors: [error],\n });\n }\n\n async cleanUpConditionalPolicies(): Promise<void> {\n const csvFileRoles =\n await this.roleMetadataStorage.filterRoleMetadata('csv-file');\n const existedFileConds = (\n await this.conditionalStorage.filterConditions(\n csvFileRoles.map(role => role.roleEntityRef),\n )\n ).map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n });\n this.conditionsDiff.removedConditions = existedFileConds;\n await this.removeConditions();\n }\n}\n"],"names":["AbstractFileWatcher","fs","ConditionEvents","deepSortEqual","omit","yaml","validateRoleCondition","processConditionMapping","HANDLE_RBAC_DATA_STAGE"],"mappings":"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"}
1
+ {"version":3,"file":"yaml-conditional-file-watcher.cjs.js","sources":["../../src/file-permissions/yaml-conditional-file-watcher.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 AuthService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\nimport yaml from 'js-yaml';\nimport { omit } from 'lodash';\n\nimport type {\n PermissionAction,\n RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\n\nimport fs from 'fs';\n\nimport { ActionType, ConditionEvents } from '../auditor/auditor';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport { RoleMetadataStorage } from '../database/role-metadata';\nimport { deepSortEqual, processConditionMapping } from '../helper';\nimport { RoleEventEmitter, RoleEvents } from '../service/enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from '../service/plugin-endpoints';\nimport { validateRoleCondition } from '../validation/condition-validation';\nimport { AbstractFileWatcher } from './file-watcher';\n\ntype ConditionalPoliciesDiff = {\n addedConditions: RoleConditionalPolicyDecision<PermissionAction>[];\n removedConditions: RoleConditionalPolicyDecision<PermissionAction>[];\n};\n\nexport class YamlConditinalPoliciesFileWatcher extends AbstractFileWatcher<\n RoleConditionalPolicyDecision<PermissionAction>[]\n> {\n private conditionsDiff: ConditionalPoliciesDiff;\n\n constructor(\n filePath: string | undefined,\n allowReload: boolean,\n logger: LoggerService,\n private readonly conditionalStorage: ConditionalStorage,\n private readonly auditor: AuditorService,\n private readonly auth: AuthService,\n private readonly pluginMetadataCollector: PluginPermissionMetadataCollector,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly roleEventEmitter: RoleEventEmitter<RoleEvents>,\n ) {\n super(filePath, allowReload, logger);\n\n this.conditionsDiff = {\n addedConditions: [],\n removedConditions: [],\n };\n }\n\n async initialize(): Promise<void> {\n if (!this.filePath) {\n return;\n }\n const fileExists = fs.existsSync(this.filePath);\n if (!fileExists) {\n const auditorEvent = await this.auditor.createEvent({\n eventId: ConditionEvents.CONDITIONAL_POLICIES_FILE_NOT_FOUND,\n severityLevel: 'medium',\n });\n await auditorEvent.fail({\n error: new Error(`File '${this.filePath}' was not found`),\n });\n return;\n }\n\n this.roleEventEmitter.on('roleAdded', this.onChange.bind(this));\n await this.onChange();\n\n if (this.allowReload) {\n this.watchFile();\n }\n }\n\n async onChange(): Promise<void> {\n try {\n const newConds = this.parse().filter(c => c);\n\n const addedConds: RoleConditionalPolicyDecision<PermissionAction>[] = [];\n const removedConds: RoleConditionalPolicyDecision<PermissionAction>[] =\n [];\n\n const csvFileRoles =\n await this.roleMetadataStorage.filterRoleMetadata('csv-file');\n const existedFileConds = (\n await this.conditionalStorage.filterConditions(\n csvFileRoles.map(role => role.roleEntityRef),\n )\n ).map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n });\n\n // Find added conditions\n for (const condition of newConds) {\n const roleMetadata = csvFileRoles.find(\n role => condition.roleEntityRef === role.roleEntityRef,\n );\n if (!roleMetadata) {\n this.logger.warn(\n `skip to add condition for role '${condition.roleEntityRef}'. The role either does not exist or was not created from a CSV file.`,\n );\n continue;\n }\n if (roleMetadata.source !== 'csv-file') {\n this.logger.warn(\n `skip to add condition for role '${condition.roleEntityRef}'. Role is not from csv-file`,\n );\n continue;\n }\n\n const existingCondition = existedFileConds.find(c =>\n deepSortEqual(omit(c, ['id']), omit(condition, ['id'])),\n );\n\n if (!existingCondition) {\n addedConds.push(condition);\n }\n }\n\n // Find removed conditions\n for (const condition of existedFileConds) {\n if (\n !newConds.find(c =>\n deepSortEqual(omit(c, ['id']), omit(condition, ['id'])),\n )\n ) {\n removedConds.push(condition);\n }\n }\n\n this.conditionsDiff = {\n addedConditions: addedConds,\n removedConditions: removedConds,\n };\n\n await this.handleFileChanges();\n } catch (error) {\n const auditorEvent = await this.auditor.createEvent({\n eventId: ConditionEvents.CONDITIONAL_POLICIES_FILE_CHANGE,\n severityLevel: 'medium',\n });\n await auditorEvent.fail({\n error,\n });\n }\n }\n\n /**\n * Reads the current contents of the file and parses it.\n * @returns parsed data.\n */\n parse(): RoleConditionalPolicyDecision<PermissionAction>[] {\n const fileContents = this.getCurrentContents();\n const data = yaml.loadAll(\n fileContents,\n ) as RoleConditionalPolicyDecision<PermissionAction>[];\n\n for (const condition of data) {\n validateRoleCondition(condition);\n }\n\n return data;\n }\n\n private async handleFileChanges(): Promise<void> {\n await this.removeConditions();\n await this.addConditions();\n }\n\n private async addConditions(): Promise<void> {\n for (const condition of this.conditionsDiff.addedConditions) {\n const auditorEvent = await this.auditor.createEvent({\n eventId: ConditionEvents.CONDITION_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.CREATE },\n });\n\n try {\n const conditionToCreate = await processConditionMapping(\n condition,\n this.pluginMetadataCollector,\n this.auth,\n );\n\n await this.conditionalStorage.createCondition(conditionToCreate);\n await auditorEvent.success({\n meta: { condition },\n });\n } catch (error) {\n await auditorEvent.fail({ error, meta: { condition } });\n }\n }\n\n this.conditionsDiff.addedConditions = [];\n }\n\n private async removeConditions(): Promise<void> {\n for (const condition of this.conditionsDiff.removedConditions) {\n const auditorEvent = await this.auditor.createEvent({\n eventId: ConditionEvents.CONDITION_WRITE,\n severityLevel: 'medium',\n meta: { actionType: ActionType.DELETE },\n });\n\n try {\n const conditionToDelete = (\n await this.conditionalStorage.filterConditions(\n condition.roleEntityRef,\n condition.pluginId,\n condition.resourceType,\n condition.permissionMapping,\n )\n )[0];\n await this.conditionalStorage.deleteCondition(conditionToDelete.id!);\n await auditorEvent.success({ meta: { condition } });\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: { condition },\n });\n }\n }\n\n this.conditionsDiff.removedConditions = [];\n }\n\n async cleanUpConditionalPolicies(): Promise<void> {\n const csvFileRoles =\n await this.roleMetadataStorage.filterRoleMetadata('csv-file');\n const existedFileConds = (\n await this.conditionalStorage.filterConditions(\n csvFileRoles.map(role => role.roleEntityRef),\n )\n ).map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n });\n this.conditionsDiff.removedConditions = existedFileConds;\n await this.removeConditions();\n }\n}\n"],"names":["AbstractFileWatcher","fs","ConditionEvents","deepSortEqual","omit","yaml","validateRoleCondition","ActionType","processConditionMapping"],"mappings":"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"}