@backstage-community/plugin-rbac-backend 7.2.0 → 7.4.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/README.md +14 -0
- package/config.d.ts +8 -0
- package/dist/policies/permission-policy.cjs.js +28 -13
- package/dist/policies/permission-policy.cjs.js.map +1 -1
- package/package.json +12 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
### Dependencies
|
|
2
2
|
|
|
3
|
+
## 7.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 232a84d: Backstage version bump to v1.42.5
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [232a84d]
|
|
12
|
+
- @backstage-community/plugin-rbac-common@1.20.0
|
|
13
|
+
- @backstage-community/plugin-rbac-node@1.14.0
|
|
14
|
+
|
|
15
|
+
## 7.3.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- 5260b5c: support config to set permission vs conditional policy evaluation order
|
|
20
|
+
|
|
3
21
|
## 7.2.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -279,3 +279,17 @@ More information about group hierarchy can be found in the doc: [Group hierarchy
|
|
|
279
279
|
### Optional RBAC provider module support
|
|
280
280
|
|
|
281
281
|
We also include the ability to create and load in RBAC backend plugin modules that can be used to make connections to third part access management tools. For more information, consult the [RBAC Providers documentation](./docs/providers.md).
|
|
282
|
+
|
|
283
|
+
### Optional configuration to control policy decision precedence
|
|
284
|
+
|
|
285
|
+
Controls the evaluation order between permission policies (basic) and conditional policies for resource permissions.
|
|
286
|
+
|
|
287
|
+
- Default: `conditional` (conditional policies take precedence when present)
|
|
288
|
+
- Set to `basic` to evaluate basic permission policy first
|
|
289
|
+
|
|
290
|
+
```YAML
|
|
291
|
+
permission:
|
|
292
|
+
enabled: true
|
|
293
|
+
rbac:
|
|
294
|
+
policyDecisionPrecedence: basic # or conditional
|
|
295
|
+
```
|
package/config.d.ts
CHANGED
|
@@ -63,6 +63,14 @@ export interface Config {
|
|
|
63
63
|
* @visibility frontend
|
|
64
64
|
*/
|
|
65
65
|
maxDepth?: number;
|
|
66
|
+
/**
|
|
67
|
+
* An optional value that controls evaluation order between basic permission policy and conditional policy for permissions.
|
|
68
|
+
* - Default: "conditional"
|
|
69
|
+
* - "basic": prefer permission policy first
|
|
70
|
+
* - "conditional": prefer conditional policies first
|
|
71
|
+
* @visibility frontend
|
|
72
|
+
*/
|
|
73
|
+
policyDecisionPrecedence?: 'basic' | 'conditional';
|
|
66
74
|
};
|
|
67
75
|
};
|
|
68
76
|
}
|
|
@@ -9,13 +9,15 @@ var csvFileWatcher = require('../file-permissions/csv-file-watcher.cjs.js');
|
|
|
9
9
|
var yamlConditionalFileWatcher = require('../file-permissions/yaml-conditional-file-watcher.cjs.js');
|
|
10
10
|
|
|
11
11
|
class RBACPermissionPolicy {
|
|
12
|
-
constructor(enforcer, auditor, conditionStorage, superUserList) {
|
|
12
|
+
constructor(enforcer, auditor, conditionStorage, preferPermissionPolicy, superUserList) {
|
|
13
13
|
this.enforcer = enforcer;
|
|
14
14
|
this.auditor = auditor;
|
|
15
15
|
this.conditionStorage = conditionStorage;
|
|
16
16
|
this.superUserList = superUserList;
|
|
17
|
+
this.preferPermissionPolicy = preferPermissionPolicy;
|
|
17
18
|
}
|
|
18
19
|
superUserList;
|
|
20
|
+
preferPermissionPolicy;
|
|
19
21
|
static async build(logger, auditor, configApi, conditionalStorage, enforcerDelegate, roleMetadataStorage, knex, pluginMetadataCollector, auth) {
|
|
20
22
|
const superUserList = [];
|
|
21
23
|
const adminUsers = configApi.getOptionalConfigArray(
|
|
@@ -31,6 +33,9 @@ class RBACPermissionPolicy {
|
|
|
31
33
|
const conditionalPoliciesFile = configApi.getOptionalString(
|
|
32
34
|
"permission.rbac.conditionalPoliciesFile"
|
|
33
35
|
);
|
|
36
|
+
const preferPermissionPolicy = (configApi.getOptionalString(
|
|
37
|
+
"permission.rbac.policyDecisionPrecedence"
|
|
38
|
+
) ?? "conditional") === "basic";
|
|
34
39
|
if (superUsers && superUsers.length > 0) {
|
|
35
40
|
for (const user of superUsers) {
|
|
36
41
|
const userName = user.getString("name");
|
|
@@ -83,6 +88,7 @@ class RBACPermissionPolicy {
|
|
|
83
88
|
enforcerDelegate,
|
|
84
89
|
auditor,
|
|
85
90
|
conditionalStorage,
|
|
91
|
+
preferPermissionPolicy,
|
|
86
92
|
superUserList
|
|
87
93
|
);
|
|
88
94
|
}
|
|
@@ -110,7 +116,7 @@ class RBACPermissionPolicy {
|
|
|
110
116
|
}
|
|
111
117
|
const permissionName = request.permission.name;
|
|
112
118
|
const roles = await this.enforcer.getRolesForUser(userEntityRef);
|
|
113
|
-
const hasNamedPermission = await this.
|
|
119
|
+
const hasNamedPermission = await this.hasImplicitPermission(
|
|
114
120
|
permissionName,
|
|
115
121
|
action,
|
|
116
122
|
roles
|
|
@@ -125,20 +131,29 @@ class RBACPermissionPolicy {
|
|
|
125
131
|
}
|
|
126
132
|
if (pluginPermissionCommon.isResourcePermission(request.permission)) {
|
|
127
133
|
const resourceType = request.permission.resourceType;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
const obj = hasNamedPermission ? permissionName : resourceType;
|
|
135
|
+
const conditionResult = await this.handleConditions(
|
|
136
|
+
auditorEvent,
|
|
137
|
+
userEntityRef,
|
|
138
|
+
request,
|
|
139
|
+
roles,
|
|
140
|
+
user.info
|
|
141
|
+
);
|
|
142
|
+
if (this.preferPermissionPolicy) {
|
|
143
|
+
const hasResourcedPermission = await this.hasImplicitPermission(
|
|
144
|
+
resourceType,
|
|
145
|
+
action,
|
|
146
|
+
roles
|
|
135
147
|
);
|
|
136
|
-
if (
|
|
148
|
+
if (hasNamedPermission || hasResourcedPermission) {
|
|
149
|
+
status = await this.isAuthorized(userEntityRef, obj, action, roles);
|
|
150
|
+
} else if (conditionResult) {
|
|
137
151
|
return conditionResult;
|
|
138
152
|
}
|
|
153
|
+
} else {
|
|
154
|
+
if (conditionResult) return conditionResult;
|
|
155
|
+
status = await this.isAuthorized(userEntityRef, obj, action, roles);
|
|
139
156
|
}
|
|
140
|
-
const obj = hasNamedPermission ? permissionName : resourceType;
|
|
141
|
-
status = await this.isAuthorized(userEntityRef, obj, action, roles);
|
|
142
157
|
} else {
|
|
143
158
|
status = await this.isAuthorized(
|
|
144
159
|
userEntityRef,
|
|
@@ -158,7 +173,7 @@ class RBACPermissionPolicy {
|
|
|
158
173
|
return { result: pluginPermissionCommon.AuthorizeResult.DENY };
|
|
159
174
|
}
|
|
160
175
|
}
|
|
161
|
-
async
|
|
176
|
+
async hasImplicitPermission(permissionName, action, roles) {
|
|
162
177
|
for (const role of roles) {
|
|
163
178
|
const perms = await this.enforcer.getFilteredPolicy(
|
|
164
179
|
0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-policy.cjs.js","sources":["../../src/policies/permission-policy.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type {\n AuditorService,\n AuditorServiceEvent,\n AuthService,\n BackstageUserInfo,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { ConfigApi } from '@backstage/core-plugin-api';\nimport {\n AuthorizeResult,\n ConditionalPolicyDecision,\n isResourcePermission,\n PermissionCondition,\n PermissionCriteria,\n PermissionRuleParams,\n PolicyDecision,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\nimport type {\n PermissionPolicy,\n PolicyQuery,\n PolicyQueryUser,\n} from '@backstage/plugin-permission-node';\n\nimport type { Knex } from 'knex';\n\nimport {\n NonEmptyArray,\n toPermissionAction,\n} from '@backstage-community/plugin-rbac-common';\n\nimport {\n setAdminPermissions,\n useAdminsFromConfig,\n} from '../admin-permissions/admin-creation';\nimport { createPermissionEvaluationAuditorEvent } from '../auditor/auditor';\nimport { replaceAliases } from '../conditional-aliases/alias-resolver';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport { RoleMetadataStorage } from '../database/role-metadata';\nimport { CSVFileWatcher } from '../file-permissions/csv-file-watcher';\nimport { YamlConditinalPoliciesFileWatcher } from '../file-permissions/yaml-conditional-file-watcher';\nimport { EnforcerDelegate } from '../service/enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from '../service/plugin-endpoints';\n\nexport class RBACPermissionPolicy implements PermissionPolicy {\n private readonly superUserList?: string[];\n\n public static async build(\n logger: LoggerService,\n auditor: AuditorService,\n configApi: ConfigApi,\n conditionalStorage: ConditionalStorage,\n enforcerDelegate: EnforcerDelegate,\n roleMetadataStorage: RoleMetadataStorage,\n knex: Knex,\n pluginMetadataCollector: PluginPermissionMetadataCollector,\n auth: AuthService,\n ): Promise<RBACPermissionPolicy> {\n const superUserList: string[] = [];\n const adminUsers = configApi.getOptionalConfigArray(\n 'permission.rbac.admin.users',\n );\n\n const superUsers = configApi.getOptionalConfigArray(\n 'permission.rbac.admin.superUsers',\n );\n\n const policiesFile = configApi.getOptionalString(\n 'permission.rbac.policies-csv-file',\n );\n\n const allowReload =\n configApi.getOptionalBoolean('permission.rbac.policyFileReload') || false;\n\n const conditionalPoliciesFile = configApi.getOptionalString(\n 'permission.rbac.conditionalPoliciesFile',\n );\n\n if (superUsers && superUsers.length > 0) {\n for (const user of superUsers) {\n const userName = user.getString('name');\n superUserList.push(userName);\n }\n }\n\n await useAdminsFromConfig(\n adminUsers || [],\n enforcerDelegate,\n auditor,\n roleMetadataStorage,\n knex,\n );\n await setAdminPermissions(enforcerDelegate, auditor);\n\n if (\n (!adminUsers || adminUsers.length === 0) &&\n (!superUsers || superUsers.length === 0)\n ) {\n logger.warn(\n 'There are no admins or super admins configured for the RBAC-backend plugin.',\n );\n }\n\n const csvFile = new CSVFileWatcher(\n policiesFile,\n allowReload,\n logger,\n enforcerDelegate,\n roleMetadataStorage,\n auditor,\n );\n await csvFile.initialize();\n\n const conditionalFile = new YamlConditinalPoliciesFileWatcher(\n conditionalPoliciesFile,\n allowReload,\n logger,\n conditionalStorage,\n auditor,\n auth,\n pluginMetadataCollector,\n roleMetadataStorage,\n enforcerDelegate,\n );\n await conditionalFile.initialize();\n\n if (!conditionalPoliciesFile) {\n // clean up conditional policies corresponding to roles from csv file\n logger.info('conditional policies file feature was disabled');\n await conditionalFile.cleanUpConditionalPolicies();\n }\n if (!policiesFile) {\n // remove roles and policies from csv file\n logger.info('csv policies file feature was disabled');\n await csvFile.cleanUpRolesAndPolicies();\n }\n\n return new RBACPermissionPolicy(\n enforcerDelegate,\n auditor,\n conditionalStorage,\n superUserList,\n );\n }\n\n private constructor(\n private readonly enforcer: EnforcerDelegate,\n private readonly auditor: AuditorService,\n private readonly conditionStorage: ConditionalStorage,\n superUserList?: string[],\n ) {\n this.superUserList = superUserList;\n }\n\n async handle(\n request: PolicyQuery,\n user?: PolicyQueryUser,\n ): Promise<PolicyDecision> {\n const userEntityRef = user?.info.userEntityRef ?? `user without entity`;\n\n const auditorEvent = await createPermissionEvaluationAuditorEvent(\n this.auditor,\n userEntityRef,\n request,\n );\n\n try {\n let status = false;\n const action = toPermissionAction(request.permission.attributes);\n\n if (!user) {\n await auditorEvent.success({\n meta: { result: AuthorizeResult.DENY },\n });\n return { result: AuthorizeResult.DENY };\n }\n\n if (this.superUserList!.includes(userEntityRef)) {\n await auditorEvent.success({\n meta: { result: AuthorizeResult.ALLOW },\n });\n return { result: AuthorizeResult.ALLOW };\n }\n\n const permissionName = request.permission.name;\n const roles = await this.enforcer.getRolesForUser(userEntityRef);\n // handle permission with 'resource' type\n const hasNamedPermission =\n await this.hasImplicitPermissionSpecifiedByName(\n permissionName,\n action,\n roles,\n );\n\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n if (\n request.permission.name === 'policy.entity.create' &&\n !hasNamedPermission\n ) {\n request.permission = {\n attributes: { action: 'create' },\n type: 'resource',\n resourceType: 'policy-entity',\n name: 'policy.entity.create',\n };\n }\n\n if (isResourcePermission(request.permission)) {\n const resourceType = request.permission.resourceType;\n\n // handle conditions if they are present\n if (user) {\n const conditionResult = await this.handleConditions(\n auditorEvent,\n userEntityRef,\n request,\n roles,\n user.info,\n );\n if (conditionResult) {\n return conditionResult;\n }\n }\n\n // Let's set up higher priority for permission specified by name, than by resource type\n const obj = hasNamedPermission ? permissionName : resourceType;\n\n status = await this.isAuthorized(userEntityRef, obj, action, roles);\n } else {\n // handle permission with 'basic' type\n status = await this.isAuthorized(\n userEntityRef,\n permissionName,\n action,\n roles,\n );\n }\n\n const result = status ? AuthorizeResult.ALLOW : AuthorizeResult.DENY;\n\n await auditorEvent.success({ meta: { result } });\n return { result };\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: { result: AuthorizeResult.DENY },\n });\n return { result: AuthorizeResult.DENY };\n }\n }\n\n private async hasImplicitPermissionSpecifiedByName(\n permissionName: string,\n action: string,\n roles: string[],\n ): Promise<boolean> {\n for (const role of roles) {\n const perms = await this.enforcer.getFilteredPolicy(\n 0,\n role,\n permissionName,\n action,\n );\n if (perms.length > 0) {\n return true;\n }\n }\n\n return false;\n }\n\n private isAuthorized = async (\n userIdentity: string,\n permission: string,\n action: string,\n roles: string[],\n ): Promise<boolean> => {\n return await this.enforcer.enforce(userIdentity, permission, action, roles);\n };\n\n private async handleConditions(\n auditorEvent: AuditorServiceEvent,\n userEntityRef: string,\n request: PolicyQuery,\n roles: string[],\n userInfo: BackstageUserInfo,\n ): Promise<PolicyDecision | undefined> {\n const permissionName = request.permission.name;\n const resourceType = (request.permission as ResourcePermission)\n .resourceType;\n const action = toPermissionAction(request.permission.attributes);\n\n const conditions: PermissionCriteria<\n PermissionCondition<string, PermissionRuleParams>\n >[] = [];\n let pluginId = '';\n for (const role of roles) {\n const conditionalDecisions = await this.conditionStorage.filterConditions(\n role,\n undefined,\n resourceType,\n [action],\n [permissionName],\n );\n\n if (conditionalDecisions.length === 1) {\n pluginId = conditionalDecisions[0].pluginId;\n conditions.push(conditionalDecisions[0].conditions);\n }\n\n // this error is unexpected and should not happen, but just in case handle it.\n if (conditionalDecisions.length > 1) {\n await auditorEvent.fail({\n error: new Error(\n `Detected ${JSON.stringify(\n conditionalDecisions,\n )} collisions for conditional policies. Expected to find a stored single condition for permission with name ${permissionName}, resource type ${resourceType}, action ${action} for user ${userEntityRef}`,\n ),\n meta: { result: AuthorizeResult.DENY },\n });\n return {\n result: AuthorizeResult.DENY,\n };\n }\n }\n\n if (conditions.length > 0) {\n const result: ConditionalPolicyDecision = {\n pluginId,\n result: AuthorizeResult.CONDITIONAL,\n resourceType,\n conditions: {\n anyOf: conditions as NonEmptyArray<\n PermissionCriteria<\n PermissionCondition<string, PermissionRuleParams>\n >\n >,\n },\n };\n\n replaceAliases(result.conditions, userInfo);\n\n await auditorEvent.success({ meta: { ...result } });\n return result;\n }\n return undefined;\n }\n}\n"],"names":["useAdminsFromConfig","setAdminPermissions","CSVFileWatcher","YamlConditinalPoliciesFileWatcher","createPermissionEvaluationAuditorEvent","toPermissionAction","AuthorizeResult","isResourcePermission","replaceAliases"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permission-policy.cjs.js","sources":["../../src/policies/permission-policy.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type {\n AuditorService,\n AuditorServiceEvent,\n AuthService,\n BackstageUserInfo,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { ConfigApi } from '@backstage/core-plugin-api';\nimport {\n AuthorizeResult,\n ConditionalPolicyDecision,\n isResourcePermission,\n PermissionCondition,\n PermissionCriteria,\n PermissionRuleParams,\n PolicyDecision,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\nimport type {\n PermissionPolicy,\n PolicyQuery,\n PolicyQueryUser,\n} from '@backstage/plugin-permission-node';\n\nimport type { Knex } from 'knex';\n\nimport {\n NonEmptyArray,\n toPermissionAction,\n} from '@backstage-community/plugin-rbac-common';\n\nimport {\n setAdminPermissions,\n useAdminsFromConfig,\n} from '../admin-permissions/admin-creation';\nimport { createPermissionEvaluationAuditorEvent } from '../auditor/auditor';\nimport { replaceAliases } from '../conditional-aliases/alias-resolver';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport { RoleMetadataStorage } from '../database/role-metadata';\nimport { CSVFileWatcher } from '../file-permissions/csv-file-watcher';\nimport { YamlConditinalPoliciesFileWatcher } from '../file-permissions/yaml-conditional-file-watcher';\nimport { EnforcerDelegate } from '../service/enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from '../service/plugin-endpoints';\n\nexport class RBACPermissionPolicy implements PermissionPolicy {\n private readonly superUserList?: string[];\n private readonly preferPermissionPolicy: boolean;\n\n public static async build(\n logger: LoggerService,\n auditor: AuditorService,\n configApi: ConfigApi,\n conditionalStorage: ConditionalStorage,\n enforcerDelegate: EnforcerDelegate,\n roleMetadataStorage: RoleMetadataStorage,\n knex: Knex,\n pluginMetadataCollector: PluginPermissionMetadataCollector,\n auth: AuthService,\n ): Promise<RBACPermissionPolicy> {\n const superUserList: string[] = [];\n const adminUsers = configApi.getOptionalConfigArray(\n 'permission.rbac.admin.users',\n );\n\n const superUsers = configApi.getOptionalConfigArray(\n 'permission.rbac.admin.superUsers',\n );\n\n const policiesFile = configApi.getOptionalString(\n 'permission.rbac.policies-csv-file',\n );\n\n const allowReload =\n configApi.getOptionalBoolean('permission.rbac.policyFileReload') || false;\n\n const conditionalPoliciesFile = configApi.getOptionalString(\n 'permission.rbac.conditionalPoliciesFile',\n );\n\n const preferPermissionPolicy =\n (configApi.getOptionalString(\n 'permission.rbac.policyDecisionPrecedence',\n ) ?? 'conditional') === 'basic';\n\n if (superUsers && superUsers.length > 0) {\n for (const user of superUsers) {\n const userName = user.getString('name');\n superUserList.push(userName);\n }\n }\n\n await useAdminsFromConfig(\n adminUsers || [],\n enforcerDelegate,\n auditor,\n roleMetadataStorage,\n knex,\n );\n await setAdminPermissions(enforcerDelegate, auditor);\n\n if (\n (!adminUsers || adminUsers.length === 0) &&\n (!superUsers || superUsers.length === 0)\n ) {\n logger.warn(\n 'There are no admins or super admins configured for the RBAC-backend plugin.',\n );\n }\n\n const csvFile = new CSVFileWatcher(\n policiesFile,\n allowReload,\n logger,\n enforcerDelegate,\n roleMetadataStorage,\n auditor,\n );\n await csvFile.initialize();\n\n const conditionalFile = new YamlConditinalPoliciesFileWatcher(\n conditionalPoliciesFile,\n allowReload,\n logger,\n conditionalStorage,\n auditor,\n auth,\n pluginMetadataCollector,\n roleMetadataStorage,\n enforcerDelegate,\n );\n await conditionalFile.initialize();\n\n if (!conditionalPoliciesFile) {\n // clean up conditional policies corresponding to roles from csv file\n logger.info('conditional policies file feature was disabled');\n await conditionalFile.cleanUpConditionalPolicies();\n }\n if (!policiesFile) {\n // remove roles and policies from csv file\n logger.info('csv policies file feature was disabled');\n await csvFile.cleanUpRolesAndPolicies();\n }\n\n return new RBACPermissionPolicy(\n enforcerDelegate,\n auditor,\n conditionalStorage,\n preferPermissionPolicy,\n superUserList,\n );\n }\n\n private constructor(\n private readonly enforcer: EnforcerDelegate,\n private readonly auditor: AuditorService,\n private readonly conditionStorage: ConditionalStorage,\n preferPermissionPolicy: boolean,\n superUserList?: string[],\n ) {\n this.superUserList = superUserList;\n this.preferPermissionPolicy = preferPermissionPolicy;\n }\n\n async handle(\n request: PolicyQuery,\n user?: PolicyQueryUser,\n ): Promise<PolicyDecision> {\n const userEntityRef = user?.info.userEntityRef ?? `user without entity`;\n\n const auditorEvent = await createPermissionEvaluationAuditorEvent(\n this.auditor,\n userEntityRef,\n request,\n );\n\n try {\n let status = false;\n const action = toPermissionAction(request.permission.attributes);\n\n if (!user) {\n await auditorEvent.success({\n meta: { result: AuthorizeResult.DENY },\n });\n return { result: AuthorizeResult.DENY };\n }\n\n if (this.superUserList!.includes(userEntityRef)) {\n await auditorEvent.success({\n meta: { result: AuthorizeResult.ALLOW },\n });\n return { result: AuthorizeResult.ALLOW };\n }\n\n const permissionName = request.permission.name;\n const roles = await this.enforcer.getRolesForUser(userEntityRef);\n // handle permission with 'resource' type\n const hasNamedPermission = await this.hasImplicitPermission(\n permissionName,\n action,\n roles,\n );\n\n // TODO: Temporary workaround to prevent breakages after the removal of the resource type `policy-entity` from the permission `policy.entity.create`\n if (\n request.permission.name === 'policy.entity.create' &&\n !hasNamedPermission\n ) {\n request.permission = {\n attributes: { action: 'create' },\n type: 'resource',\n resourceType: 'policy-entity',\n name: 'policy.entity.create',\n };\n }\n\n if (isResourcePermission(request.permission)) {\n const resourceType = request.permission.resourceType;\n // Let's set up higher priority for permission specified by name, than by resource type\n const obj = hasNamedPermission ? permissionName : resourceType;\n // handle conditions if they are present\n const conditionResult = await this.handleConditions(\n auditorEvent,\n userEntityRef,\n request,\n roles,\n user.info,\n );\n\n if (this.preferPermissionPolicy) {\n const hasResourcedPermission = await this.hasImplicitPermission(\n resourceType,\n action,\n roles,\n );\n // Permission policy first\n if (hasNamedPermission || hasResourcedPermission) {\n status = await this.isAuthorized(userEntityRef, obj, action, roles);\n } else if (conditionResult) {\n return conditionResult;\n }\n } else {\n if (conditionResult) return conditionResult;\n status = await this.isAuthorized(userEntityRef, obj, action, roles);\n }\n } else {\n // handle permission with 'basic' type\n status = await this.isAuthorized(\n userEntityRef,\n permissionName,\n action,\n roles,\n );\n }\n\n const result = status ? AuthorizeResult.ALLOW : AuthorizeResult.DENY;\n\n await auditorEvent.success({ meta: { result } });\n return { result };\n } catch (error) {\n await auditorEvent.fail({\n error,\n meta: { result: AuthorizeResult.DENY },\n });\n return { result: AuthorizeResult.DENY };\n }\n }\n\n private async hasImplicitPermission(\n permissionName: string,\n action: string,\n roles: string[],\n ): Promise<boolean> {\n for (const role of roles) {\n const perms = await this.enforcer.getFilteredPolicy(\n 0,\n role,\n permissionName,\n action,\n );\n if (perms.length > 0) {\n return true;\n }\n }\n\n return false;\n }\n\n private isAuthorized = async (\n userIdentity: string,\n permission: string,\n action: string,\n roles: string[],\n ): Promise<boolean> => {\n return await this.enforcer.enforce(userIdentity, permission, action, roles);\n };\n\n private async handleConditions(\n auditorEvent: AuditorServiceEvent,\n userEntityRef: string,\n request: PolicyQuery,\n roles: string[],\n userInfo: BackstageUserInfo,\n ): Promise<PolicyDecision | undefined> {\n const permissionName = request.permission.name;\n const resourceType = (request.permission as ResourcePermission)\n .resourceType;\n const action = toPermissionAction(request.permission.attributes);\n\n const conditions: PermissionCriteria<\n PermissionCondition<string, PermissionRuleParams>\n >[] = [];\n let pluginId = '';\n for (const role of roles) {\n const conditionalDecisions = await this.conditionStorage.filterConditions(\n role,\n undefined,\n resourceType,\n [action],\n [permissionName],\n );\n\n if (conditionalDecisions.length === 1) {\n pluginId = conditionalDecisions[0].pluginId;\n conditions.push(conditionalDecisions[0].conditions);\n }\n\n // this error is unexpected and should not happen, but just in case handle it.\n if (conditionalDecisions.length > 1) {\n await auditorEvent.fail({\n error: new Error(\n `Detected ${JSON.stringify(\n conditionalDecisions,\n )} collisions for conditional policies. Expected to find a stored single condition for permission with name ${permissionName}, resource type ${resourceType}, action ${action} for user ${userEntityRef}`,\n ),\n meta: { result: AuthorizeResult.DENY },\n });\n return {\n result: AuthorizeResult.DENY,\n };\n }\n }\n\n if (conditions.length > 0) {\n const result: ConditionalPolicyDecision = {\n pluginId,\n result: AuthorizeResult.CONDITIONAL,\n resourceType,\n conditions: {\n anyOf: conditions as NonEmptyArray<\n PermissionCriteria<\n PermissionCondition<string, PermissionRuleParams>\n >\n >,\n },\n };\n\n replaceAliases(result.conditions, userInfo);\n\n await auditorEvent.success({ meta: { ...result } });\n return result;\n }\n return undefined;\n }\n}\n"],"names":["useAdminsFromConfig","setAdminPermissions","CSVFileWatcher","YamlConditinalPoliciesFileWatcher","createPermissionEvaluationAuditorEvent","toPermissionAction","AuthorizeResult","isResourcePermission","replaceAliases"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-rbac-backend",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"postpack": "backstage-cli package postpack"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@backstage-community/plugin-rbac-common": "^1.
|
|
40
|
-
"@backstage-community/plugin-rbac-node": "^1.
|
|
41
|
-
"@backstage/backend-defaults": "^0.
|
|
42
|
-
"@backstage/backend-plugin-api": "^1.4.
|
|
43
|
-
"@backstage/catalog-client": "^1.
|
|
39
|
+
"@backstage-community/plugin-rbac-common": "^1.20.0",
|
|
40
|
+
"@backstage-community/plugin-rbac-node": "^1.14.0",
|
|
41
|
+
"@backstage/backend-defaults": "^0.12.0",
|
|
42
|
+
"@backstage/backend-plugin-api": "^1.4.2",
|
|
43
|
+
"@backstage/catalog-client": "^1.11.0",
|
|
44
44
|
"@backstage/catalog-model": "^1.7.5",
|
|
45
45
|
"@backstage/errors": "^1.2.7",
|
|
46
|
-
"@backstage/plugin-auth-node": "^0.6.
|
|
47
|
-
"@backstage/plugin-permission-backend": "^0.7.
|
|
46
|
+
"@backstage/plugin-auth-node": "^0.6.6",
|
|
47
|
+
"@backstage/plugin-permission-backend": "^0.7.3",
|
|
48
48
|
"@backstage/plugin-permission-common": "^0.9.1",
|
|
49
|
-
"@backstage/plugin-permission-node": "^0.10.
|
|
49
|
+
"@backstage/plugin-permission-node": "^0.10.3",
|
|
50
50
|
"@dagrejs/graphlib": "^2.1.13",
|
|
51
51
|
"casbin": "^5.27.1",
|
|
52
52
|
"chokidar": "^3.6.0",
|
|
@@ -61,11 +61,11 @@
|
|
|
61
61
|
"zod-to-json-schema": "^3.24.5"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@backstage/backend-test-utils": "^1.
|
|
65
|
-
"@backstage/cli": "^0.
|
|
64
|
+
"@backstage/backend-test-utils": "^1.8.0",
|
|
65
|
+
"@backstage/cli": "^0.34.1",
|
|
66
66
|
"@backstage/config": "^1.3.3",
|
|
67
67
|
"@backstage/core-plugin-api": "^1.10.9",
|
|
68
|
-
"@backstage/plugin-catalog-node": "^1.
|
|
68
|
+
"@backstage/plugin-catalog-node": "^1.18.0",
|
|
69
69
|
"@backstage/types": "^1.2.1",
|
|
70
70
|
"@types/express": "4.17.23",
|
|
71
71
|
"@types/js-yaml": "^4.0.9",
|