@backstage-community/plugin-rbac-backend 5.6.1 → 6.0.1
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 +15 -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 +3 -5
- 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
|
@@ -6,22 +6,21 @@ var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
|
6
6
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
7
7
|
var lodash = require('lodash');
|
|
8
8
|
var pluginRbacCommon = require('@backstage-community/plugin-rbac-common');
|
|
9
|
-
var
|
|
10
|
-
var restErrorsInterceptor = require('../audit-log/rest-errors-interceptor.cjs.js');
|
|
9
|
+
var restInterceptor = require('../auditor/rest-interceptor.cjs.js');
|
|
11
10
|
var roleMetadata = require('../database/role-metadata.cjs.js');
|
|
12
11
|
var helper = require('../helper.cjs.js');
|
|
13
12
|
var conditionValidation = require('../validation/condition-validation.cjs.js');
|
|
14
13
|
var policiesValidation = require('../validation/policies-validation.cjs.js');
|
|
15
14
|
|
|
16
15
|
class PoliciesServer {
|
|
17
|
-
constructor(permissions, options, enforcer, conditionalStorage, pluginPermMetaData, roleMetadata,
|
|
16
|
+
constructor(permissions, options, enforcer, conditionalStorage, pluginPermMetaData, roleMetadata, auditor, rbacProviders) {
|
|
18
17
|
this.permissions = permissions;
|
|
19
18
|
this.options = options;
|
|
20
19
|
this.enforcer = enforcer;
|
|
21
20
|
this.conditionalStorage = conditionalStorage;
|
|
22
21
|
this.pluginPermMetaData = pluginPermMetaData;
|
|
23
22
|
this.roleMetadata = roleMetadata;
|
|
24
|
-
this.
|
|
23
|
+
this.auditor = auditor;
|
|
25
24
|
this.rbacProviders = rbacProviders;
|
|
26
25
|
}
|
|
27
26
|
async authorize(request, permission) {
|
|
@@ -66,38 +65,35 @@ class PoliciesServer {
|
|
|
66
65
|
}
|
|
67
66
|
response.send({ status: "Authorized" });
|
|
68
67
|
});
|
|
69
|
-
router.get(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
68
|
+
router.get(
|
|
69
|
+
"/policies",
|
|
70
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
71
|
+
async (request, response) => {
|
|
72
|
+
const decision = await this.authorize(
|
|
73
|
+
request,
|
|
74
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
75
|
+
);
|
|
76
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
77
|
+
throw new errors.NotAllowedError();
|
|
78
|
+
}
|
|
79
|
+
let policies;
|
|
80
|
+
if (this.isPolicyFilterEnabled(request)) {
|
|
81
|
+
const entityRef = this.getFirstQuery(request.query.entityRef);
|
|
82
|
+
const permission = this.getFirstQuery(request.query.permission);
|
|
83
|
+
const policy = this.getFirstQuery(request.query.policy);
|
|
84
|
+
const effect = this.getFirstQuery(request.query.effect);
|
|
85
|
+
const filter = [entityRef, permission, policy, effect];
|
|
86
|
+
policies = await this.enforcer.getFilteredPolicy(0, ...filter);
|
|
87
|
+
} else {
|
|
88
|
+
policies = await this.enforcer.getPolicy();
|
|
89
|
+
}
|
|
90
|
+
const body = await this.transformPolicyArray(...policies);
|
|
91
|
+
response.json(body);
|
|
87
92
|
}
|
|
88
|
-
|
|
89
|
-
await this.aLog.auditLog({
|
|
90
|
-
message: `Return list permission policies`,
|
|
91
|
-
eventName: auditLogger.PermissionEvents.GET_POLICY,
|
|
92
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
93
|
-
status: "succeeded",
|
|
94
|
-
request,
|
|
95
|
-
response: { status: 200, body }
|
|
96
|
-
});
|
|
97
|
-
response.json(body);
|
|
98
|
-
});
|
|
93
|
+
);
|
|
99
94
|
router.get(
|
|
100
95
|
"/policies/:kind/:namespace/:name",
|
|
96
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
101
97
|
async (request, response) => {
|
|
102
98
|
const decision = await this.authorize(
|
|
103
99
|
request,
|
|
@@ -110,14 +106,6 @@ class PoliciesServer {
|
|
|
110
106
|
const policy = await this.enforcer.getFilteredPolicy(0, entityRef);
|
|
111
107
|
if (policy.length !== 0) {
|
|
112
108
|
const body = await this.transformPolicyArray(...policy);
|
|
113
|
-
await this.aLog.auditLog({
|
|
114
|
-
message: `Return permission policy`,
|
|
115
|
-
eventName: auditLogger.PermissionEvents.GET_POLICY,
|
|
116
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
117
|
-
status: "succeeded",
|
|
118
|
-
request,
|
|
119
|
-
response: { status: 200, body }
|
|
120
|
-
});
|
|
121
109
|
response.json(body);
|
|
122
110
|
} else {
|
|
123
111
|
throw new errors.NotFoundError();
|
|
@@ -126,6 +114,7 @@ class PoliciesServer {
|
|
|
126
114
|
);
|
|
127
115
|
router.delete(
|
|
128
116
|
"/policies/:kind/:namespace/:name",
|
|
117
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
129
118
|
async (request, response) => {
|
|
130
119
|
const decision = await this.authorize(
|
|
131
120
|
request,
|
|
@@ -144,50 +133,39 @@ class PoliciesServer {
|
|
|
144
133
|
});
|
|
145
134
|
const processedPolicies = await this.processPolicies(policyRaw, true);
|
|
146
135
|
await this.enforcer.removePolicies(processedPolicies);
|
|
147
|
-
|
|
148
|
-
message: `Deleted permission policies`,
|
|
149
|
-
eventName: auditLogger.PermissionEvents.DELETE_POLICY,
|
|
150
|
-
metadata: { policies: processedPolicies, source: "rest" },
|
|
151
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
152
|
-
status: "succeeded",
|
|
153
|
-
request,
|
|
154
|
-
response: { status: 204 }
|
|
155
|
-
});
|
|
136
|
+
response.locals.meta = { policies: processedPolicies };
|
|
156
137
|
response.status(204).end();
|
|
157
138
|
}
|
|
158
139
|
);
|
|
159
|
-
router.post(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
140
|
+
router.post(
|
|
141
|
+
"/policies",
|
|
142
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
143
|
+
async (request, response) => {
|
|
144
|
+
const decision = await this.authorize(
|
|
145
|
+
request,
|
|
146
|
+
pluginRbacCommon.policyEntityCreatePermission
|
|
147
|
+
);
|
|
148
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
149
|
+
throw new errors.NotAllowedError();
|
|
150
|
+
}
|
|
151
|
+
const policyRaw = request.body;
|
|
152
|
+
if (lodash.isEmpty(policyRaw)) {
|
|
153
|
+
throw new errors.InputError(`permission policy must be present`);
|
|
154
|
+
}
|
|
155
|
+
const processedPolicies = await this.processPolicies(policyRaw);
|
|
156
|
+
const entityRef = processedPolicies[0][0];
|
|
157
|
+
const roleMetadata = await this.roleMetadata.findRoleMetadata(entityRef);
|
|
158
|
+
if (entityRef.startsWith("role:default") && !roleMetadata) {
|
|
159
|
+
throw new Error(`Corresponding role ${entityRef} was not found`);
|
|
160
|
+
}
|
|
161
|
+
await this.enforcer.addPolicies(processedPolicies);
|
|
162
|
+
response.locals.meta = { policies: processedPolicies };
|
|
163
|
+
response.status(201).end();
|
|
176
164
|
}
|
|
177
|
-
|
|
178
|
-
await this.aLog.auditLog({
|
|
179
|
-
message: `Created permission policies`,
|
|
180
|
-
eventName: auditLogger.PermissionEvents.CREATE_POLICY,
|
|
181
|
-
metadata: { policies: processedPolicies, source: "rest" },
|
|
182
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
183
|
-
status: "succeeded",
|
|
184
|
-
request,
|
|
185
|
-
response: { status: 201 }
|
|
186
|
-
});
|
|
187
|
-
response.status(201).end();
|
|
188
|
-
});
|
|
165
|
+
);
|
|
189
166
|
router.put(
|
|
190
167
|
"/policies/:kind/:namespace/:name",
|
|
168
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
191
169
|
async (request, response) => {
|
|
192
170
|
const decision = await this.authorize(
|
|
193
171
|
request,
|
|
@@ -239,253 +217,235 @@ class PoliciesServer {
|
|
|
239
217
|
processedOldPolicy,
|
|
240
218
|
processedNewPolicy
|
|
241
219
|
);
|
|
242
|
-
|
|
243
|
-
message: `Updated permission policies`,
|
|
244
|
-
eventName: auditLogger.PermissionEvents.UPDATE_POLICY,
|
|
245
|
-
metadata: { policies: processedNewPolicy, source: "rest" },
|
|
246
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
247
|
-
status: "succeeded",
|
|
248
|
-
request,
|
|
249
|
-
response: { status: 200 }
|
|
250
|
-
});
|
|
220
|
+
response.locals.meta = { policies: processedNewPolicy };
|
|
251
221
|
response.status(200).end();
|
|
252
222
|
}
|
|
253
223
|
);
|
|
254
|
-
router.get(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
260
|
-
throw new errors.NotAllowedError();
|
|
261
|
-
}
|
|
262
|
-
const roles = await this.enforcer.getGroupingPolicy();
|
|
263
|
-
const body = await this.transformRoleArray(...roles);
|
|
264
|
-
await this.aLog.auditLog({
|
|
265
|
-
message: `Return list roles`,
|
|
266
|
-
eventName: auditLogger.RoleEvents.GET_ROLE,
|
|
267
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
268
|
-
status: "succeeded",
|
|
269
|
-
request,
|
|
270
|
-
response: { status: 200, body }
|
|
271
|
-
});
|
|
272
|
-
response.json(body);
|
|
273
|
-
});
|
|
274
|
-
router.get("/roles/:kind/:namespace/:name", async (request, response) => {
|
|
275
|
-
const decision = await this.authorize(
|
|
276
|
-
request,
|
|
277
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
278
|
-
);
|
|
279
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
280
|
-
throw new errors.NotAllowedError();
|
|
281
|
-
}
|
|
282
|
-
const roleEntityRef = this.getEntityReference(request, true);
|
|
283
|
-
const role = await this.enforcer.getFilteredGroupingPolicy(
|
|
284
|
-
1,
|
|
285
|
-
roleEntityRef
|
|
286
|
-
);
|
|
287
|
-
if (role.length !== 0) {
|
|
288
|
-
const body = await this.transformRoleArray(...role);
|
|
289
|
-
await this.aLog.auditLog({
|
|
290
|
-
message: `Return ${body[0].name}`,
|
|
291
|
-
eventName: auditLogger.RoleEvents.GET_ROLE,
|
|
292
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
293
|
-
status: "succeeded",
|
|
224
|
+
router.get(
|
|
225
|
+
"/roles",
|
|
226
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
227
|
+
async (request, response) => {
|
|
228
|
+
const decision = await this.authorize(
|
|
294
229
|
request,
|
|
295
|
-
|
|
296
|
-
|
|
230
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
231
|
+
);
|
|
232
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
233
|
+
throw new errors.NotAllowedError();
|
|
234
|
+
}
|
|
235
|
+
const roles = await this.enforcer.getGroupingPolicy();
|
|
236
|
+
const body = await this.transformRoleArray(...roles);
|
|
297
237
|
response.json(body);
|
|
298
|
-
} else {
|
|
299
|
-
throw new errors.NotFoundError();
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
router.post("/roles", async (request, response) => {
|
|
303
|
-
const uniqueItems = /* @__PURE__ */ new Set();
|
|
304
|
-
const decision = await this.authorize(
|
|
305
|
-
request,
|
|
306
|
-
pluginRbacCommon.policyEntityCreatePermission
|
|
307
|
-
);
|
|
308
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
309
|
-
throw new errors.NotAllowedError();
|
|
310
238
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
239
|
+
);
|
|
240
|
+
router.get(
|
|
241
|
+
"/roles/:kind/:namespace/:name",
|
|
242
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
243
|
+
async (request, response) => {
|
|
244
|
+
const decision = await this.authorize(
|
|
245
|
+
request,
|
|
246
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
317
247
|
);
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
const roleString = JSON.stringify(role);
|
|
331
|
-
if (uniqueItems.has(roleString)) {
|
|
332
|
-
throw new errors.ConflictError(
|
|
333
|
-
`Duplicate role members found; ${role.at(0)}, ${role.at(
|
|
334
|
-
1
|
|
335
|
-
)} is a duplicate`
|
|
336
|
-
);
|
|
248
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
249
|
+
throw new errors.NotAllowedError();
|
|
250
|
+
}
|
|
251
|
+
const roleEntityRef = this.getEntityReference(request, true);
|
|
252
|
+
const role = await this.enforcer.getFilteredGroupingPolicy(
|
|
253
|
+
1,
|
|
254
|
+
roleEntityRef
|
|
255
|
+
);
|
|
256
|
+
if (role.length !== 0) {
|
|
257
|
+
const body = await this.transformRoleArray(...role);
|
|
258
|
+
response.json(body);
|
|
337
259
|
} else {
|
|
338
|
-
|
|
260
|
+
throw new errors.NotFoundError();
|
|
339
261
|
}
|
|
340
262
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
modifiedBy
|
|
351
|
-
};
|
|
352
|
-
await this.enforcer.addGroupingPolicies(roles, metadata);
|
|
353
|
-
await this.aLog.auditLog({
|
|
354
|
-
message: `Created ${metadata.roleEntityRef}`,
|
|
355
|
-
eventName: auditLogger.RoleEvents.CREATE_ROLE,
|
|
356
|
-
metadata: {
|
|
357
|
-
...metadata,
|
|
358
|
-
members: roles.map((gp) => gp[0])
|
|
359
|
-
},
|
|
360
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
361
|
-
status: "succeeded",
|
|
362
|
-
request,
|
|
363
|
-
response: { status: 201 }
|
|
364
|
-
});
|
|
365
|
-
response.status(201).end();
|
|
366
|
-
});
|
|
367
|
-
router.put("/roles/:kind/:namespace/:name", async (request, response) => {
|
|
368
|
-
const uniqueItems = /* @__PURE__ */ new Set();
|
|
369
|
-
const decision = await this.authorize(
|
|
370
|
-
request,
|
|
371
|
-
pluginRbacCommon.policyEntityUpdatePermission
|
|
372
|
-
);
|
|
373
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
374
|
-
throw new errors.NotAllowedError();
|
|
375
|
-
}
|
|
376
|
-
const roleEntityRef = this.getEntityReference(request, true);
|
|
377
|
-
const oldRoleRaw = request.body.oldRole;
|
|
378
|
-
if (!oldRoleRaw) {
|
|
379
|
-
throw new errors.InputError(`'oldRole' object must be present`);
|
|
380
|
-
}
|
|
381
|
-
const newRoleRaw = request.body.newRole;
|
|
382
|
-
if (!newRoleRaw) {
|
|
383
|
-
throw new errors.InputError(`'newRole' object must be present`);
|
|
384
|
-
}
|
|
385
|
-
oldRoleRaw.name = roleEntityRef;
|
|
386
|
-
let err = policiesValidation.validateRole(oldRoleRaw);
|
|
387
|
-
if (err) {
|
|
388
|
-
throw new errors.InputError(
|
|
389
|
-
// 400
|
|
390
|
-
`Invalid old role object. Cause: ${err.message}`
|
|
263
|
+
);
|
|
264
|
+
router.post(
|
|
265
|
+
"/roles",
|
|
266
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
267
|
+
async (request, response) => {
|
|
268
|
+
const uniqueItems = /* @__PURE__ */ new Set();
|
|
269
|
+
const decision = await this.authorize(
|
|
270
|
+
request,
|
|
271
|
+
pluginRbacCommon.policyEntityCreatePermission
|
|
391
272
|
);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
273
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
274
|
+
throw new errors.NotAllowedError();
|
|
275
|
+
}
|
|
276
|
+
const roleRaw = request.body;
|
|
277
|
+
let err = policiesValidation.validateRole(roleRaw);
|
|
278
|
+
if (err) {
|
|
279
|
+
throw new errors.InputError(
|
|
280
|
+
// 400
|
|
281
|
+
`Invalid role definition. Cause: ${err.message}`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
this.transformMemberReferencesToLowercase(roleRaw);
|
|
285
|
+
const rMetadata = await this.roleMetadata.findRoleMetadata(
|
|
286
|
+
roleRaw.name
|
|
398
287
|
);
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
});
|
|
407
|
-
const newMetadata = {
|
|
408
|
-
...newRoleRaw.metadata,
|
|
409
|
-
source: newRoleRaw.metadata?.source ?? "rest",
|
|
410
|
-
roleEntityRef: newRoleRaw.name,
|
|
411
|
-
modifiedBy: credentials.principal.userEntityRef
|
|
412
|
-
};
|
|
413
|
-
const oldMetadata = await this.roleMetadata.findRoleMetadata(roleEntityRef);
|
|
414
|
-
if (!oldMetadata) {
|
|
415
|
-
throw new errors.NotFoundError(`Unable to find metadata for ${roleEntityRef}`);
|
|
416
|
-
}
|
|
417
|
-
err = await policiesValidation.validateSource("rest", oldMetadata);
|
|
418
|
-
if (err) {
|
|
419
|
-
throw new errors.NotAllowedError(`Unable to edit role: ${err.message}`);
|
|
420
|
-
}
|
|
421
|
-
if (lodash.isEqual(oldRole, newRole) && helper.deepSortedEqual(oldMetadata, newMetadata, [
|
|
422
|
-
"author",
|
|
423
|
-
"modifiedBy",
|
|
424
|
-
"createdAt",
|
|
425
|
-
"lastModified"
|
|
426
|
-
])) {
|
|
427
|
-
response.status(204).end();
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
for (const role of newRole) {
|
|
431
|
-
const hasRole = oldRole.some((element) => {
|
|
432
|
-
return lodash.isEqual(element, role);
|
|
433
|
-
});
|
|
434
|
-
if (await this.enforcer.hasGroupingPolicy(...role)) {
|
|
435
|
-
if (!hasRole) {
|
|
288
|
+
err = await policiesValidation.validateSource("rest", rMetadata);
|
|
289
|
+
if (err) {
|
|
290
|
+
throw new errors.NotAllowedError(`Unable to add role: ${err.message}`);
|
|
291
|
+
}
|
|
292
|
+
const roles = this.transformRoleToArray(roleRaw);
|
|
293
|
+
for (const role of roles) {
|
|
294
|
+
if (await this.enforcer.hasGroupingPolicy(...role)) {
|
|
436
295
|
throw new errors.ConflictError();
|
|
437
296
|
}
|
|
297
|
+
const roleString = JSON.stringify(role);
|
|
298
|
+
if (uniqueItems.has(roleString)) {
|
|
299
|
+
throw new errors.ConflictError(
|
|
300
|
+
`Duplicate role members found; ${role.at(0)}, ${role.at(
|
|
301
|
+
1
|
|
302
|
+
)} is a duplicate`
|
|
303
|
+
);
|
|
304
|
+
} else {
|
|
305
|
+
uniqueItems.add(roleString);
|
|
306
|
+
}
|
|
438
307
|
}
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
308
|
+
const credentials = await httpAuth.credentials(request, {
|
|
309
|
+
allow: ["user"]
|
|
310
|
+
});
|
|
311
|
+
const modifiedBy = credentials.principal.userEntityRef;
|
|
312
|
+
const metadata = {
|
|
313
|
+
roleEntityRef: roleRaw.name,
|
|
314
|
+
source: "rest",
|
|
315
|
+
description: roleRaw.metadata?.description ?? "",
|
|
316
|
+
author: modifiedBy,
|
|
317
|
+
modifiedBy
|
|
318
|
+
};
|
|
319
|
+
await this.enforcer.addGroupingPolicies(roles, metadata);
|
|
320
|
+
response.locals.meta = { ...metadata, members: roles.map((gp) => gp[0]) };
|
|
321
|
+
response.status(201).end();
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
router.put(
|
|
325
|
+
"/roles/:kind/:namespace/:name",
|
|
326
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
327
|
+
async (request, response) => {
|
|
328
|
+
const uniqueItems = /* @__PURE__ */ new Set();
|
|
329
|
+
const decision = await this.authorize(
|
|
330
|
+
request,
|
|
331
|
+
pluginRbacCommon.policyEntityUpdatePermission
|
|
332
|
+
);
|
|
333
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
334
|
+
throw new errors.NotAllowedError();
|
|
335
|
+
}
|
|
336
|
+
const roleEntityRef = this.getEntityReference(request, true);
|
|
337
|
+
const oldRoleRaw = request.body.oldRole;
|
|
338
|
+
if (!oldRoleRaw) {
|
|
339
|
+
throw new errors.InputError(`'oldRole' object must be present`);
|
|
340
|
+
}
|
|
341
|
+
const newRoleRaw = request.body.newRole;
|
|
342
|
+
if (!newRoleRaw) {
|
|
343
|
+
throw new errors.InputError(`'newRole' object must be present`);
|
|
344
|
+
}
|
|
345
|
+
oldRoleRaw.name = roleEntityRef;
|
|
346
|
+
let err = policiesValidation.validateRole(oldRoleRaw);
|
|
347
|
+
if (err) {
|
|
348
|
+
throw new errors.InputError(
|
|
349
|
+
// 400
|
|
350
|
+
`Invalid old role object. Cause: ${err.message}`
|
|
445
351
|
);
|
|
446
|
-
} else {
|
|
447
|
-
uniqueItems.add(roleString);
|
|
448
352
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
`Member reference: ${role[0]} was not found for role ${roleEntityRef}`
|
|
353
|
+
err = policiesValidation.validateRole(newRoleRaw);
|
|
354
|
+
if (err) {
|
|
355
|
+
throw new errors.InputError(
|
|
356
|
+
// 400
|
|
357
|
+
`Invalid new role object. Cause: ${err.message}`
|
|
455
358
|
);
|
|
456
359
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
360
|
+
this.transformMemberReferencesToLowercase(oldRoleRaw);
|
|
361
|
+
this.transformMemberReferencesToLowercase(newRoleRaw);
|
|
362
|
+
const oldRole = this.transformRoleToArray(oldRoleRaw);
|
|
363
|
+
const newRole = this.transformRoleToArray(newRoleRaw);
|
|
364
|
+
const credentials = await httpAuth.credentials(request, {
|
|
365
|
+
allow: ["user"]
|
|
366
|
+
});
|
|
367
|
+
const newMetadata = {
|
|
368
|
+
...newRoleRaw.metadata,
|
|
369
|
+
source: newRoleRaw.metadata?.source ?? "rest",
|
|
370
|
+
roleEntityRef: newRoleRaw.name,
|
|
371
|
+
modifiedBy: credentials.principal.userEntityRef
|
|
372
|
+
};
|
|
373
|
+
const oldMetadata = await this.roleMetadata.findRoleMetadata(roleEntityRef);
|
|
374
|
+
if (!oldMetadata) {
|
|
375
|
+
throw new errors.NotFoundError(
|
|
376
|
+
`Unable to find metadata for ${roleEntityRef}`
|
|
463
377
|
);
|
|
464
|
-
} else {
|
|
465
|
-
uniqueItems.add(roleString);
|
|
466
378
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
379
|
+
err = await policiesValidation.validateSource("rest", oldMetadata);
|
|
380
|
+
if (err) {
|
|
381
|
+
throw new errors.NotAllowedError(`Unable to edit role: ${err.message}`);
|
|
382
|
+
}
|
|
383
|
+
if (lodash.isEqual(oldRole, newRole) && helper.deepSortedEqual(oldMetadata, newMetadata, [
|
|
384
|
+
"author",
|
|
385
|
+
"modifiedBy",
|
|
386
|
+
"createdAt",
|
|
387
|
+
"lastModified"
|
|
388
|
+
])) {
|
|
389
|
+
response.status(204).end();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
for (const role of newRole) {
|
|
393
|
+
const hasRole = oldRole.some((element) => {
|
|
394
|
+
return lodash.isEqual(element, role);
|
|
395
|
+
});
|
|
396
|
+
if (await this.enforcer.hasGroupingPolicy(...role)) {
|
|
397
|
+
if (!hasRole) {
|
|
398
|
+
throw new errors.ConflictError();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const roleString = JSON.stringify(role);
|
|
402
|
+
if (uniqueItems.has(roleString)) {
|
|
403
|
+
throw new errors.ConflictError(
|
|
404
|
+
`Duplicate role members found; ${role.at(0)}, ${role.at(
|
|
405
|
+
1
|
|
406
|
+
)} is a duplicate`
|
|
407
|
+
);
|
|
408
|
+
} else {
|
|
409
|
+
uniqueItems.add(roleString);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
uniqueItems.clear();
|
|
413
|
+
for (const role of oldRole) {
|
|
414
|
+
if (!await this.enforcer.hasGroupingPolicy(...role)) {
|
|
415
|
+
throw new errors.NotFoundError(
|
|
416
|
+
`Member reference: ${role[0]} was not found for role ${roleEntityRef}`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
const roleString = JSON.stringify(role);
|
|
420
|
+
if (uniqueItems.has(roleString)) {
|
|
421
|
+
throw new errors.ConflictError(
|
|
422
|
+
`Duplicate role members found; ${role.at(0)}, ${role.at(
|
|
423
|
+
1
|
|
424
|
+
)} is a duplicate`
|
|
425
|
+
);
|
|
426
|
+
} else {
|
|
427
|
+
uniqueItems.add(roleString);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
await this.enforcer.updateGroupingPolicies(
|
|
431
|
+
oldRole,
|
|
432
|
+
newRole,
|
|
433
|
+
newMetadata
|
|
434
|
+
);
|
|
435
|
+
let message = `Updated ${oldMetadata.roleEntityRef}.`;
|
|
436
|
+
if (newMetadata.roleEntityRef !== oldMetadata.roleEntityRef) {
|
|
437
|
+
message = `${message}. Role entity reference renamed to ${newMetadata.roleEntityRef}`;
|
|
438
|
+
}
|
|
439
|
+
response.locals.meta = {
|
|
477
440
|
...newMetadata,
|
|
478
441
|
members: newRole.map((gp) => gp[0])
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
response: { status: 200 }
|
|
484
|
-
});
|
|
485
|
-
response.status(200).end();
|
|
486
|
-
});
|
|
442
|
+
};
|
|
443
|
+
response.status(200).end();
|
|
444
|
+
}
|
|
445
|
+
);
|
|
487
446
|
router.delete(
|
|
488
447
|
"/roles/:kind/:namespace/:name",
|
|
448
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
489
449
|
async (request, response) => {
|
|
490
450
|
const decision = await this.authorize(
|
|
491
451
|
request,
|
|
@@ -541,238 +501,208 @@ class PoliciesServer {
|
|
|
541
501
|
metadata,
|
|
542
502
|
false
|
|
543
503
|
);
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
...metadata,
|
|
549
|
-
members: roleMembers.map((gp) => gp[0])
|
|
550
|
-
},
|
|
551
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
552
|
-
status: "succeeded",
|
|
553
|
-
request,
|
|
554
|
-
response: { status: 204 }
|
|
555
|
-
});
|
|
504
|
+
response.locals.meta = {
|
|
505
|
+
...metadata,
|
|
506
|
+
members: roleMembers.map((gp) => gp[0])
|
|
507
|
+
};
|
|
556
508
|
response.status(204).end();
|
|
557
509
|
}
|
|
558
510
|
);
|
|
559
|
-
router.get(
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
511
|
+
router.get(
|
|
512
|
+
"/plugins/policies",
|
|
513
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
514
|
+
async (request, response) => {
|
|
515
|
+
const decision = await this.authorize(
|
|
516
|
+
request,
|
|
517
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
518
|
+
);
|
|
519
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
520
|
+
throw new errors.NotAllowedError();
|
|
521
|
+
}
|
|
522
|
+
const body = await this.pluginPermMetaData.getPluginPolicies(
|
|
523
|
+
this.options.auth
|
|
524
|
+
);
|
|
525
|
+
response.json(body);
|
|
566
526
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
584
|
-
);
|
|
585
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
586
|
-
throw new errors.NotAllowedError();
|
|
527
|
+
);
|
|
528
|
+
router.get(
|
|
529
|
+
"/plugins/condition-rules",
|
|
530
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
531
|
+
async (request, response) => {
|
|
532
|
+
const decision = await this.authorize(
|
|
533
|
+
request,
|
|
534
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
535
|
+
);
|
|
536
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
537
|
+
throw new errors.NotAllowedError();
|
|
538
|
+
}
|
|
539
|
+
const body = await this.pluginPermMetaData.getPluginConditionRules(
|
|
540
|
+
this.options.auth
|
|
541
|
+
);
|
|
542
|
+
response.json(body);
|
|
587
543
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
544
|
+
);
|
|
545
|
+
router.get(
|
|
546
|
+
"/roles/conditions",
|
|
547
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
548
|
+
async (request, response) => {
|
|
549
|
+
const decision = await this.authorize(
|
|
550
|
+
request,
|
|
551
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
552
|
+
);
|
|
553
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
554
|
+
throw new errors.NotAllowedError();
|
|
555
|
+
}
|
|
556
|
+
const conditions = await this.conditionalStorage.filterConditions(
|
|
557
|
+
this.getFirstQuery(request.query.roleEntityRef),
|
|
558
|
+
this.getFirstQuery(request.query.pluginId),
|
|
559
|
+
this.getFirstQuery(request.query.resourceType),
|
|
560
|
+
this.getActionQueries(request.query.actions)
|
|
561
|
+
);
|
|
562
|
+
const body = conditions.map((condition) => {
|
|
563
|
+
return {
|
|
564
|
+
...condition,
|
|
565
|
+
permissionMapping: condition.permissionMapping.map(
|
|
566
|
+
(pm) => pm.action
|
|
567
|
+
)
|
|
568
|
+
};
|
|
569
|
+
});
|
|
570
|
+
response.json(body);
|
|
608
571
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
572
|
+
);
|
|
573
|
+
router.post(
|
|
574
|
+
"/roles/conditions",
|
|
575
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
576
|
+
async (request, response) => {
|
|
577
|
+
const decision = await this.authorize(
|
|
578
|
+
request,
|
|
579
|
+
pluginRbacCommon.policyEntityCreatePermission
|
|
580
|
+
);
|
|
581
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
582
|
+
throw new errors.NotAllowedError();
|
|
583
|
+
}
|
|
584
|
+
const roleConditionPolicy = request.body;
|
|
585
|
+
conditionValidation.validateRoleCondition(roleConditionPolicy);
|
|
586
|
+
const conditionToCreate = await helper.processConditionMapping(
|
|
587
|
+
roleConditionPolicy,
|
|
588
|
+
this.pluginPermMetaData,
|
|
589
|
+
this.options.auth
|
|
590
|
+
);
|
|
591
|
+
const id = await this.conditionalStorage.createCondition(conditionToCreate);
|
|
592
|
+
const body = { id };
|
|
593
|
+
response.locals.meta = { condition: roleConditionPolicy };
|
|
594
|
+
response.status(201).json(body);
|
|
595
|
+
}
|
|
596
|
+
);
|
|
597
|
+
router.get(
|
|
598
|
+
"/roles/conditions/:id",
|
|
599
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
600
|
+
async (request, response) => {
|
|
601
|
+
const decision = await this.authorize(
|
|
602
|
+
request,
|
|
603
|
+
pluginRbacCommon.policyEntityReadPermission
|
|
604
|
+
);
|
|
605
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
606
|
+
throw new errors.NotAllowedError();
|
|
607
|
+
}
|
|
608
|
+
const id = parseInt(request.params.id, 10);
|
|
609
|
+
if (isNaN(id)) {
|
|
610
|
+
throw new errors.InputError("Id is not a valid number.");
|
|
611
|
+
}
|
|
612
|
+
const condition = await this.conditionalStorage.getCondition(id);
|
|
613
|
+
if (!condition) {
|
|
614
|
+
throw new errors.NotFoundError();
|
|
615
|
+
}
|
|
616
|
+
const body = {
|
|
617
617
|
...condition,
|
|
618
618
|
permissionMapping: condition.permissionMapping.map((pm) => pm.action)
|
|
619
619
|
};
|
|
620
|
-
|
|
621
|
-
await this.aLog.auditLog({
|
|
622
|
-
message: `Return list conditional permission policies`,
|
|
623
|
-
eventName: auditLogger.ConditionEvents.GET_CONDITION,
|
|
624
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
625
|
-
status: "succeeded",
|
|
626
|
-
request,
|
|
627
|
-
response: { status: 200, body }
|
|
628
|
-
});
|
|
629
|
-
response.json(body);
|
|
630
|
-
});
|
|
631
|
-
router.post("/roles/conditions", async (request, response) => {
|
|
632
|
-
const decision = await this.authorize(
|
|
633
|
-
request,
|
|
634
|
-
pluginRbacCommon.policyEntityCreatePermission
|
|
635
|
-
);
|
|
636
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
637
|
-
throw new errors.NotAllowedError();
|
|
638
|
-
}
|
|
639
|
-
const roleConditionPolicy = request.body;
|
|
640
|
-
conditionValidation.validateRoleCondition(roleConditionPolicy);
|
|
641
|
-
const conditionToCreate = await helper.processConditionMapping(
|
|
642
|
-
roleConditionPolicy,
|
|
643
|
-
this.pluginPermMetaData,
|
|
644
|
-
this.options.auth
|
|
645
|
-
);
|
|
646
|
-
const id = await this.conditionalStorage.createCondition(conditionToCreate);
|
|
647
|
-
const body = { id };
|
|
648
|
-
await this.aLog.auditLog({
|
|
649
|
-
message: `Created conditional permission policy`,
|
|
650
|
-
eventName: auditLogger.ConditionEvents.CREATE_CONDITION,
|
|
651
|
-
metadata: { condition: roleConditionPolicy },
|
|
652
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
653
|
-
status: "succeeded",
|
|
654
|
-
request,
|
|
655
|
-
response: { status: 201, body }
|
|
656
|
-
});
|
|
657
|
-
response.status(201).json(body);
|
|
658
|
-
});
|
|
659
|
-
router.get("/roles/conditions/:id", async (request, response) => {
|
|
660
|
-
const decision = await this.authorize(
|
|
661
|
-
request,
|
|
662
|
-
pluginRbacCommon.policyEntityReadPermission
|
|
663
|
-
);
|
|
664
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
665
|
-
throw new errors.NotAllowedError();
|
|
666
|
-
}
|
|
667
|
-
const id = parseInt(request.params.id, 10);
|
|
668
|
-
if (isNaN(id)) {
|
|
669
|
-
throw new errors.InputError("Id is not a valid number.");
|
|
670
|
-
}
|
|
671
|
-
const condition = await this.conditionalStorage.getCondition(id);
|
|
672
|
-
if (!condition) {
|
|
673
|
-
throw new errors.NotFoundError();
|
|
674
|
-
}
|
|
675
|
-
const body = {
|
|
676
|
-
...condition,
|
|
677
|
-
permissionMapping: condition.permissionMapping.map((pm) => pm.action)
|
|
678
|
-
};
|
|
679
|
-
await this.aLog.auditLog({
|
|
680
|
-
message: `Return conditional permission policy by id`,
|
|
681
|
-
eventName: auditLogger.ConditionEvents.GET_CONDITION,
|
|
682
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
683
|
-
status: "succeeded",
|
|
684
|
-
request,
|
|
685
|
-
response: { status: 200, body }
|
|
686
|
-
});
|
|
687
|
-
response.json(body);
|
|
688
|
-
});
|
|
689
|
-
router.delete("/roles/conditions/:id", async (request, response) => {
|
|
690
|
-
const decision = await this.authorize(
|
|
691
|
-
request,
|
|
692
|
-
pluginRbacCommon.policyEntityDeletePermission
|
|
693
|
-
);
|
|
694
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
695
|
-
throw new errors.NotAllowedError();
|
|
696
|
-
}
|
|
697
|
-
const id = parseInt(request.params.id, 10);
|
|
698
|
-
if (isNaN(id)) {
|
|
699
|
-
throw new errors.InputError("Id is not a valid number.");
|
|
700
|
-
}
|
|
701
|
-
const condition = await this.conditionalStorage.getCondition(id);
|
|
702
|
-
if (!condition) {
|
|
703
|
-
throw new errors.NotFoundError(`Condition with id ${id} was not found`);
|
|
704
|
-
}
|
|
705
|
-
const conditionToDelete = {
|
|
706
|
-
...condition,
|
|
707
|
-
permissionMapping: condition.permissionMapping.map((pm) => pm.action)
|
|
708
|
-
};
|
|
709
|
-
await this.conditionalStorage.deleteCondition(id);
|
|
710
|
-
await this.aLog.auditLog({
|
|
711
|
-
message: `Deleted conditional permission policy`,
|
|
712
|
-
eventName: auditLogger.ConditionEvents.DELETE_CONDITION,
|
|
713
|
-
metadata: { condition: conditionToDelete },
|
|
714
|
-
stage: auditLogger.SEND_RESPONSE_STAGE,
|
|
715
|
-
status: "succeeded",
|
|
716
|
-
request,
|
|
717
|
-
response: { status: 204 }
|
|
718
|
-
});
|
|
719
|
-
response.status(204).end();
|
|
720
|
-
});
|
|
721
|
-
router.put("/roles/conditions/:id", async (request, response) => {
|
|
722
|
-
const decision = await this.authorize(
|
|
723
|
-
request,
|
|
724
|
-
pluginRbacCommon.policyEntityUpdatePermission
|
|
725
|
-
);
|
|
726
|
-
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
727
|
-
throw new errors.NotAllowedError();
|
|
728
|
-
}
|
|
729
|
-
const id = parseInt(request.params.id, 10);
|
|
730
|
-
if (isNaN(id)) {
|
|
731
|
-
throw new errors.InputError("Id is not a valid number.");
|
|
620
|
+
response.json(body);
|
|
732
621
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
this.
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
622
|
+
);
|
|
623
|
+
router.delete(
|
|
624
|
+
"/roles/conditions/:id",
|
|
625
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
626
|
+
async (request, response) => {
|
|
627
|
+
const decision = await this.authorize(
|
|
628
|
+
request,
|
|
629
|
+
pluginRbacCommon.policyEntityDeletePermission
|
|
630
|
+
);
|
|
631
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
632
|
+
throw new errors.NotAllowedError();
|
|
633
|
+
}
|
|
634
|
+
const id = parseInt(request.params.id, 10);
|
|
635
|
+
if (isNaN(id)) {
|
|
636
|
+
throw new errors.InputError("Id is not a valid number.");
|
|
637
|
+
}
|
|
638
|
+
const condition = await this.conditionalStorage.getCondition(id);
|
|
639
|
+
if (!condition) {
|
|
640
|
+
throw new errors.NotFoundError(`Condition with id ${id} was not found`);
|
|
641
|
+
}
|
|
642
|
+
const conditionToDelete = {
|
|
643
|
+
...condition,
|
|
644
|
+
permissionMapping: condition.permissionMapping.map((pm) => pm.action)
|
|
645
|
+
};
|
|
646
|
+
await this.conditionalStorage.deleteCondition(id);
|
|
647
|
+
response.locals.meta = { condition: conditionToDelete };
|
|
648
|
+
response.status(204).end();
|
|
759
649
|
}
|
|
760
|
-
|
|
761
|
-
|
|
650
|
+
);
|
|
651
|
+
router.put(
|
|
652
|
+
"/roles/conditions/:id",
|
|
653
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
654
|
+
async (request, response) => {
|
|
655
|
+
const decision = await this.authorize(
|
|
656
|
+
request,
|
|
657
|
+
pluginRbacCommon.policyEntityUpdatePermission
|
|
658
|
+
);
|
|
659
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
660
|
+
throw new errors.NotAllowedError();
|
|
661
|
+
}
|
|
662
|
+
const id = parseInt(request.params.id, 10);
|
|
663
|
+
if (isNaN(id)) {
|
|
664
|
+
throw new errors.InputError("Id is not a valid number.");
|
|
665
|
+
}
|
|
666
|
+
const roleConditionPolicy = request.body;
|
|
667
|
+
conditionValidation.validateRoleCondition(roleConditionPolicy);
|
|
668
|
+
const conditionToUpdate = await helper.processConditionMapping(
|
|
669
|
+
roleConditionPolicy,
|
|
670
|
+
this.pluginPermMetaData,
|
|
671
|
+
this.options.auth
|
|
672
|
+
);
|
|
673
|
+
await this.conditionalStorage.updateCondition(id, conditionToUpdate);
|
|
674
|
+
response.locals.meta = { condition: roleConditionPolicy };
|
|
675
|
+
response.status(200).end();
|
|
762
676
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
677
|
+
);
|
|
678
|
+
router.post(
|
|
679
|
+
"/refresh/:id",
|
|
680
|
+
restInterceptor.logAuditorEvent(this.auditor),
|
|
681
|
+
async (request, response) => {
|
|
682
|
+
const decision = await this.authorize(
|
|
683
|
+
request,
|
|
684
|
+
pluginRbacCommon.policyEntityCreatePermission
|
|
770
685
|
);
|
|
686
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
687
|
+
throw new errors.NotAllowedError();
|
|
688
|
+
}
|
|
689
|
+
if (!this.rbacProviders) {
|
|
690
|
+
throw new errors.NotFoundError(`No RBAC providers were found`);
|
|
691
|
+
}
|
|
692
|
+
const idProvider = this.rbacProviders.find((provider) => {
|
|
693
|
+
const id = provider.getProviderName();
|
|
694
|
+
return id === request.params.id;
|
|
695
|
+
});
|
|
696
|
+
if (!idProvider) {
|
|
697
|
+
throw new errors.NotFoundError(
|
|
698
|
+
`The RBAC provider ${request.params.id} was not found`
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
await idProvider.refresh();
|
|
702
|
+
response.status(200).end();
|
|
771
703
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
});
|
|
775
|
-
router.use(restErrorsInterceptor.auditError(this.aLog));
|
|
704
|
+
);
|
|
705
|
+
router.use(restInterceptor.setAuditorError());
|
|
776
706
|
return router;
|
|
777
707
|
}
|
|
778
708
|
getEntityReference(request, role) {
|