@backstage-community/plugin-rbac-backend 5.3.1 → 5.5.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 +18 -0
- package/dist/database/casbin-adapter-factory.cjs.js +5 -5
- package/dist/database/casbin-adapter-factory.cjs.js.map +1 -1
- package/dist/database/conditional-storage.cjs.js +1 -1
- package/dist/database/conditional-storage.cjs.js.map +1 -1
- package/dist/helper.cjs.js +1 -1
- package/dist/helper.cjs.js.map +1 -1
- package/dist/policies/permission-policy.cjs.js +13 -9
- package/dist/policies/permission-policy.cjs.js.map +1 -1
- package/dist/role-manager/ancestor-search-memo.cjs.js +2 -2
- package/dist/role-manager/ancestor-search-memo.cjs.js.map +1 -1
- package/dist/role-manager/member-list.cjs.js +1 -1
- package/dist/role-manager/member-list.cjs.js.map +1 -1
- package/dist/role-manager/role-manager.cjs.js +48 -69
- package/dist/role-manager/role-manager.cjs.js.map +1 -1
- package/dist/service/enforcer-delegate.cjs.js +45 -26
- package/dist/service/enforcer-delegate.cjs.js.map +1 -1
- package/dist/service/plugin-endpoints.cjs.js +2 -2
- package/dist/service/plugin-endpoints.cjs.js.map +1 -1
- package/dist/service/policies-rest-api.cjs.js +2 -2
- package/dist/service/policies-rest-api.cjs.js.map +1 -1
- package/dist/validation/policies-validation.cjs.js +8 -8
- package/dist/validation/policies-validation.cjs.js.map +1 -1
- package/package.json +24 -17
|
@@ -15,7 +15,7 @@ class BackstageRoleManager {
|
|
|
15
15
|
this.allRoles = /* @__PURE__ */ new Map();
|
|
16
16
|
const rbacConfig = this.config.getOptionalConfig("permission.rbac");
|
|
17
17
|
this.maxDepth = rbacConfig?.getOptionalNumber("maxDepth");
|
|
18
|
-
if (this.maxDepth !==
|
|
18
|
+
if (this.maxDepth !== undefined && this.maxDepth < 0) {
|
|
19
19
|
throw new Error(
|
|
20
20
|
"Max Depth for RBAC group hierarchy must be greater than or equal to zero"
|
|
21
21
|
);
|
|
@@ -65,17 +65,24 @@ class BackstageRoleManager {
|
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* hasLink determines whether name1 inherits role: name2.
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
68
|
+
* Before this check is called in the background by the enforcer,
|
|
69
|
+
* we filter out all roles that the user is not connected to
|
|
70
|
+
* directly or indirectly through the use of retrieving roles through
|
|
71
|
+
* enforcer.getRolesForUser and apply those roles to a tempEnforcer.
|
|
72
|
+
*
|
|
73
|
+
* This means that hasLink will almost always be true in the event that a user
|
|
74
|
+
* is assigned to a role (either directly or indirectly)
|
|
75
|
+
*
|
|
76
|
+
* In the event that a user or group is not assigned to a role and instead
|
|
77
|
+
* are assigned directly to permissions, then name2 will become either that
|
|
78
|
+
* user or group through the filtering. In this case we will build the graph
|
|
79
|
+
* if necessary for name2 group presence or evaulate based on the names matching.
|
|
72
80
|
* @param name1 The user that we are authorizing.
|
|
73
81
|
* @param name2 The name of the role that we are checking against.
|
|
74
82
|
* @param domain Unimplemented.
|
|
75
83
|
* @returns True if the user is directly or indirectly attached to the role.
|
|
76
84
|
*/
|
|
77
85
|
async hasLink(name1, name2, ...domain) {
|
|
78
|
-
let currentRole;
|
|
79
86
|
if (domain.length > 0) {
|
|
80
87
|
throw new Error("domain argument is not supported.");
|
|
81
88
|
}
|
|
@@ -85,48 +92,34 @@ class BackstageRoleManager {
|
|
|
85
92
|
if (name1 === name2) {
|
|
86
93
|
return true;
|
|
87
94
|
}
|
|
88
|
-
if (this.isPGClient()) {
|
|
89
|
-
currentRole = new memberList.RoleMemberList(name2);
|
|
90
|
-
await currentRole.buildMembers(currentRole, this.rbacDBClient);
|
|
91
|
-
} else {
|
|
92
|
-
currentRole = this.allRoles.get(name2);
|
|
93
|
-
}
|
|
94
|
-
const directDeclaration = await this.checkForUserToRole(
|
|
95
|
-
name1,
|
|
96
|
-
name2,
|
|
97
|
-
currentRole
|
|
98
|
-
);
|
|
99
|
-
if (directDeclaration) {
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
95
|
const { kind } = catalogModel.parseEntityRef(name2);
|
|
103
96
|
if (kind.toLocaleLowerCase() === "user") {
|
|
104
97
|
return false;
|
|
105
98
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
await memo.buildUserGraph(memo);
|
|
114
|
-
memo.debugNodesAndEdges(this.logger, name1);
|
|
115
|
-
if (!memo.isAcyclic()) {
|
|
116
|
-
const cycles = memo.findCycles();
|
|
117
|
-
this.logger.warn(
|
|
118
|
-
`Detected cycle dependencies in the Group graph: ${JSON.stringify(
|
|
119
|
-
cycles
|
|
120
|
-
)}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(
|
|
121
|
-
cycles
|
|
122
|
-
)}`
|
|
99
|
+
if (kind.toLocaleLowerCase() === "group") {
|
|
100
|
+
const memo = new ancestorSearchMemo.AncestorSearchMemo(
|
|
101
|
+
name1,
|
|
102
|
+
this.catalogApi,
|
|
103
|
+
this.catalogDBClient,
|
|
104
|
+
this.auth,
|
|
105
|
+
this.maxDepth
|
|
123
106
|
);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
107
|
+
await memo.buildUserGraph(memo);
|
|
108
|
+
memo.debugNodesAndEdges(this.logger, name1);
|
|
109
|
+
if (!memo.isAcyclic()) {
|
|
110
|
+
const cycles = memo.findCycles();
|
|
111
|
+
this.logger.warn(
|
|
112
|
+
`Detected cycle dependencies in the Group graph: ${JSON.stringify(
|
|
113
|
+
cycles
|
|
114
|
+
)}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(
|
|
115
|
+
cycles
|
|
116
|
+
)}`
|
|
117
|
+
);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return memo.hasEntityRef(name2);
|
|
128
121
|
}
|
|
129
|
-
return
|
|
122
|
+
return true;
|
|
130
123
|
}
|
|
131
124
|
/**
|
|
132
125
|
* syncedHasLink determines whether role: name1 inherits role: name2.
|
|
@@ -173,6 +166,18 @@ class BackstageRoleManager {
|
|
|
173
166
|
);
|
|
174
167
|
await memo.buildUserGraph(memo);
|
|
175
168
|
memo.debugNodesAndEdges(this.logger, name);
|
|
169
|
+
memo.setNode(name);
|
|
170
|
+
if (!memo.isAcyclic()) {
|
|
171
|
+
const cycles = memo.findCycles();
|
|
172
|
+
this.logger.warn(
|
|
173
|
+
`Detected cycle dependencies in the Group graph: ${JSON.stringify(
|
|
174
|
+
cycles
|
|
175
|
+
)}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(
|
|
176
|
+
cycles
|
|
177
|
+
)}`
|
|
178
|
+
);
|
|
179
|
+
return Promise.resolve([]);
|
|
180
|
+
}
|
|
176
181
|
if (this.isPGClient()) {
|
|
177
182
|
const currentRole = new memberList.RoleMemberList(name);
|
|
178
183
|
await currentRole.buildRoles(
|
|
@@ -183,7 +188,6 @@ class BackstageRoleManager {
|
|
|
183
188
|
return Promise.resolve(currentRole.getRoles());
|
|
184
189
|
}
|
|
185
190
|
const allRoles = [];
|
|
186
|
-
memo.setNode(name);
|
|
187
191
|
for (const value of this.allRoles.values()) {
|
|
188
192
|
if (this.hasMember(value, memo)) {
|
|
189
193
|
allRoles.push(value.name);
|
|
@@ -222,11 +226,6 @@ class BackstageRoleManager {
|
|
|
222
226
|
this.allRoles.set(name, newRole);
|
|
223
227
|
return newRole;
|
|
224
228
|
}
|
|
225
|
-
// parse the entity to find out if it is a user / group / or role
|
|
226
|
-
parseEntityKind(name) {
|
|
227
|
-
const parsed = name.split(":");
|
|
228
|
-
return parsed[0];
|
|
229
|
-
}
|
|
230
229
|
/**
|
|
231
230
|
* isPGClient checks what the current database client is at them time.
|
|
232
231
|
* This is to ensure that we are querying the database in the event of postgres
|
|
@@ -237,26 +236,6 @@ class BackstageRoleManager {
|
|
|
237
236
|
const client = this.rbacDBClient.client.config.client;
|
|
238
237
|
return client === "pg";
|
|
239
238
|
}
|
|
240
|
-
/**
|
|
241
|
-
* checkForUserToRole checks if there exists a direct declaration of a user to a role. Used to exit out of
|
|
242
|
-
* hasLink faster in the event to reduce the time it would take to build the user graph.
|
|
243
|
-
* @param name1 The user that we are checking for.
|
|
244
|
-
* @param name2 The role that we are checking for.
|
|
245
|
-
* @returns True if there is a user that is directly attached to a particular role.
|
|
246
|
-
*/
|
|
247
|
-
async checkForUserToRole(name1, name2, currentRole) {
|
|
248
|
-
const tempRole = this.getOrCreateRole(name2);
|
|
249
|
-
if (this.parseEntityKind(name2) === "role" && tempRole.hasMember(name1)) {
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
|
-
if (tempRole.getMembers().length === 0) {
|
|
253
|
-
this.allRoles.delete(name2);
|
|
254
|
-
}
|
|
255
|
-
if (currentRole && currentRole.hasMember(name1)) {
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
|
-
return void 0;
|
|
259
|
-
}
|
|
260
239
|
/**
|
|
261
240
|
* hasMember checks if the members from a particular role is associated with the user
|
|
262
241
|
* that the AncestorSearchMemo graph is built for.
|
|
@@ -265,7 +244,7 @@ class BackstageRoleManager {
|
|
|
265
244
|
* @returns True if a member from the role is also associated with the user.
|
|
266
245
|
*/
|
|
267
246
|
hasMember(role, memo) {
|
|
268
|
-
if (role ===
|
|
247
|
+
if (role === undefined) {
|
|
269
248
|
return false;
|
|
270
249
|
}
|
|
271
250
|
for (const member of role.getMembers()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-manager.cjs.js","sources":["../../src/role-manager/role-manager.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { AuthService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport type { Config } from '@backstage/config';\n\nimport { RoleManager } from 'casbin';\nimport { Knex } from 'knex';\n\nimport { AncestorSearchMemo } from './ancestor-search-memo';\nimport { RoleMemberList } from './member-list';\n\nexport class BackstageRoleManager implements RoleManager {\n private allRoles: Map<string, RoleMemberList>;\n private maxDepth?: number;\n constructor(\n private readonly catalogApi: CatalogApi,\n private readonly logger: LoggerService,\n private readonly catalogDBClient: Knex,\n private readonly rbacDBClient: Knex,\n private readonly config: Config,\n private readonly auth: AuthService,\n ) {\n this.allRoles = new Map<string, RoleMemberList>();\n const rbacConfig = this.config.getOptionalConfig('permission.rbac');\n this.maxDepth = rbacConfig?.getOptionalNumber('maxDepth');\n if (this.maxDepth !== undefined && this.maxDepth! < 0) {\n throw new Error(\n 'Max Depth for RBAC group hierarchy must be greater than or equal to zero',\n );\n }\n }\n\n /**\n * clear clears all stored data and resets the role manager to the initial state.\n */\n async clear(): Promise<void> {\n // do nothing\n }\n\n /**\n * addLink adds the inheritance link between name1 and role: name2.\n * aka name1 inherits role: name2.\n * The link that is established is based on the defined grouping policies that are added by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be assigned to a role.\n * @param name2 The role that will be created or updated.\n * @param _domain Unimplemented prefix to the role.\n */\n async addLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.addMember(name1);\n }\n }\n\n /**\n * deleteLink deletes the inheritance link between name1 and role: name2.\n * aka name1 does not inherit role: name2 any more.\n * The link that is deleted is based on the defined grouping policies that are removed by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be removed from assignment of a role.\n * @param name2 The role that will be deleted or updated.\n * @param _domain Unimplemented.\n */\n async deleteLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.deleteMember(name1);\n\n // Clean up in the event that there are no more members in the role\n if (role1.getMembers().length === 0) {\n this.allRoles.delete(name2);\n }\n }\n }\n\n /**\n * hasLink determines whether name1 inherits role: name2.\n * During this check we build the group hierarchy graph to determine if the particular user is directly or indirectly\n * attached to the role that we are receiving.\n * In the event that there is a postgres database connection, we will attempt to query the roles from the database.\n * Otherwise we will use the cached allRoles to determine if there is a link.\n * @param name1 The user that we are authorizing.\n * @param name2 The name of the role that we are checking against.\n * @param domain Unimplemented.\n * @returns True if the user is directly or indirectly attached to the role.\n */\n async hasLink(\n name1: string,\n name2: string,\n ...domain: string[]\n ): Promise<boolean> {\n let currentRole: RoleMemberList;\n if (domain.length > 0) {\n throw new Error('domain argument is not supported.');\n }\n\n // Name2 can be an empty string in the event that there is not a role associated with the user\n // This happens because of the filtering of the roles reduces the number of roles that we iterate through.\n if (name2.length === 0) {\n return false;\n }\n\n if (name1 === name2) {\n return true;\n }\n\n if (this.isPGClient()) {\n currentRole = new RoleMemberList(name2);\n await currentRole.buildMembers(currentRole, this.rbacDBClient);\n } else {\n currentRole = this.allRoles.get(name2)!;\n }\n\n // Check for direct declaration of user to role\n const directDeclaration = await this.checkForUserToRole(\n name1,\n name2,\n currentRole,\n );\n if (directDeclaration) {\n return true;\n }\n\n // name1 is always user in our case.\n // name2 is user or group.\n // user(name1) couldn't inherit user(name2).\n // We can use this fact for optimization.\n const { kind } = parseEntityRef(name2);\n if (kind.toLocaleLowerCase() === 'user') {\n return false;\n }\n\n const memo = new AncestorSearchMemo(\n name1,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n await memo.buildUserGraph(memo);\n\n memo.debugNodesAndEdges(this.logger, name1);\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n\n return false;\n }\n\n if (\n this.parseEntityKind(name2) === 'role' &&\n this.hasMember(currentRole, memo)\n ) {\n return true;\n }\n return memo.hasEntityRef(name2);\n }\n\n /**\n * syncedHasLink determines whether role: name1 inherits role: name2.\n * domain is a prefix to the roles.\n */\n syncedHasLink?(\n _name1: string,\n _name2: string,\n ..._domain: string[]\n ): boolean {\n throw new Error('Method \"syncedHasLink\" not implemented.');\n }\n\n /**\n * getRoles gets the roles that a subject inherits.\n *\n * name - is a string entity reference, for example: user:default/tom, role:default/dev,\n * so format is <kind>:<namespace>/<entity-name>.\n * GetRoles method supports only two kind values: 'user' and 'role'.\n *\n * domain - is a prefix to the roles, unused parameter.\n *\n * If name's kind === 'user' we return all inherited roles from groups and roles directly assigned to the user.\n * if name's kind === 'role' we return empty array, because we don't support role inheritance.\n * Case kind === 'group' - should not happen, because:\n * 1) Method getRoles returns only role entity references, so casbin engine doesn't call this\n * method again to ask about name with kind \"group\".\n * 2) We implemented getRoles method only to use:\n * 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * so name argument can be only with kind 'user' or 'role'.\n *\n * Info: when we call 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * then casbin engine executes 'getRoles' method few times.\n * Firstly casbin asks about roles for 'userEntityRef'.\n * Let's imagine, that 'getRoles' returned two roles for userEntityRef.\n * Then casbin calls 'getRoles' two more times to\n * find parent roles. But we return empty array for each such call,\n * because we don't support role inheritance and we notify casbin about end of the role sub-tree.\n */\n async getRoles(name: string, ..._domain: string[]): Promise<string[]> {\n const { kind } = parseEntityRef(name);\n if (kind === 'user') {\n const memo = new AncestorSearchMemo(\n name,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n await memo.buildUserGraph(memo);\n memo.debugNodesAndEdges(this.logger, name);\n\n if (this.isPGClient()) {\n const currentRole = new RoleMemberList(name);\n await currentRole.buildRoles(\n currentRole,\n memo.getNodes(),\n this.rbacDBClient,\n );\n return Promise.resolve(currentRole.getRoles());\n }\n\n const allRoles: string[] = [];\n // Account for the user not being in the graph\n memo.setNode(name);\n for (const value of this.allRoles.values()) {\n if (this.hasMember(value, memo)) {\n allRoles.push(value.name);\n }\n }\n\n return Promise.resolve(allRoles);\n }\n\n return [];\n }\n\n /**\n * getUsers gets the users that inherits a subject.\n * domain is an unreferenced parameter here, may be used in other implementations.\n */\n async getUsers(_name: string, ..._domain: string[]): Promise<string[]> {\n throw new Error('Method \"getUsers\" not implemented.');\n }\n\n /**\n * printRoles prints all the roles to log.\n */\n async printRoles(): Promise<void> {\n // do nothing\n }\n\n /**\n * getOrCreateRole will get a role if it has already been cached\n * or it will create a new role to be cached.\n * This cache is a simple tree that is used to quickly compare\n * users and groups to roles.\n * @param name The user or group whose cache we will be getting / creating.\n * @returns The cached role as a RoleList.\n */\n private getOrCreateRole(name: string): RoleMemberList {\n const role = this.allRoles.get(name);\n if (role) {\n return role;\n }\n const newRole = new RoleMemberList(name);\n this.allRoles.set(name, newRole);\n\n return newRole;\n }\n\n // parse the entity to find out if it is a user / group / or role\n private parseEntityKind(name: string): string {\n const parsed = name.split(':');\n return parsed[0];\n }\n\n /**\n * isPGClient checks what the current database client is at them time.\n * This is to ensure that we are querying the database in the event of postgres\n * or using in memory cache for better sqlite3.\n * @returns True if the database client is pg.\n */\n isPGClient(): boolean {\n const client = this.rbacDBClient.client.config.client;\n return client === 'pg';\n }\n\n /**\n * checkForUserToRole checks if there exists a direct declaration of a user to a role. Used to exit out of\n * hasLink faster in the event to reduce the time it would take to build the user graph.\n * @param name1 The user that we are checking for.\n * @param name2 The role that we are checking for.\n * @returns True if there is a user that is directly attached to a particular role.\n */\n private async checkForUserToRole(\n name1: string,\n name2: string,\n currentRole: RoleMemberList | undefined,\n ): Promise<boolean | undefined> {\n const tempRole = this.getOrCreateRole(name2);\n\n // Immediately check if the our temporary role has a link with the role that we are comparing it to\n if (this.parseEntityKind(name2) === 'role' && tempRole.hasMember(name1)) {\n return true;\n }\n\n // Clean up the temp role\n if (tempRole.getMembers().length === 0) {\n this.allRoles.delete(name2);\n }\n\n if (currentRole && currentRole.hasMember(name1)) {\n return true;\n }\n\n return undefined;\n }\n\n /**\n * hasMember checks if the members from a particular role is associated with the user\n * that the AncestorSearchMemo graph is built for.\n * @param role The role that we are getting the members from.\n * @param memo The user graph that we are comparing members with.\n * @returns True if a member from the role is also associated with the user.\n */\n private hasMember(\n role: RoleMemberList | undefined,\n memo: AncestorSearchMemo,\n ): boolean {\n if (role === undefined) {\n return false;\n }\n\n for (const member of role.getMembers()) {\n if (memo.hasEntityRef(member)) {\n return true;\n }\n }\n return false;\n }\n}\n"],"names":["RoleMemberList","parseEntityRef","AncestorSearchMemo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"role-manager.cjs.js","sources":["../../src/role-manager/role-manager.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { AuthService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport type { Config } from '@backstage/config';\n\nimport { RoleManager } from 'casbin';\nimport { Knex } from 'knex';\n\nimport { AncestorSearchMemo } from './ancestor-search-memo';\nimport { RoleMemberList } from './member-list';\n\nexport class BackstageRoleManager implements RoleManager {\n private allRoles: Map<string, RoleMemberList>;\n private maxDepth?: number;\n constructor(\n private readonly catalogApi: CatalogApi,\n private readonly logger: LoggerService,\n private readonly catalogDBClient: Knex,\n private readonly rbacDBClient: Knex,\n private readonly config: Config,\n private readonly auth: AuthService,\n ) {\n this.allRoles = new Map<string, RoleMemberList>();\n const rbacConfig = this.config.getOptionalConfig('permission.rbac');\n this.maxDepth = rbacConfig?.getOptionalNumber('maxDepth');\n if (this.maxDepth !== undefined && this.maxDepth! < 0) {\n throw new Error(\n 'Max Depth for RBAC group hierarchy must be greater than or equal to zero',\n );\n }\n }\n\n /**\n * clear clears all stored data and resets the role manager to the initial state.\n */\n async clear(): Promise<void> {\n // do nothing\n }\n\n /**\n * addLink adds the inheritance link between name1 and role: name2.\n * aka name1 inherits role: name2.\n * The link that is established is based on the defined grouping policies that are added by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be assigned to a role.\n * @param name2 The role that will be created or updated.\n * @param _domain Unimplemented prefix to the role.\n */\n async addLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.addMember(name1);\n }\n }\n\n /**\n * deleteLink deletes the inheritance link between name1 and role: name2.\n * aka name1 does not inherit role: name2 any more.\n * The link that is deleted is based on the defined grouping policies that are removed by the enforcer.\n *\n * ex. `g, name1, name2`.\n * @param name1 User or group that will be removed from assignment of a role.\n * @param name2 The role that will be deleted or updated.\n * @param _domain Unimplemented.\n */\n async deleteLink(\n name1: string,\n name2: string,\n ..._domain: string[]\n ): Promise<void> {\n if (!this.isPGClient()) {\n const role1 = this.getOrCreateRole(name2);\n role1.deleteMember(name1);\n\n // Clean up in the event that there are no more members in the role\n if (role1.getMembers().length === 0) {\n this.allRoles.delete(name2);\n }\n }\n }\n\n /**\n * hasLink determines whether name1 inherits role: name2.\n * Before this check is called in the background by the enforcer,\n * we filter out all roles that the user is not connected to\n * directly or indirectly through the use of retrieving roles through\n * enforcer.getRolesForUser and apply those roles to a tempEnforcer.\n *\n * This means that hasLink will almost always be true in the event that a user\n * is assigned to a role (either directly or indirectly)\n *\n * In the event that a user or group is not assigned to a role and instead\n * are assigned directly to permissions, then name2 will become either that\n * user or group through the filtering. In this case we will build the graph\n * if necessary for name2 group presence or evaulate based on the names matching.\n * @param name1 The user that we are authorizing.\n * @param name2 The name of the role that we are checking against.\n * @param domain Unimplemented.\n * @returns True if the user is directly or indirectly attached to the role.\n */\n async hasLink(\n name1: string,\n name2: string,\n ...domain: string[]\n ): Promise<boolean> {\n if (domain.length > 0) {\n throw new Error('domain argument is not supported.');\n }\n\n // Name2 can be an empty string in the event that there is not a role associated with the user\n // This happens because of the filtering of the roles reduces the number of roles that we iterate through.\n if (name2.length === 0) {\n return false;\n }\n\n if (name1 === name2) {\n return true;\n }\n\n // name1 is always user in our case.\n // name2 is user or group.\n // user(name1) couldn't inherit user(name2).\n // We can use this fact for optimization.\n const { kind } = parseEntityRef(name2);\n if (kind.toLocaleLowerCase() === 'user') {\n return false;\n }\n\n // if it is a group, then we will have to build the graph,\n if (kind.toLocaleLowerCase() === 'group') {\n const memo = new AncestorSearchMemo(\n name1,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n await memo.buildUserGraph(memo);\n memo.debugNodesAndEdges(this.logger, name1);\n\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n return false;\n }\n\n return memo.hasEntityRef(name2);\n }\n\n return true;\n }\n\n /**\n * syncedHasLink determines whether role: name1 inherits role: name2.\n * domain is a prefix to the roles.\n */\n syncedHasLink?(\n _name1: string,\n _name2: string,\n ..._domain: string[]\n ): boolean {\n throw new Error('Method \"syncedHasLink\" not implemented.');\n }\n\n /**\n * getRoles gets the roles that a subject inherits.\n *\n * name - is a string entity reference, for example: user:default/tom, role:default/dev,\n * so format is <kind>:<namespace>/<entity-name>.\n * GetRoles method supports only two kind values: 'user' and 'role'.\n *\n * domain - is a prefix to the roles, unused parameter.\n *\n * If name's kind === 'user' we return all inherited roles from groups and roles directly assigned to the user.\n * if name's kind === 'role' we return empty array, because we don't support role inheritance.\n * Case kind === 'group' - should not happen, because:\n * 1) Method getRoles returns only role entity references, so casbin engine doesn't call this\n * method again to ask about name with kind \"group\".\n * 2) We implemented getRoles method only to use:\n * 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * so name argument can be only with kind 'user' or 'role'.\n *\n * Info: when we call 'await enforcer.getImplicitPermissionsForUser(userEntityRef)',\n * then casbin engine executes 'getRoles' method few times.\n * Firstly casbin asks about roles for 'userEntityRef'.\n * Let's imagine, that 'getRoles' returned two roles for userEntityRef.\n * Then casbin calls 'getRoles' two more times to\n * find parent roles. But we return empty array for each such call,\n * because we don't support role inheritance and we notify casbin about end of the role sub-tree.\n */\n async getRoles(name: string, ..._domain: string[]): Promise<string[]> {\n const { kind } = parseEntityRef(name);\n if (kind === 'user') {\n const memo = new AncestorSearchMemo(\n name,\n this.catalogApi,\n this.catalogDBClient,\n this.auth,\n this.maxDepth,\n );\n await memo.buildUserGraph(memo);\n memo.debugNodesAndEdges(this.logger, name);\n\n // Account for the user not being in the graph (this can happen during direct assignment to roles)\n memo.setNode(name);\n\n if (!memo.isAcyclic()) {\n const cycles = memo.findCycles();\n\n this.logger.warn(\n `Detected cycle dependencies in the Group graph: ${JSON.stringify(\n cycles,\n )}. Admin/(catalog owner) have to fix it to make RBAC permission evaluation correct for groups: ${JSON.stringify(\n cycles,\n )}`,\n );\n return Promise.resolve([]);\n }\n\n if (this.isPGClient()) {\n const currentRole = new RoleMemberList(name);\n await currentRole.buildRoles(\n currentRole,\n memo.getNodes(),\n this.rbacDBClient,\n );\n return Promise.resolve(currentRole.getRoles());\n }\n\n const allRoles: string[] = [];\n for (const value of this.allRoles.values()) {\n if (this.hasMember(value, memo)) {\n allRoles.push(value.name);\n }\n }\n\n return Promise.resolve(allRoles);\n }\n\n return [];\n }\n\n /**\n * getUsers gets the users that inherits a subject.\n * domain is an unreferenced parameter here, may be used in other implementations.\n */\n async getUsers(_name: string, ..._domain: string[]): Promise<string[]> {\n throw new Error('Method \"getUsers\" not implemented.');\n }\n\n /**\n * printRoles prints all the roles to log.\n */\n async printRoles(): Promise<void> {\n // do nothing\n }\n\n /**\n * getOrCreateRole will get a role if it has already been cached\n * or it will create a new role to be cached.\n * This cache is a simple tree that is used to quickly compare\n * users and groups to roles.\n * @param name The user or group whose cache we will be getting / creating.\n * @returns The cached role as a RoleList.\n */\n private getOrCreateRole(name: string): RoleMemberList {\n const role = this.allRoles.get(name);\n if (role) {\n return role;\n }\n const newRole = new RoleMemberList(name);\n this.allRoles.set(name, newRole);\n\n return newRole;\n }\n\n /**\n * isPGClient checks what the current database client is at them time.\n * This is to ensure that we are querying the database in the event of postgres\n * or using in memory cache for better sqlite3.\n * @returns True if the database client is pg.\n */\n isPGClient(): boolean {\n const client = this.rbacDBClient.client.config.client;\n return client === 'pg';\n }\n\n /**\n * hasMember checks if the members from a particular role is associated with the user\n * that the AncestorSearchMemo graph is built for.\n * @param role The role that we are getting the members from.\n * @param memo The user graph that we are comparing members with.\n * @returns True if a member from the role is also associated with the user.\n */\n private hasMember(\n role: RoleMemberList | undefined,\n memo: AncestorSearchMemo,\n ): boolean {\n if (role === undefined) {\n return false;\n }\n\n for (const member of role.getMembers()) {\n if (memo.hasEntityRef(member)) {\n return true;\n }\n }\n return false;\n }\n}\n"],"names":["parseEntityRef","AncestorSearchMemo","RoleMemberList"],"mappings":"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"}
|
|
@@ -21,13 +21,11 @@ class EnforcerDelegate {
|
|
|
21
21
|
}
|
|
22
22
|
roleEventEmitter = new EventEmitter__default.default();
|
|
23
23
|
loadPolicyPromise = null;
|
|
24
|
-
semaphore = 0;
|
|
25
24
|
editOperationsQueue = [];
|
|
26
25
|
async loadPolicy() {
|
|
27
26
|
if (this.loadPolicyPromise) {
|
|
28
27
|
return this.loadPolicyPromise;
|
|
29
28
|
}
|
|
30
|
-
this.semaphore++;
|
|
31
29
|
this.loadPolicyPromise = (async () => {
|
|
32
30
|
try {
|
|
33
31
|
await this.waitForEditOperationsToFinish();
|
|
@@ -41,7 +39,6 @@ class EnforcerDelegate {
|
|
|
41
39
|
errors: [err]
|
|
42
40
|
});
|
|
43
41
|
} finally {
|
|
44
|
-
this.semaphore--;
|
|
45
42
|
this.loadPolicyPromise = null;
|
|
46
43
|
}
|
|
47
44
|
})();
|
|
@@ -169,6 +166,8 @@ class EnforcerDelegate {
|
|
|
169
166
|
async addPolicies(policies, externalTrx) {
|
|
170
167
|
if (this.loadPolicyPromise) {
|
|
171
168
|
await this.loadPolicyPromise;
|
|
169
|
+
} else {
|
|
170
|
+
await this.loadPolicy();
|
|
172
171
|
}
|
|
173
172
|
const addPoliciesOperation = (async () => {
|
|
174
173
|
if (policies.length === 0) {
|
|
@@ -197,6 +196,8 @@ class EnforcerDelegate {
|
|
|
197
196
|
async addGroupingPolicy(policy, roleMetadata, externalTrx) {
|
|
198
197
|
if (this.loadPolicyPromise) {
|
|
199
198
|
await this.loadPolicyPromise;
|
|
199
|
+
} else {
|
|
200
|
+
await this.loadPolicy();
|
|
200
201
|
}
|
|
201
202
|
const addGroupingPolicyOperation = (async () => {
|
|
202
203
|
const trx = externalTrx ?? await this.knex.transaction();
|
|
@@ -246,6 +247,8 @@ class EnforcerDelegate {
|
|
|
246
247
|
async addGroupingPolicies(policies, roleMetadata, externalTrx) {
|
|
247
248
|
if (this.loadPolicyPromise) {
|
|
248
249
|
await this.loadPolicyPromise;
|
|
250
|
+
} else {
|
|
251
|
+
await this.loadPolicy();
|
|
249
252
|
}
|
|
250
253
|
const addGroupingPoliciesOperation = (async () => {
|
|
251
254
|
if (policies.length === 0) {
|
|
@@ -323,6 +326,8 @@ class EnforcerDelegate {
|
|
|
323
326
|
async removePolicy(policy, externalTrx) {
|
|
324
327
|
if (this.loadPolicyPromise) {
|
|
325
328
|
await this.loadPolicyPromise;
|
|
329
|
+
} else {
|
|
330
|
+
await this.loadPolicy();
|
|
326
331
|
}
|
|
327
332
|
const removePolicyOperation = (async () => {
|
|
328
333
|
const trx = externalTrx ?? await this.knex.transaction();
|
|
@@ -346,6 +351,8 @@ class EnforcerDelegate {
|
|
|
346
351
|
async removePolicies(policies, externalTrx) {
|
|
347
352
|
if (this.loadPolicyPromise) {
|
|
348
353
|
await this.loadPolicyPromise;
|
|
354
|
+
} else {
|
|
355
|
+
await this.loadPolicy();
|
|
349
356
|
}
|
|
350
357
|
const removePoliciesOperation = (async () => {
|
|
351
358
|
const trx = externalTrx ?? await this.knex.transaction();
|
|
@@ -371,6 +378,8 @@ class EnforcerDelegate {
|
|
|
371
378
|
async removeGroupingPolicy(policy, roleMetadata, isUpdate, externalTrx) {
|
|
372
379
|
if (this.loadPolicyPromise) {
|
|
373
380
|
await this.loadPolicyPromise;
|
|
381
|
+
} else {
|
|
382
|
+
await this.loadPolicy();
|
|
374
383
|
}
|
|
375
384
|
const removeGroupingPolicyOperation = (async () => {
|
|
376
385
|
const trx = externalTrx ?? await this.knex.transaction();
|
|
@@ -411,6 +420,8 @@ class EnforcerDelegate {
|
|
|
411
420
|
async removeGroupingPolicies(policies, roleMetadata, isUpdate, externalTrx) {
|
|
412
421
|
if (this.loadPolicyPromise) {
|
|
413
422
|
await this.loadPolicyPromise;
|
|
423
|
+
} else {
|
|
424
|
+
await this.loadPolicy();
|
|
414
425
|
}
|
|
415
426
|
const removeGroupingPolicyOperation = (async () => {
|
|
416
427
|
const trx = externalTrx ?? await this.knex.transaction();
|
|
@@ -474,35 +485,41 @@ class EnforcerDelegate {
|
|
|
474
485
|
* @returns True if the user is allowed based on the particular permission
|
|
475
486
|
*/
|
|
476
487
|
async enforce(entityRef, resourceType, action, roles) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
+
const model = casbin.newModelFromString(permissionModel.MODEL);
|
|
489
|
+
let policies = [];
|
|
490
|
+
if (roles.length > 0) {
|
|
491
|
+
for (const role of roles) {
|
|
492
|
+
const filteredPolicy = await this.getFilteredPolicy(
|
|
493
|
+
0,
|
|
494
|
+
role,
|
|
495
|
+
resourceType,
|
|
496
|
+
action
|
|
497
|
+
);
|
|
498
|
+
policies.push(...filteredPolicy);
|
|
488
499
|
}
|
|
489
|
-
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
adapt,
|
|
495
|
-
true
|
|
500
|
+
} else {
|
|
501
|
+
const enforcePolicies = await this.getFilteredPolicy(
|
|
502
|
+
1,
|
|
503
|
+
resourceType,
|
|
504
|
+
action
|
|
496
505
|
);
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
501
|
-
|
|
506
|
+
policies = enforcePolicies.filter(
|
|
507
|
+
(policy) => policy[0].startsWith("user:") || policy[0].startsWith("group:")
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
const roleManager = this.enforcer.getRoleManager();
|
|
511
|
+
const tempEnforcer = new casbin.Enforcer();
|
|
512
|
+
model.addPolicies("p", "p", policies);
|
|
513
|
+
await tempEnforcer.initWithModelAndAdapter(model);
|
|
514
|
+
tempEnforcer.setRoleManager(roleManager);
|
|
515
|
+
await tempEnforcer.buildRoleLinks();
|
|
516
|
+
return await tempEnforcer.enforce(entityRef, resourceType, action);
|
|
502
517
|
}
|
|
503
518
|
async getImplicitPermissionsForUser(user) {
|
|
504
519
|
if (this.loadPolicyPromise) {
|
|
505
520
|
await this.loadPolicyPromise;
|
|
521
|
+
} else {
|
|
522
|
+
await this.loadPolicy();
|
|
506
523
|
}
|
|
507
524
|
const getPermissionsForUserOperation = (async () => {
|
|
508
525
|
return this.enforcer.getImplicitPermissionsForUser(user);
|
|
@@ -512,6 +529,8 @@ class EnforcerDelegate {
|
|
|
512
529
|
async getAllRoles() {
|
|
513
530
|
if (this.loadPolicyPromise) {
|
|
514
531
|
await this.loadPolicyPromise;
|
|
532
|
+
} else {
|
|
533
|
+
await this.loadPolicy();
|
|
515
534
|
}
|
|
516
535
|
const getRolesOperation = (async () => {
|
|
517
536
|
return this.enforcer.getAllRoles();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enforcer-delegate.cjs.js","sources":["../../src/service/enforcer-delegate.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 { Enforcer, FilteredAdapter, newModelFromString } from 'casbin';\nimport { Knex } from 'knex';\n\nimport EventEmitter from 'events';\n\nimport { ADMIN_ROLE_NAME } from '../admin-permissions/admin-creation';\nimport {\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport { mergeRoleMetadata, policiesToString, policyToString } from '../helper';\nimport { MODEL } from './permission-model';\nimport { AuditLogger } from '@janus-idp/backstage-plugin-audit-log-node';\nimport {\n FETCH_NEWER_PERMISSIONS_STAGE,\n PoliciesData,\n} from '../audit-log/audit-logger';\n\nexport type RoleEvents = 'roleAdded';\nexport interface RoleEventEmitter<T extends RoleEvents> {\n on(event: T, listener: (roleEntityRef: string | string[]) => void): this;\n}\n\ntype EventMap = {\n [event in RoleEvents]: any[];\n};\n\nexport class EnforcerDelegate implements RoleEventEmitter<RoleEvents> {\n private readonly roleEventEmitter = new EventEmitter<EventMap>();\n\n private loadPolicyPromise: Promise<void> | null = null;\n private semaphore: number = 0;\n private editOperationsQueue: Promise<any>[] = []; // Queue to track edit operations\n\n constructor(\n private readonly enforcer: Enforcer,\n private readonly auditLogger: AuditLogger,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly knex: Knex,\n ) {}\n\n async loadPolicy(): Promise<void> {\n if (this.loadPolicyPromise) {\n // If a load operation is already in progress, return the cached promise\n return this.loadPolicyPromise;\n }\n\n // Increment semaphore to block edits during load\n this.semaphore++;\n\n this.loadPolicyPromise = (async () => {\n try {\n await this.waitForEditOperationsToFinish();\n\n await this.enforcer.loadPolicy();\n } catch (err) {\n this.auditLogger.auditLog({\n message: 'Failed to load newer policies from database',\n eventName: PoliciesData.FAILED_TO_FETCH_NEWER_PERMISSIONS,\n stage: FETCH_NEWER_PERMISSIONS_STAGE,\n status: 'failed',\n errors: [err],\n });\n } finally {\n this.semaphore--;\n this.loadPolicyPromise = null;\n }\n })();\n\n return this.loadPolicyPromise;\n }\n\n private async waitForEditOperationsToFinish(): Promise<void> {\n await Promise.all(this.editOperationsQueue);\n }\n\n async execOperation<T>(operation: Promise<T>): Promise<T> {\n this.editOperationsQueue.push(operation);\n\n let result;\n try {\n result = await operation;\n } catch (err) {\n throw err;\n } finally {\n const index = this.editOperationsQueue.indexOf(operation);\n if (index !== -1) {\n this.editOperationsQueue.splice(index, 1);\n }\n }\n\n return result;\n }\n\n on(event: RoleEvents, listener: (role: string) => void): this {\n this.roleEventEmitter.on(event, listener);\n return this;\n }\n\n async hasPolicy(...policy: string[]): Promise<boolean> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [\n {\n ptype: 'p',\n v0: policy[0],\n v1: policy[1],\n v2: policy[2],\n v3: policy[3],\n },\n ],\n );\n return tempModel.hasPolicy('p', 'p', policy);\n }\n\n async hasGroupingPolicy(...policy: string[]): Promise<boolean> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [\n {\n ptype: 'g',\n v0: policy[0],\n v1: policy[1],\n },\n ],\n );\n return tempModel.hasPolicy('g', 'g', policy);\n }\n\n async getPolicy(): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [{ ptype: 'p' }],\n );\n return await tempModel.getPolicy('p', 'p');\n }\n\n async getGroupingPolicy(): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [{ ptype: 'g' }],\n );\n return await tempModel.getPolicy('g', 'g');\n }\n\n async getRolesForUser(userEntityRef: string): Promise<string[]> {\n return await this.enforcer.getRolesForUser(userEntityRef);\n }\n\n async getFilteredPolicy(\n fieldIndex: number,\n ...filter: string[]\n ): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n\n const filterArgs: Record<string, string>[] = [];\n const filterObj: Record<string, string> = { ptype: 'p' };\n for (let i = 0; i < filter.length; i++) {\n filterObj[`v${i + fieldIndex}`] = filter[i];\n filterArgs.push(filterObj);\n }\n\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n filterArgs,\n );\n\n return await tempModel.getPolicy('p', 'p');\n }\n\n async getFilteredGroupingPolicy(\n fieldIndex: number,\n ...filter: string[]\n ): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n\n const filterArgs: Record<string, string>[] = [];\n const filterObj: Record<string, string> = { ptype: 'g' };\n for (let i = 0; i < filter.length; i++) {\n filterObj[`v${i + fieldIndex}`] = filter[i];\n filterArgs.push(filterObj);\n }\n\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n filterArgs,\n );\n\n return await tempModel.getPolicy('g', 'g');\n }\n\n async addPolicy(\n policy: string[],\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n const trx = externalTrx ?? (await this.knex.transaction());\n\n if (await this.hasPolicy(...policy)) {\n return;\n }\n try {\n const ok = await this.enforcer.addPolicy(...policy);\n if (!ok) {\n throw new Error(`failed to create policy ${policyToString(policy)}`);\n }\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n }\n\n async addPolicies(\n policies: string[][],\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const addPoliciesOperation = (async () => {\n if (policies.length === 0) {\n return;\n }\n\n const trx = externalTrx || (await this.knex.transaction());\n\n try {\n const ok = await this.enforcer.addPolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to store policies ${policiesToString(policies)}`,\n );\n }\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(addPoliciesOperation);\n }\n\n async addGroupingPolicy(\n policy: string[],\n roleMetadata: RoleMetadataDao,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const addGroupingPolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n const entityRef = roleMetadata.roleEntityRef;\n\n if (await this.hasGroupingPolicy(...policy)) {\n return;\n }\n try {\n let currentMetadata;\n if (entityRef.startsWith(`role:`)) {\n currentMetadata = await this.roleMetadataStorage.findRoleMetadata(\n entityRef,\n trx,\n );\n }\n\n if (currentMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentMetadata, roleMetadata),\n entityRef,\n trx,\n );\n } else {\n const currentDate: Date = new Date();\n roleMetadata.createdAt = currentDate.toUTCString();\n roleMetadata.lastModified = currentDate.toUTCString();\n await this.roleMetadataStorage.createRoleMetadata(roleMetadata, trx);\n }\n\n const ok = await this.enforcer.addGroupingPolicy(...policy);\n if (!ok) {\n throw new Error(`failed to create policy ${policyToString(policy)}`);\n }\n if (!externalTrx) {\n await trx.commit();\n }\n if (!currentMetadata) {\n this.roleEventEmitter.emit('roleAdded', roleMetadata.roleEntityRef);\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(addGroupingPolicyOperation);\n }\n\n async addGroupingPolicies(\n policies: string[][],\n roleMetadata: RoleMetadataDao,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const addGroupingPoliciesOperation = (async () => {\n if (policies.length === 0) {\n return;\n }\n\n const trx = externalTrx ?? (await this.knex.transaction());\n\n try {\n const currentRoleMetadata =\n await this.roleMetadataStorage.findRoleMetadata(\n roleMetadata.roleEntityRef,\n trx,\n );\n if (currentRoleMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentRoleMetadata, roleMetadata),\n roleMetadata.roleEntityRef,\n trx,\n );\n } else {\n const currentDate: Date = new Date();\n roleMetadata.createdAt = currentDate.toUTCString();\n roleMetadata.lastModified = currentDate.toUTCString();\n await this.roleMetadataStorage.createRoleMetadata(roleMetadata, trx);\n }\n\n const ok = await this.enforcer.addGroupingPolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to store policies ${policiesToString(policies)}`,\n );\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n if (!currentRoleMetadata) {\n this.roleEventEmitter.emit('roleAdded', roleMetadata.roleEntityRef);\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(addGroupingPoliciesOperation);\n }\n\n async updateGroupingPolicies(\n oldRole: string[][],\n newRole: string[][],\n newRoleMetadata: RoleMetadataDao,\n ): Promise<void> {\n const oldRoleName = oldRole.at(0)?.at(1)!;\n\n const trx = await this.knex.transaction();\n try {\n const currentMetadata = await this.roleMetadataStorage.findRoleMetadata(\n oldRoleName,\n trx,\n );\n if (!currentMetadata) {\n throw new Error(`Role metadata ${oldRoleName} was not found`);\n }\n\n await this.removeGroupingPolicies(oldRole, currentMetadata, true, trx);\n await this.addGroupingPolicies(newRole, newRoleMetadata, trx);\n await trx.commit();\n } catch (err) {\n await trx.rollback(err);\n throw err;\n }\n }\n\n async updatePolicies(\n oldPolicies: string[][],\n newPolicies: string[][],\n ): Promise<void> {\n const trx = await this.knex.transaction();\n\n try {\n await this.removePolicies(oldPolicies, trx);\n await this.addPolicies(newPolicies, trx);\n await trx.commit();\n } catch (err) {\n await trx.rollback(err);\n throw err;\n }\n }\n\n async removePolicy(policy: string[], externalTrx?: Knex.Transaction) {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const removePolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n\n try {\n const ok = await this.enforcer.removePolicy(...policy);\n if (!ok) {\n throw new Error(`fail to delete policy ${policy}`);\n }\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removePolicyOperation);\n }\n\n async removePolicies(\n policies: string[][],\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const removePoliciesOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n\n try {\n const ok = await this.enforcer.removePolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to delete policies ${policiesToString(policies)}`,\n );\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removePoliciesOperation);\n }\n\n async removeGroupingPolicy(\n policy: string[],\n roleMetadata: RoleMetadataDao,\n isUpdate?: boolean,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const removeGroupingPolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n const roleEntity = policy[1];\n\n try {\n const ok = await this.enforcer.removeGroupingPolicy(...policy);\n if (!ok) {\n throw new Error(`Failed to delete policy ${policyToString(policy)}`);\n }\n\n if (!isUpdate) {\n const currentRoleMetadata =\n await this.roleMetadataStorage.findRoleMetadata(roleEntity, trx);\n const remainingGroupPolicies = await this.getFilteredGroupingPolicy(\n 1,\n roleEntity,\n );\n if (\n currentRoleMetadata &&\n remainingGroupPolicies.length === 0 &&\n roleEntity !== ADMIN_ROLE_NAME\n ) {\n await this.roleMetadataStorage.removeRoleMetadata(roleEntity, trx);\n } else if (currentRoleMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentRoleMetadata, roleMetadata),\n roleEntity,\n trx,\n );\n }\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removeGroupingPolicyOperation);\n }\n\n async removeGroupingPolicies(\n policies: string[][],\n roleMetadata: RoleMetadataDao,\n isUpdate?: boolean,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const removeGroupingPolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n const roleEntity = roleMetadata.roleEntityRef;\n\n try {\n const ok = await this.enforcer.removeGroupingPolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to delete grouping policies: ${policiesToString(policies)}`,\n );\n }\n\n if (!isUpdate) {\n const currentRoleMetadata =\n await this.roleMetadataStorage.findRoleMetadata(roleEntity, trx);\n const remainingGroupPolicies = await this.getFilteredGroupingPolicy(\n 1,\n roleEntity,\n );\n\n if (\n currentRoleMetadata &&\n remainingGroupPolicies.length === 0 &&\n roleEntity !== ADMIN_ROLE_NAME\n ) {\n await this.roleMetadataStorage.removeRoleMetadata(roleEntity, trx);\n } else if (currentRoleMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentRoleMetadata, roleMetadata),\n roleEntity,\n trx,\n );\n }\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removeGroupingPolicyOperation);\n }\n\n /**\n * enforce aims to enforce a particular permission policy based on the user that it receives.\n * Under the hood, enforce uses the `enforce` method from the enforcer`.\n *\n * Before enforcement, a filter is set up to reduce the number of permission policies that will\n * be loaded in.\n * This will reduce the amount of checks that need to be made to determine if a user is authorize\n * to perform an action\n *\n * A temporary enforcer will also be used while enforcing.\n * This is to ensure that the filter does not interact with the base enforcer.\n * The temporary enforcer has lazy loading of the permission policies enabled to reduce the amount\n * of time it takes to initialize the temporary enforcer.\n * The justification for lazy loading is because permission policies are already present in the\n * role manager / database and it will be filtered and loaded whenever `getFilteredPolicy` is called\n * and permissions / roles are applied to the temp enforcer\n * @param entityRef The user to enforce\n * @param resourceType The resource type / name of the permission policy\n * @param action The action of the permission policy\n * @param roles Any roles that the user is directly or indirectly attached to.\n * Used for filtering permission policies.\n * @returns True if the user is allowed based on the particular permission\n */\n async enforce(\n entityRef: string,\n resourceType: string,\n action: string,\n roles: string[],\n ): Promise<boolean> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const evaluatePermissionOperation = (async () => {\n const filter = [];\n if (roles.length > 0) {\n roles.forEach(role => {\n filter.push({ ptype: 'p', v0: role, v1: resourceType, v2: action });\n });\n } else {\n filter.push({ ptype: 'p', v1: resourceType, v2: action });\n }\n\n const adapt = this.enforcer.getAdapter();\n const roleManager = this.enforcer.getRoleManager();\n const tempEnforcer = new Enforcer();\n await tempEnforcer.initWithModelAndAdapter(\n newModelFromString(MODEL),\n adapt,\n true,\n );\n tempEnforcer.setRoleManager(roleManager);\n\n await tempEnforcer.loadFilteredPolicy(filter);\n\n return await tempEnforcer.enforce(entityRef, resourceType, action);\n })();\n\n return await this.execOperation(evaluatePermissionOperation);\n }\n\n async getImplicitPermissionsForUser(user: string): Promise<string[][]> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const getPermissionsForUserOperation = (async () => {\n return this.enforcer.getImplicitPermissionsForUser(user);\n })();\n\n return await this.execOperation(getPermissionsForUserOperation);\n }\n\n async getAllRoles(): Promise<string[]> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n }\n\n const getRolesOperation = (async () => {\n return this.enforcer.getAllRoles();\n })();\n\n return await this.execOperation(getRolesOperation);\n }\n}\n"],"names":["EventEmitter","PoliciesData","FETCH_NEWER_PERMISSIONS_STAGE","newModelFromString","MODEL","policyToString","policiesToString","mergeRoleMetadata","ADMIN_ROLE_NAME","Enforcer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"enforcer-delegate.cjs.js","sources":["../../src/service/enforcer-delegate.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 { Enforcer, FilteredAdapter, newModelFromString } from 'casbin';\nimport { Knex } from 'knex';\n\nimport EventEmitter from 'events';\n\nimport { ADMIN_ROLE_NAME } from '../admin-permissions/admin-creation';\nimport {\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport { mergeRoleMetadata, policiesToString, policyToString } from '../helper';\nimport { MODEL } from './permission-model';\nimport { AuditLogger } from '@janus-idp/backstage-plugin-audit-log-node';\nimport {\n FETCH_NEWER_PERMISSIONS_STAGE,\n PoliciesData,\n} from '../audit-log/audit-logger';\n\nexport type RoleEvents = 'roleAdded';\nexport interface RoleEventEmitter<T extends RoleEvents> {\n on(event: T, listener: (roleEntityRef: string | string[]) => void): this;\n}\n\ntype EventMap = {\n [event in RoleEvents]: any[];\n};\n\nexport class EnforcerDelegate implements RoleEventEmitter<RoleEvents> {\n private readonly roleEventEmitter = new EventEmitter<EventMap>();\n\n private loadPolicyPromise: Promise<void> | null = null;\n private editOperationsQueue: Promise<any>[] = []; // Queue to track edit operations\n\n constructor(\n private readonly enforcer: Enforcer,\n private readonly auditLogger: AuditLogger,\n private readonly roleMetadataStorage: RoleMetadataStorage,\n private readonly knex: Knex,\n ) {}\n\n async loadPolicy(): Promise<void> {\n if (this.loadPolicyPromise) {\n // If a load operation is already in progress, return the cached promise\n return this.loadPolicyPromise;\n }\n\n this.loadPolicyPromise = (async () => {\n try {\n await this.waitForEditOperationsToFinish();\n\n await this.enforcer.loadPolicy();\n } catch (err) {\n this.auditLogger.auditLog({\n message: 'Failed to load newer policies from database',\n eventName: PoliciesData.FAILED_TO_FETCH_NEWER_PERMISSIONS,\n stage: FETCH_NEWER_PERMISSIONS_STAGE,\n status: 'failed',\n errors: [err],\n });\n } finally {\n this.loadPolicyPromise = null;\n }\n })();\n\n return this.loadPolicyPromise;\n }\n\n private async waitForEditOperationsToFinish(): Promise<void> {\n await Promise.all(this.editOperationsQueue);\n }\n\n async execOperation<T>(operation: Promise<T>): Promise<T> {\n this.editOperationsQueue.push(operation);\n\n let result;\n try {\n result = await operation;\n } catch (err) {\n throw err;\n } finally {\n const index = this.editOperationsQueue.indexOf(operation);\n if (index !== -1) {\n this.editOperationsQueue.splice(index, 1);\n }\n }\n\n return result;\n }\n\n on(event: RoleEvents, listener: (role: string) => void): this {\n this.roleEventEmitter.on(event, listener);\n return this;\n }\n\n async hasPolicy(...policy: string[]): Promise<boolean> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [\n {\n ptype: 'p',\n v0: policy[0],\n v1: policy[1],\n v2: policy[2],\n v3: policy[3],\n },\n ],\n );\n return tempModel.hasPolicy('p', 'p', policy);\n }\n\n async hasGroupingPolicy(...policy: string[]): Promise<boolean> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [\n {\n ptype: 'g',\n v0: policy[0],\n v1: policy[1],\n },\n ],\n );\n return tempModel.hasPolicy('g', 'g', policy);\n }\n\n async getPolicy(): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [{ ptype: 'p' }],\n );\n return await tempModel.getPolicy('p', 'p');\n }\n\n async getGroupingPolicy(): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n [{ ptype: 'g' }],\n );\n return await tempModel.getPolicy('g', 'g');\n }\n\n async getRolesForUser(userEntityRef: string): Promise<string[]> {\n return await this.enforcer.getRolesForUser(userEntityRef);\n }\n\n async getFilteredPolicy(\n fieldIndex: number,\n ...filter: string[]\n ): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n\n const filterArgs: Record<string, string>[] = [];\n const filterObj: Record<string, string> = { ptype: 'p' };\n for (let i = 0; i < filter.length; i++) {\n filterObj[`v${i + fieldIndex}`] = filter[i];\n filterArgs.push(filterObj);\n }\n\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n filterArgs,\n );\n\n return await tempModel.getPolicy('p', 'p');\n }\n\n async getFilteredGroupingPolicy(\n fieldIndex: number,\n ...filter: string[]\n ): Promise<string[][]> {\n const tempModel = newModelFromString(MODEL);\n\n const filterArgs: Record<string, string>[] = [];\n const filterObj: Record<string, string> = { ptype: 'g' };\n for (let i = 0; i < filter.length; i++) {\n filterObj[`v${i + fieldIndex}`] = filter[i];\n filterArgs.push(filterObj);\n }\n\n await (this.enforcer.getAdapter() as FilteredAdapter).loadFilteredPolicy(\n tempModel,\n filterArgs,\n );\n\n return await tempModel.getPolicy('g', 'g');\n }\n\n async addPolicy(\n policy: string[],\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n const trx = externalTrx ?? (await this.knex.transaction());\n\n if (await this.hasPolicy(...policy)) {\n return;\n }\n try {\n const ok = await this.enforcer.addPolicy(...policy);\n if (!ok) {\n throw new Error(`failed to create policy ${policyToString(policy)}`);\n }\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n }\n\n async addPolicies(\n policies: string[][],\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const addPoliciesOperation = (async () => {\n if (policies.length === 0) {\n return;\n }\n\n const trx = externalTrx || (await this.knex.transaction());\n\n try {\n const ok = await this.enforcer.addPolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to store policies ${policiesToString(policies)}`,\n );\n }\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(addPoliciesOperation);\n }\n\n async addGroupingPolicy(\n policy: string[],\n roleMetadata: RoleMetadataDao,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const addGroupingPolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n const entityRef = roleMetadata.roleEntityRef;\n\n if (await this.hasGroupingPolicy(...policy)) {\n return;\n }\n try {\n let currentMetadata;\n if (entityRef.startsWith(`role:`)) {\n currentMetadata = await this.roleMetadataStorage.findRoleMetadata(\n entityRef,\n trx,\n );\n }\n\n if (currentMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentMetadata, roleMetadata),\n entityRef,\n trx,\n );\n } else {\n const currentDate: Date = new Date();\n roleMetadata.createdAt = currentDate.toUTCString();\n roleMetadata.lastModified = currentDate.toUTCString();\n await this.roleMetadataStorage.createRoleMetadata(roleMetadata, trx);\n }\n\n const ok = await this.enforcer.addGroupingPolicy(...policy);\n if (!ok) {\n throw new Error(`failed to create policy ${policyToString(policy)}`);\n }\n if (!externalTrx) {\n await trx.commit();\n }\n if (!currentMetadata) {\n this.roleEventEmitter.emit('roleAdded', roleMetadata.roleEntityRef);\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(addGroupingPolicyOperation);\n }\n\n async addGroupingPolicies(\n policies: string[][],\n roleMetadata: RoleMetadataDao,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const addGroupingPoliciesOperation = (async () => {\n if (policies.length === 0) {\n return;\n }\n\n const trx = externalTrx ?? (await this.knex.transaction());\n\n try {\n const currentRoleMetadata =\n await this.roleMetadataStorage.findRoleMetadata(\n roleMetadata.roleEntityRef,\n trx,\n );\n if (currentRoleMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentRoleMetadata, roleMetadata),\n roleMetadata.roleEntityRef,\n trx,\n );\n } else {\n const currentDate: Date = new Date();\n roleMetadata.createdAt = currentDate.toUTCString();\n roleMetadata.lastModified = currentDate.toUTCString();\n await this.roleMetadataStorage.createRoleMetadata(roleMetadata, trx);\n }\n\n const ok = await this.enforcer.addGroupingPolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to store policies ${policiesToString(policies)}`,\n );\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n if (!currentRoleMetadata) {\n this.roleEventEmitter.emit('roleAdded', roleMetadata.roleEntityRef);\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(addGroupingPoliciesOperation);\n }\n\n async updateGroupingPolicies(\n oldRole: string[][],\n newRole: string[][],\n newRoleMetadata: RoleMetadataDao,\n ): Promise<void> {\n const oldRoleName = oldRole.at(0)?.at(1)!;\n\n const trx = await this.knex.transaction();\n try {\n const currentMetadata = await this.roleMetadataStorage.findRoleMetadata(\n oldRoleName,\n trx,\n );\n if (!currentMetadata) {\n throw new Error(`Role metadata ${oldRoleName} was not found`);\n }\n\n await this.removeGroupingPolicies(oldRole, currentMetadata, true, trx);\n await this.addGroupingPolicies(newRole, newRoleMetadata, trx);\n await trx.commit();\n } catch (err) {\n await trx.rollback(err);\n throw err;\n }\n }\n\n async updatePolicies(\n oldPolicies: string[][],\n newPolicies: string[][],\n ): Promise<void> {\n const trx = await this.knex.transaction();\n\n try {\n await this.removePolicies(oldPolicies, trx);\n await this.addPolicies(newPolicies, trx);\n await trx.commit();\n } catch (err) {\n await trx.rollback(err);\n throw err;\n }\n }\n\n async removePolicy(policy: string[], externalTrx?: Knex.Transaction) {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const removePolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n\n try {\n const ok = await this.enforcer.removePolicy(...policy);\n if (!ok) {\n throw new Error(`fail to delete policy ${policy}`);\n }\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removePolicyOperation);\n }\n\n async removePolicies(\n policies: string[][],\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const removePoliciesOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n\n try {\n const ok = await this.enforcer.removePolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to delete policies ${policiesToString(policies)}`,\n );\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removePoliciesOperation);\n }\n\n async removeGroupingPolicy(\n policy: string[],\n roleMetadata: RoleMetadataDao,\n isUpdate?: boolean,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const removeGroupingPolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n const roleEntity = policy[1];\n\n try {\n const ok = await this.enforcer.removeGroupingPolicy(...policy);\n if (!ok) {\n throw new Error(`Failed to delete policy ${policyToString(policy)}`);\n }\n\n if (!isUpdate) {\n const currentRoleMetadata =\n await this.roleMetadataStorage.findRoleMetadata(roleEntity, trx);\n const remainingGroupPolicies = await this.getFilteredGroupingPolicy(\n 1,\n roleEntity,\n );\n if (\n currentRoleMetadata &&\n remainingGroupPolicies.length === 0 &&\n roleEntity !== ADMIN_ROLE_NAME\n ) {\n await this.roleMetadataStorage.removeRoleMetadata(roleEntity, trx);\n } else if (currentRoleMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentRoleMetadata, roleMetadata),\n roleEntity,\n trx,\n );\n }\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removeGroupingPolicyOperation);\n }\n\n async removeGroupingPolicies(\n policies: string[][],\n roleMetadata: RoleMetadataDao,\n isUpdate?: boolean,\n externalTrx?: Knex.Transaction,\n ): Promise<void> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const removeGroupingPolicyOperation = (async () => {\n const trx = externalTrx ?? (await this.knex.transaction());\n const roleEntity = roleMetadata.roleEntityRef;\n\n try {\n const ok = await this.enforcer.removeGroupingPolicies(policies);\n if (!ok) {\n throw new Error(\n `Failed to delete grouping policies: ${policiesToString(policies)}`,\n );\n }\n\n if (!isUpdate) {\n const currentRoleMetadata =\n await this.roleMetadataStorage.findRoleMetadata(roleEntity, trx);\n const remainingGroupPolicies = await this.getFilteredGroupingPolicy(\n 1,\n roleEntity,\n );\n\n if (\n currentRoleMetadata &&\n remainingGroupPolicies.length === 0 &&\n roleEntity !== ADMIN_ROLE_NAME\n ) {\n await this.roleMetadataStorage.removeRoleMetadata(roleEntity, trx);\n } else if (currentRoleMetadata) {\n await this.roleMetadataStorage.updateRoleMetadata(\n mergeRoleMetadata(currentRoleMetadata, roleMetadata),\n roleEntity,\n trx,\n );\n }\n }\n\n if (!externalTrx) {\n await trx.commit();\n }\n } catch (err) {\n if (!externalTrx) {\n await trx.rollback(err);\n }\n throw err;\n }\n })();\n await this.execOperation(removeGroupingPolicyOperation);\n }\n\n /**\n * enforce aims to enforce a particular permission policy based on the user that it receives.\n * Under the hood, enforce uses the `enforce` method from the enforcer`.\n *\n * Before enforcement, a filter is set up to reduce the number of permission policies that will\n * be loaded in.\n * This will reduce the amount of checks that need to be made to determine if a user is authorize\n * to perform an action\n *\n * A temporary enforcer will also be used while enforcing.\n * This is to ensure that the filter does not interact with the base enforcer.\n * The temporary enforcer has lazy loading of the permission policies enabled to reduce the amount\n * of time it takes to initialize the temporary enforcer.\n * The justification for lazy loading is because permission policies are already present in the\n * role manager / database and it will be filtered and loaded whenever `getFilteredPolicy` is called\n * and permissions / roles are applied to the temp enforcer\n * @param entityRef The user to enforce\n * @param resourceType The resource type / name of the permission policy\n * @param action The action of the permission policy\n * @param roles Any roles that the user is directly or indirectly attached to.\n * Used for filtering permission policies.\n * @returns True if the user is allowed based on the particular permission\n */\n async enforce(\n entityRef: string,\n resourceType: string,\n action: string,\n roles: string[],\n ): Promise<boolean> {\n const model = newModelFromString(MODEL);\n let policies: string[][] = [];\n if (roles.length > 0) {\n for (const role of roles) {\n const filteredPolicy = await this.getFilteredPolicy(\n 0,\n role,\n resourceType,\n action,\n );\n policies.push(...filteredPolicy);\n }\n } else {\n const enforcePolicies = await this.getFilteredPolicy(\n 1,\n resourceType,\n action,\n );\n policies = enforcePolicies.filter(\n policy =>\n policy[0].startsWith('user:') || policy[0].startsWith('group:'),\n );\n }\n\n const roleManager = this.enforcer.getRoleManager();\n const tempEnforcer = new Enforcer();\n\n model.addPolicies('p', 'p', policies);\n\n await tempEnforcer.initWithModelAndAdapter(model);\n tempEnforcer.setRoleManager(roleManager);\n await tempEnforcer.buildRoleLinks();\n\n return await tempEnforcer.enforce(entityRef, resourceType, action);\n }\n\n async getImplicitPermissionsForUser(user: string): Promise<string[][]> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const getPermissionsForUserOperation = (async () => {\n return this.enforcer.getImplicitPermissionsForUser(user);\n })();\n\n return await this.execOperation(getPermissionsForUserOperation);\n }\n\n async getAllRoles(): Promise<string[]> {\n if (this.loadPolicyPromise) {\n await this.loadPolicyPromise;\n } else {\n await this.loadPolicy();\n }\n\n const getRolesOperation = (async () => {\n return this.enforcer.getAllRoles();\n })();\n\n return await this.execOperation(getRolesOperation);\n }\n}\n"],"names":["EventEmitter","PoliciesData","FETCH_NEWER_PERMISSIONS_STAGE","newModelFromString","MODEL","policyToString","policiesToString","mergeRoleMetadata","ADMIN_ROLE_NAME","Enforcer"],"mappings":"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"}
|
|
@@ -34,7 +34,7 @@ class PluginPermissionMetadataCollector {
|
|
|
34
34
|
}
|
|
35
35
|
async getPluginPolicies(auth) {
|
|
36
36
|
const pluginMetadata = await this.getPluginMetaData(auth);
|
|
37
|
-
return pluginMetadata.filter((metadata) => metadata.metaDataResponse.permissions !==
|
|
37
|
+
return pluginMetadata.filter((metadata) => metadata.metaDataResponse.permissions !== undefined).map((metadata) => {
|
|
38
38
|
return {
|
|
39
39
|
pluginId: metadata.pluginId,
|
|
40
40
|
policies: permissionsToCasbinPolicies(
|
|
@@ -89,7 +89,7 @@ class PluginPermissionMetadataCollector {
|
|
|
89
89
|
this.logger.warn(
|
|
90
90
|
`No permission metadata found for ${pluginId}. ${err}`
|
|
91
91
|
);
|
|
92
|
-
return
|
|
92
|
+
return undefined;
|
|
93
93
|
}
|
|
94
94
|
this.logger.error(
|
|
95
95
|
`Failed to retrieve permission metadata for ${pluginId}. ${err}`
|