@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.
- package/CHANGELOG.md +12 -0
- package/dist/admin-permissions/admin-creation.cjs.js +41 -27
- package/dist/admin-permissions/admin-creation.cjs.js.map +1 -1
- package/dist/auditor/auditor.cjs.js +65 -0
- package/dist/auditor/auditor.cjs.js.map +1 -0
- package/dist/auditor/rest-interceptor.cjs.js +130 -0
- package/dist/auditor/rest-interceptor.cjs.js.map +1 -0
- package/dist/file-permissions/csv-file-watcher.cjs.js +90 -92
- package/dist/file-permissions/csv-file-watcher.cjs.js.map +1 -1
- package/dist/file-permissions/yaml-conditional-file-watcher.cjs.js +40 -51
- package/dist/file-permissions/yaml-conditional-file-watcher.cjs.js.map +1 -1
- package/dist/helper.cjs.js +22 -19
- package/dist/helper.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/plugin.cjs.js +3 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/policies/permission-policy.cjs.js +32 -70
- package/dist/policies/permission-policy.cjs.js.map +1 -1
- package/dist/providers/connect-providers.cjs.js +75 -68
- package/dist/providers/connect-providers.cjs.js.map +1 -1
- package/dist/service/enforcer-delegate.cjs.js +8 -10
- package/dist/service/enforcer-delegate.cjs.js.map +1 -1
- package/dist/service/policies-rest-api.cjs.js +449 -519
- package/dist/service/policies-rest-api.cjs.js.map +1 -1
- package/dist/service/policy-builder.cjs.js +4 -10
- package/dist/service/policy-builder.cjs.js.map +1 -1
- package/package.json +2 -3
- package/dist/audit-log/audit-logger.cjs.js +0 -114
- package/dist/audit-log/audit-logger.cjs.js.map +0 -1
- package/dist/audit-log/rest-errors-interceptor.cjs.js +0 -100
- 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
|
|
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,
|
|
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.
|
|
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
|
|
170
|
-
|
|
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
|
-
|
|
182
|
-
|
|
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
|
|
194
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
|
218
|
-
|
|
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
|
-
|
|
235
|
-
|
|
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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
changedPolicies.failedPolicies.push({
|
|
243
|
+
error: e,
|
|
244
|
+
policies: groupPolicies
|
|
245
|
+
});
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
|
-
if (
|
|
247
|
-
await
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
|
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
|
|
300
|
+
isUpdate
|
|
282
301
|
);
|
|
283
|
-
|
|
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
|
-
|
|
298
|
-
|
|
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":"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"}
|
|
@@ -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
|
|
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,
|
|
17
|
+
constructor(filePath, allowReload, logger, conditionalStorage, auditor, auth, pluginMetadataCollector, roleMetadataStorage, roleEventEmitter) {
|
|
18
18
|
super(filePath, allowReload, logger);
|
|
19
19
|
this.conditionalStorage = conditionalStorage;
|
|
20
|
-
this.
|
|
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
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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
|
|
136
|
-
|
|
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
|
-
|
|
154
|
-
|
|
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
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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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"}
|