@backstage-community/plugin-rbac-backend 5.3.0 → 5.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/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 +18 -6
- 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/role-manager.cjs.js +3 -3
- package/dist/role-manager/role-manager.cjs.js.map +1 -1
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policies-rest-api.cjs.js","sources":["../../src/service/policies-rest-api.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 { PermissionsService } from '@backstage/backend-plugin-api';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n NotFoundError,\n ServiceUnavailableError,\n} from '@backstage/errors';\nimport { createRouter } from '@backstage/plugin-permission-backend';\nimport {\n AuthorizeResult,\n PolicyDecision,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport type { AuditLogger } from '@janus-idp/backstage-plugin-audit-log-node';\nimport express from 'express';\nimport type { Request } from 'express-serve-static-core';\nimport { isEmpty, isEqual } from 'lodash';\nimport type { ParsedQs } from 'qs';\n\nimport {\n PermissionAction,\n policyEntityCreatePermission,\n policyEntityDeletePermission,\n policyEntityPermissions,\n policyEntityReadPermission,\n policyEntityUpdatePermission,\n RESOURCE_TYPE_POLICY_ENTITY,\n Role,\n RoleBasedPolicy,\n RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\nimport type { RBACProvider } from '@backstage-community/plugin-rbac-node';\n\nimport {\n ConditionAuditInfo,\n ConditionEvents,\n ListConditionEvents,\n ListPluginPoliciesEvents,\n PermissionAuditInfo,\n PermissionEvents,\n RoleAuditInfo,\n RoleEvents,\n SEND_RESPONSE_STAGE,\n} from '../audit-log/audit-logger';\nimport { auditError as logAuditError } from '../audit-log/rest-errors-interceptor';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport {\n daoToMetadata,\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport {\n buildRoleSourceMap,\n deepSortedEqual,\n isPermissionAction,\n policyToString,\n processConditionMapping,\n} from '../helper';\nimport { validateRoleCondition } from '../validation/condition-validation';\nimport {\n validateEntityReference,\n validatePolicy,\n validateRole,\n validateSource,\n} from '../validation/policies-validation';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { RBACRouterOptions } from './policy-builder';\n\nexport class PoliciesServer {\n constructor(\n private readonly permissions: PermissionsService,\n private readonly options: RBACRouterOptions,\n private readonly enforcer: EnforcerDelegate,\n private readonly conditionalStorage: ConditionalStorage,\n private readonly pluginPermMetaData: PluginPermissionMetadataCollector,\n private readonly roleMetadata: RoleMetadataStorage,\n private readonly aLog: AuditLogger,\n private readonly rbacProviders?: RBACProvider[],\n ) {}\n\n private async authorize(\n request: Request,\n permission: ResourcePermission,\n ): Promise<PolicyDecision> {\n const credentials = await this.options.httpAuth.credentials(request, {\n allow: ['user', 'service'],\n });\n\n // allow service to service communication, but only with read permission\n if (\n this.options.auth.isPrincipal(credentials, 'service') &&\n permission !== policyEntityReadPermission\n ) {\n throw new NotAllowedError(\n `Only creadential principal with type 'user' permitted to modify permissions`,\n );\n }\n\n const decision = (\n await this.permissions.authorize(\n [{ permission: permission, resourceRef: permission.resourceType }],\n { credentials },\n )\n )[0];\n\n return decision;\n }\n\n async serve(): Promise<express.Router> {\n const router = await createRouter(this.options);\n\n const { httpAuth } = this.options;\n\n if (!httpAuth) {\n throw new ServiceUnavailableError(\n 'httpAuth not found, ensure the correct configuration for the RBAC plugin',\n );\n }\n\n const permissionsIntegrationRouter = createPermissionIntegrationRouter({\n resourceType: RESOURCE_TYPE_POLICY_ENTITY,\n permissions: policyEntityPermissions,\n });\n router.use(permissionsIntegrationRouter);\n\n const isPluginEnabled =\n this.options.config.getOptionalBoolean('permission.enabled');\n if (!isPluginEnabled) {\n return router;\n }\n\n router.get('/', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n response.send({ status: 'Authorized' });\n });\n\n // Policy CRUD\n\n router.get('/policies', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n let policies: string[][];\n if (this.isPolicyFilterEnabled(request)) {\n const entityRef = this.getFirstQuery(request.query.entityRef);\n const permission = this.getFirstQuery(request.query.permission);\n const policy = this.getFirstQuery(request.query.policy);\n const effect = this.getFirstQuery(request.query.effect);\n\n const filter: string[] = [entityRef, permission, policy, effect];\n policies = await this.enforcer.getFilteredPolicy(0, ...filter);\n } else {\n policies = await this.enforcer.getPolicy();\n }\n\n const body = await this.transformPolicyArray(...policies);\n\n await this.aLog.auditLog({\n message: `Return list permission policies`,\n eventName: PermissionEvents.GET_POLICY,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get(\n '/policies/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const entityRef = this.getEntityReference(request);\n\n const policy = await this.enforcer.getFilteredPolicy(0, entityRef);\n if (policy.length !== 0) {\n const body = await this.transformPolicyArray(...policy);\n\n await this.aLog.auditLog({\n message: `Return permission policy`,\n eventName: PermissionEvents.GET_POLICY,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n },\n );\n\n router.delete(\n '/policies/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityDeletePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const entityRef = this.getEntityReference(request);\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n policyRaw.forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedPolicies = await this.processPolicies(policyRaw, true);\n\n await this.enforcer.removePolicies(processedPolicies);\n\n await this.aLog.auditLog<PermissionAuditInfo>({\n message: `Deleted permission policies`,\n eventName: PermissionEvents.DELETE_POLICY,\n metadata: { policies: processedPolicies, source: 'rest' },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 204 },\n });\n\n response.status(204).end();\n },\n );\n\n router.post('/policies', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n const processedPolicies = await this.processPolicies(policyRaw);\n\n const entityRef = processedPolicies[0][0];\n const roleMetadata = await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.addPolicies(processedPolicies);\n\n await this.aLog.auditLog<PermissionAuditInfo>({\n message: `Created permission policies`,\n eventName: PermissionEvents.CREATE_POLICY,\n metadata: { policies: processedPolicies, source: 'rest' },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 201 },\n });\n\n response.status(201).end();\n });\n\n router.put(\n '/policies/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityUpdatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const entityRef = this.getEntityReference(request);\n\n const oldPolicyRaw: RoleBasedPolicy[] = request.body.oldPolicy;\n if (isEmpty(oldPolicyRaw)) {\n throw new InputError(`'oldPolicy' object must be present`); // 400\n }\n const newPolicyRaw: RoleBasedPolicy[] = request.body.newPolicy;\n if (isEmpty(newPolicyRaw)) {\n throw new InputError(`'newPolicy' object must be present`); // 400\n }\n\n [...oldPolicyRaw, ...newPolicyRaw].forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedOldPolicy = await this.processPolicies(\n oldPolicyRaw,\n true,\n 'old policy',\n );\n\n oldPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n newPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n if (\n isEqual(oldPolicyRaw, newPolicyRaw) &&\n !oldPolicyRaw.some(isEmpty)\n ) {\n response.status(204).end();\n } else if (oldPolicyRaw.length > newPolicyRaw.length) {\n throw new InputError(\n `'oldPolicy' object has more permission policies compared to 'newPolicy' object`,\n );\n }\n\n const processedNewPolicy = await this.processPolicies(\n newPolicyRaw,\n false,\n 'new policy',\n );\n\n const roleMetadata =\n await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.updatePolicies(\n processedOldPolicy,\n processedNewPolicy,\n );\n\n await this.aLog.auditLog<PermissionAuditInfo>({\n message: `Updated permission policies`,\n eventName: PermissionEvents.UPDATE_POLICY,\n metadata: { policies: processedNewPolicy, source: 'rest' },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200 },\n });\n\n response.status(200).end();\n },\n );\n\n // Role CRUD\n\n router.get('/roles', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const roles = await this.enforcer.getGroupingPolicy();\n\n const body = await this.transformRoleArray(...roles);\n\n await this.aLog.auditLog({\n message: `Return list roles`,\n eventName: RoleEvents.GET_ROLE,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get('/roles/:kind/:namespace/:name', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n const roleEntityRef = this.getEntityReference(request, true);\n\n const role = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n\n if (role.length !== 0) {\n const body = await this.transformRoleArray(...role);\n\n await this.aLog.auditLog({\n message: `Return ${body[0].name}`,\n eventName: RoleEvents.GET_ROLE,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n });\n\n router.post('/roles', async (request, response) => {\n const uniqueItems = new Set<string>();\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n const roleRaw: Role = request.body;\n let err = validateRole(roleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid role definition. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(roleRaw);\n\n const rMetadata = await this.roleMetadata.findRoleMetadata(roleRaw.name);\n\n err = await validateSource('rest', rMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to add role: ${err.message}`);\n }\n\n const roles = this.transformRoleToArray(roleRaw);\n\n for (const role of roles) {\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n throw new ConflictError(); // 409\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n const modifiedBy = credentials.principal.userEntityRef;\n const metadata: RoleMetadataDao = {\n roleEntityRef: roleRaw.name,\n source: 'rest',\n description: roleRaw.metadata?.description ?? '',\n author: modifiedBy,\n modifiedBy,\n };\n\n await this.enforcer.addGroupingPolicies(roles, metadata);\n\n await this.aLog.auditLog<RoleAuditInfo>({\n message: `Created ${metadata.roleEntityRef}`,\n eventName: RoleEvents.CREATE_ROLE,\n metadata: {\n ...metadata,\n members: roles.map(gp => gp[0]),\n },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 201 },\n });\n\n response.status(201).end();\n });\n\n router.put('/roles/:kind/:namespace/:name', async (request, response) => {\n const uniqueItems = new Set<string>();\n const decision = await this.authorize(\n request,\n policyEntityUpdatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n const roleEntityRef = this.getEntityReference(request, true);\n\n const oldRoleRaw: Role = request.body.oldRole;\n\n if (!oldRoleRaw) {\n throw new InputError(`'oldRole' object must be present`); // 400\n }\n const newRoleRaw: Role = request.body.newRole;\n if (!newRoleRaw) {\n throw new InputError(`'newRole' object must be present`); // 400\n }\n\n oldRoleRaw.name = roleEntityRef;\n let err = validateRole(oldRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid old role object. Cause: ${err.message}`,\n );\n }\n err = validateRole(newRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid new role object. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(oldRoleRaw);\n this.transformMemberReferencesToLowercase(newRoleRaw);\n\n const oldRole = this.transformRoleToArray(oldRoleRaw);\n const newRole = this.transformRoleToArray(newRoleRaw);\n // todo shell we allow newRole with an empty array?...\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n const newMetadata: RoleMetadataDao = {\n ...newRoleRaw.metadata,\n source: newRoleRaw.metadata?.source ?? 'rest',\n roleEntityRef: newRoleRaw.name,\n modifiedBy: credentials.principal.userEntityRef,\n };\n\n const oldMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n if (!oldMetadata) {\n throw new NotFoundError(`Unable to find metadata for ${roleEntityRef}`);\n }\n\n err = await validateSource('rest', oldMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to edit role: ${err.message}`);\n }\n\n if (\n isEqual(oldRole, newRole) &&\n deepSortedEqual(oldMetadata, newMetadata, [\n 'author',\n 'modifiedBy',\n 'createdAt',\n 'lastModified',\n ])\n ) {\n // no content: old role and new role are equal and their metadata too\n response.status(204).end();\n return;\n }\n\n for (const role of newRole) {\n const hasRole = oldRole.some(element => {\n return isEqual(element, role);\n });\n // if the role is already part of old role and is a grouping policy we want to skip returning a conflict error\n // to allow for other roles to be checked and added\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n if (!hasRole) {\n throw new ConflictError(); // 409\n }\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n uniqueItems.clear();\n for (const role of oldRole) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(\n `Member reference: ${role[0]} was not found for role ${roleEntityRef}`,\n ); // 404\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n await this.enforcer.updateGroupingPolicies(oldRole, newRole, newMetadata);\n\n let message = `Updated ${oldMetadata.roleEntityRef}.`;\n if (newMetadata.roleEntityRef !== oldMetadata.roleEntityRef) {\n message = `${message}. Role entity reference renamed to ${newMetadata.roleEntityRef}`;\n }\n await this.aLog.auditLog<RoleAuditInfo>({\n message,\n eventName: RoleEvents.UPDATE_ROLE,\n metadata: {\n ...newMetadata,\n members: newRole.map(gp => gp[0]),\n },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200 },\n });\n\n response.status(200).end();\n });\n\n router.delete(\n '/roles/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityDeletePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n let roleMembers = [];\n if (request.query.memberReferences) {\n const memberReference = this.getFirstQuery(\n request.query.memberReferences!,\n ).toLocaleLowerCase('en-US');\n const gp = await this.enforcer.getFilteredGroupingPolicy(\n 0,\n memberReference,\n roleEntityRef,\n );\n if (gp.length > 0) {\n roleMembers.push(gp[0]);\n } else {\n throw new NotFoundError(\n `role member '${memberReference}' was not found`,\n ); // 404\n }\n } else {\n roleMembers = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n }\n\n for (const role of roleMembers) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(`role member '${role[0]}' was not found`);\n }\n }\n\n const currentMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n const err = await validateSource('rest', currentMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to delete role: ${err.message}`);\n }\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n const metadata: RoleMetadataDao = {\n roleEntityRef,\n source: 'rest',\n modifiedBy: credentials.principal.userEntityRef,\n };\n\n await this.enforcer.removeGroupingPolicies(\n roleMembers,\n metadata,\n false,\n );\n\n await this.aLog.auditLog<RoleAuditInfo>({\n message: `Deleted ${metadata.roleEntityRef}`,\n eventName: RoleEvents.DELETE_ROLE,\n metadata: {\n ...metadata,\n members: roleMembers.map(gp => gp[0]),\n },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 204 },\n });\n\n response.status(204).end();\n },\n );\n\n router.get('/plugins/policies', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const body = await this.pluginPermMetaData.getPluginPolicies(\n this.options.auth,\n );\n\n await this.aLog.auditLog({\n message: `Return list plugin policies`,\n eventName: ListPluginPoliciesEvents.GET_PLUGINS_POLICIES,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get('/plugins/condition-rules', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const body = await this.pluginPermMetaData.getPluginConditionRules(\n this.options.auth,\n );\n\n await this.aLog.auditLog({\n message: `Return list conditional rules and schemas`,\n eventName: ListConditionEvents.GET_CONDITION_RULES,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get('/roles/conditions', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const conditions = await this.conditionalStorage.filterConditions(\n this.getFirstQuery(request.query.roleEntityRef),\n this.getFirstQuery(request.query.pluginId),\n this.getFirstQuery(request.query.resourceType),\n this.getActionQueries(request.query.actions),\n );\n\n const body: RoleConditionalPolicyDecision<PermissionAction>[] =\n conditions.map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n });\n\n await this.aLog.auditLog({\n message: `Return list conditional permission policies`,\n eventName: ConditionEvents.GET_CONDITION,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.post('/roles/conditions', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToCreate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n this.options.auth,\n );\n\n const id =\n await this.conditionalStorage.createCondition(conditionToCreate);\n\n const body = { id: id };\n\n await this.aLog.auditLog<ConditionAuditInfo>({\n message: `Created conditional permission policy`,\n eventName: ConditionEvents.CREATE_CONDITION,\n metadata: { condition: roleConditionPolicy },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 201, body },\n });\n\n response.status(201).json(body);\n });\n\n router.get('/roles/conditions/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError();\n }\n\n const body: RoleConditionalPolicyDecision<PermissionAction> = {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n\n await this.aLog.auditLog({\n message: `Return conditional permission policy by id`,\n eventName: ConditionEvents.GET_CONDITION,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.delete('/roles/conditions/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityDeletePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError(`Condition with id ${id} was not found`);\n }\n const conditionToDelete: RoleConditionalPolicyDecision<PermissionAction> =\n {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n\n await this.conditionalStorage.deleteCondition(id);\n\n await this.aLog.auditLog<ConditionAuditInfo>({\n message: `Deleted conditional permission policy`,\n eventName: ConditionEvents.DELETE_CONDITION,\n metadata: { condition: conditionToDelete },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 204 },\n });\n\n response.status(204).end();\n });\n\n router.put('/roles/conditions/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityUpdatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToUpdate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n this.options.auth,\n );\n\n await this.conditionalStorage.updateCondition(id, conditionToUpdate);\n\n await this.aLog.auditLog<ConditionAuditInfo>({\n message: `Updated conditional permission policy`,\n eventName: ConditionEvents.UPDATE_CONDITION,\n metadata: { condition: roleConditionPolicy },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200 },\n });\n\n response.status(200).end();\n });\n\n router.post('/refresh/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n if (!this.rbacProviders) {\n throw new NotFoundError(`No RBAC providers were found`);\n }\n\n const idProvider = this.rbacProviders.find(provider => {\n const id = provider.getProviderName();\n return id === request.params.id;\n });\n\n if (!idProvider) {\n throw new NotFoundError(\n `The RBAC provider ${request.params.id} was not found`,\n );\n }\n\n await idProvider.refresh();\n response.status(200).end();\n });\n\n router.use(logAuditError(this.aLog));\n\n return router;\n }\n\n getEntityReference(request: Request, role?: boolean): string {\n const kind = request.params.kind;\n const namespace = request.params.namespace;\n const name = request.params.name;\n const entityRef = `${kind}:${namespace}/${name}`;\n\n const err = validateEntityReference(entityRef, role);\n if (err) {\n throw new InputError(err.message);\n }\n\n return entityRef;\n }\n\n async transformPolicyArray(\n ...policies: string[][]\n ): Promise<RoleBasedPolicy[]> {\n const roleToSourceMap = await buildRoleSourceMap(\n policies,\n this.roleMetadata,\n );\n\n const roleBasedPolices: RoleBasedPolicy[] = [];\n for (const p of policies) {\n const [entityReference, permission, policy, effect] = p;\n roleBasedPolices.push({\n entityReference,\n permission,\n policy,\n effect,\n metadata: { source: roleToSourceMap.get(entityReference)! },\n });\n }\n\n return roleBasedPolices;\n }\n\n async transformRoleArray(...roles: string[][]): Promise<Role[]> {\n const combinedRoles: { [key: string]: string[] } = {};\n\n roles.forEach(([value, role]) => {\n if (combinedRoles.hasOwnProperty(role)) {\n combinedRoles[role].push(value);\n } else {\n combinedRoles[role] = [value];\n }\n });\n\n const result: Role[] = await Promise.all(\n Object.entries(combinedRoles).map(async ([role, value]) => {\n const metadataDao = await this.roleMetadata.findRoleMetadata(role);\n const metadata = metadataDao ? daoToMetadata(metadataDao) : undefined;\n return Promise.resolve({\n memberReferences: value,\n name: role,\n metadata,\n });\n }),\n );\n return result;\n }\n\n transformPolicyToArray(policy: RoleBasedPolicy): string[] {\n return [\n policy.entityReference!,\n policy.permission!,\n policy.policy!,\n policy.effect!,\n ];\n }\n\n transformRoleToArray(role: Role): string[][] {\n const roles: string[][] = [];\n for (const entity of role.memberReferences) {\n roles.push([entity, role.name]);\n }\n return roles;\n }\n\n transformMemberReferencesToLowercase(role: Role) {\n role.memberReferences = role.memberReferences.map(member =>\n member.toLocaleLowerCase('en-US'),\n );\n }\n\n getActionQueries(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): PermissionAction[] | undefined {\n if (!queryValue) {\n return undefined;\n }\n if (Array.isArray(queryValue)) {\n const permissionNames: PermissionAction[] = [];\n for (const permissionQuery of queryValue) {\n if (\n typeof permissionQuery === 'string' &&\n isPermissionAction(permissionQuery)\n ) {\n permissionNames.push(permissionQuery);\n } else {\n throw new InputError(\n `Invalid permission action query value: ${permissionQuery}. Permission name should be string.`,\n );\n }\n }\n return permissionNames;\n }\n\n if (typeof queryValue === 'string' && isPermissionAction(queryValue)) {\n return [queryValue];\n }\n throw new InputError(\n `Invalid permission action query value: ${queryValue}. Permission name should be string.`,\n );\n }\n\n getFirstQuery(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): string {\n if (!queryValue) {\n return '';\n }\n if (Array.isArray(queryValue)) {\n if (typeof queryValue[0] === 'string') {\n return queryValue[0].toString();\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n if (typeof queryValue === 'string') {\n return queryValue;\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n isPolicyFilterEnabled(request: Request): boolean {\n return (\n !!request.query.entityRef ||\n !!request.query.permission ||\n !!request.query.policy ||\n !!request.query.effect\n );\n }\n\n async processPolicies(\n policyArray: RoleBasedPolicy[],\n isOld?: boolean,\n errorMessage?: string,\n ): Promise<string[][]> {\n const policies: string[][] = [];\n const uniqueItems = new Set<string>();\n for (const policy of policyArray) {\n let err = validatePolicy(policy);\n if (err) {\n throw new InputError(\n `Invalid ${errorMessage ?? 'policy'} definition. Cause: ${\n err.message\n }`,\n ); // 400\n }\n\n const metadata = await this.roleMetadata.findRoleMetadata(\n policy.entityReference!,\n );\n\n let action = errorMessage ? 'edit' : 'delete';\n action = isOld ? action : 'add';\n\n err = await validateSource('rest', metadata);\n if (err) {\n throw new NotAllowedError(\n `Unable to ${action} policy ${policy.entityReference},${policy.permission},${policy.policy},${policy.effect}: ${err.message}`,\n );\n }\n\n const transformedPolicy = this.transformPolicyToArray(policy);\n if (isOld && !(await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new NotFoundError(\n `Policy '${policyToString(transformedPolicy)}' not found`,\n ); // 404\n }\n\n if (!isOld && (await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new ConflictError(\n `Policy '${policyToString(\n transformedPolicy,\n )}' has been already stored`,\n ); // 409\n }\n\n // We want to ensure that there are not duplicate permission policies\n const rowString = JSON.stringify(transformedPolicy);\n if (uniqueItems.has(rowString)) {\n throw new ConflictError(\n `Duplicate polices found; ${policy.entityReference}, ${policy.permission}, ${policy.policy}, ${policy.effect} is a duplicate`,\n );\n } else {\n uniqueItems.add(rowString);\n policies.push(transformedPolicy);\n }\n }\n return policies;\n }\n\n nameSort(nameA: string, nameB: string): number {\n if (nameA.toLocaleUpperCase('en-US') < nameB.toLocaleUpperCase('en-US')) {\n return -1;\n }\n if (nameA.toLocaleUpperCase('en-US') > nameB.toLocaleUpperCase('en-US')) {\n return 1;\n }\n return 0;\n }\n}\n"],"names":["policyEntityReadPermission","NotAllowedError","createRouter","ServiceUnavailableError","createPermissionIntegrationRouter","RESOURCE_TYPE_POLICY_ENTITY","policyEntityPermissions","AuthorizeResult","PermissionEvents","SEND_RESPONSE_STAGE","NotFoundError","policyEntityDeletePermission","isEmpty","InputError","policyEntityCreatePermission","policyEntityUpdatePermission","isEqual","RoleEvents","validateRole","validateSource","ConflictError","deepSortedEqual","ListPluginPoliciesEvents","ListConditionEvents","ConditionEvents","validateRoleCondition","processConditionMapping","logAuditError","validateEntityReference","buildRoleSourceMap","daoToMetadata","isPermissionAction","validatePolicy","policyToString"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"policies-rest-api.cjs.js","sources":["../../src/service/policies-rest-api.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 { PermissionsService } from '@backstage/backend-plugin-api';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n NotFoundError,\n ServiceUnavailableError,\n} from '@backstage/errors';\nimport { createRouter } from '@backstage/plugin-permission-backend';\nimport {\n AuthorizeResult,\n PolicyDecision,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport type { AuditLogger } from '@janus-idp/backstage-plugin-audit-log-node';\nimport express from 'express';\nimport type { Request } from 'express-serve-static-core';\nimport { isEmpty, isEqual } from 'lodash';\nimport type { ParsedQs } from 'qs';\n\nimport {\n PermissionAction,\n policyEntityCreatePermission,\n policyEntityDeletePermission,\n policyEntityPermissions,\n policyEntityReadPermission,\n policyEntityUpdatePermission,\n RESOURCE_TYPE_POLICY_ENTITY,\n Role,\n RoleBasedPolicy,\n RoleConditionalPolicyDecision,\n} from '@backstage-community/plugin-rbac-common';\nimport type { RBACProvider } from '@backstage-community/plugin-rbac-node';\n\nimport {\n ConditionAuditInfo,\n ConditionEvents,\n ListConditionEvents,\n ListPluginPoliciesEvents,\n PermissionAuditInfo,\n PermissionEvents,\n RoleAuditInfo,\n RoleEvents,\n SEND_RESPONSE_STAGE,\n} from '../audit-log/audit-logger';\nimport { auditError as logAuditError } from '../audit-log/rest-errors-interceptor';\nimport { ConditionalStorage } from '../database/conditional-storage';\nimport {\n daoToMetadata,\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\nimport {\n buildRoleSourceMap,\n deepSortedEqual,\n isPermissionAction,\n policyToString,\n processConditionMapping,\n} from '../helper';\nimport { validateRoleCondition } from '../validation/condition-validation';\nimport {\n validateEntityReference,\n validatePolicy,\n validateRole,\n validateSource,\n} from '../validation/policies-validation';\nimport { EnforcerDelegate } from './enforcer-delegate';\nimport { PluginPermissionMetadataCollector } from './plugin-endpoints';\nimport { RBACRouterOptions } from './policy-builder';\n\nexport class PoliciesServer {\n constructor(\n private readonly permissions: PermissionsService,\n private readonly options: RBACRouterOptions,\n private readonly enforcer: EnforcerDelegate,\n private readonly conditionalStorage: ConditionalStorage,\n private readonly pluginPermMetaData: PluginPermissionMetadataCollector,\n private readonly roleMetadata: RoleMetadataStorage,\n private readonly aLog: AuditLogger,\n private readonly rbacProviders?: RBACProvider[],\n ) {}\n\n private async authorize(\n request: Request,\n permission: ResourcePermission,\n ): Promise<PolicyDecision> {\n const credentials = await this.options.httpAuth.credentials(request, {\n allow: ['user', 'service'],\n });\n\n // allow service to service communication, but only with read permission\n if (\n this.options.auth.isPrincipal(credentials, 'service') &&\n permission !== policyEntityReadPermission\n ) {\n throw new NotAllowedError(\n `Only creadential principal with type 'user' permitted to modify permissions`,\n );\n }\n\n const decision = (\n await this.permissions.authorize(\n [{ permission: permission, resourceRef: permission.resourceType }],\n { credentials },\n )\n )[0];\n\n return decision;\n }\n\n async serve(): Promise<express.Router> {\n const router = await createRouter(this.options);\n\n const { httpAuth } = this.options;\n\n if (!httpAuth) {\n throw new ServiceUnavailableError(\n 'httpAuth not found, ensure the correct configuration for the RBAC plugin',\n );\n }\n\n const permissionsIntegrationRouter = createPermissionIntegrationRouter({\n resourceType: RESOURCE_TYPE_POLICY_ENTITY,\n permissions: policyEntityPermissions,\n });\n router.use(permissionsIntegrationRouter);\n\n const isPluginEnabled =\n this.options.config.getOptionalBoolean('permission.enabled');\n if (!isPluginEnabled) {\n return router;\n }\n\n router.get('/', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n response.send({ status: 'Authorized' });\n });\n\n // Policy CRUD\n\n router.get('/policies', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n let policies: string[][];\n if (this.isPolicyFilterEnabled(request)) {\n const entityRef = this.getFirstQuery(request.query.entityRef);\n const permission = this.getFirstQuery(request.query.permission);\n const policy = this.getFirstQuery(request.query.policy);\n const effect = this.getFirstQuery(request.query.effect);\n\n const filter: string[] = [entityRef, permission, policy, effect];\n policies = await this.enforcer.getFilteredPolicy(0, ...filter);\n } else {\n policies = await this.enforcer.getPolicy();\n }\n\n const body = await this.transformPolicyArray(...policies);\n\n await this.aLog.auditLog({\n message: `Return list permission policies`,\n eventName: PermissionEvents.GET_POLICY,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get(\n '/policies/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const entityRef = this.getEntityReference(request);\n\n const policy = await this.enforcer.getFilteredPolicy(0, entityRef);\n if (policy.length !== 0) {\n const body = await this.transformPolicyArray(...policy);\n\n await this.aLog.auditLog({\n message: `Return permission policy`,\n eventName: PermissionEvents.GET_POLICY,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n },\n );\n\n router.delete(\n '/policies/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityDeletePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const entityRef = this.getEntityReference(request);\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n policyRaw.forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedPolicies = await this.processPolicies(policyRaw, true);\n\n await this.enforcer.removePolicies(processedPolicies);\n\n await this.aLog.auditLog<PermissionAuditInfo>({\n message: `Deleted permission policies`,\n eventName: PermissionEvents.DELETE_POLICY,\n metadata: { policies: processedPolicies, source: 'rest' },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 204 },\n });\n\n response.status(204).end();\n },\n );\n\n router.post('/policies', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const policyRaw: RoleBasedPolicy[] = request.body;\n\n if (isEmpty(policyRaw)) {\n throw new InputError(`permission policy must be present`); // 400\n }\n\n const processedPolicies = await this.processPolicies(policyRaw);\n\n const entityRef = processedPolicies[0][0];\n const roleMetadata = await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.addPolicies(processedPolicies);\n\n await this.aLog.auditLog<PermissionAuditInfo>({\n message: `Created permission policies`,\n eventName: PermissionEvents.CREATE_POLICY,\n metadata: { policies: processedPolicies, source: 'rest' },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 201 },\n });\n\n response.status(201).end();\n });\n\n router.put(\n '/policies/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityUpdatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const entityRef = this.getEntityReference(request);\n\n const oldPolicyRaw: RoleBasedPolicy[] = request.body.oldPolicy;\n if (isEmpty(oldPolicyRaw)) {\n throw new InputError(`'oldPolicy' object must be present`); // 400\n }\n const newPolicyRaw: RoleBasedPolicy[] = request.body.newPolicy;\n if (isEmpty(newPolicyRaw)) {\n throw new InputError(`'newPolicy' object must be present`); // 400\n }\n\n [...oldPolicyRaw, ...newPolicyRaw].forEach(element => {\n element.entityReference = entityRef;\n });\n\n const processedOldPolicy = await this.processPolicies(\n oldPolicyRaw,\n true,\n 'old policy',\n );\n\n oldPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n newPolicyRaw.sort((a, b) =>\n a.permission === b.permission\n ? this.nameSort(a.policy!, b.policy!)\n : this.nameSort(a.permission!, b.permission!),\n );\n\n if (\n isEqual(oldPolicyRaw, newPolicyRaw) &&\n !oldPolicyRaw.some(isEmpty)\n ) {\n response.status(204).end();\n } else if (oldPolicyRaw.length > newPolicyRaw.length) {\n throw new InputError(\n `'oldPolicy' object has more permission policies compared to 'newPolicy' object`,\n );\n }\n\n const processedNewPolicy = await this.processPolicies(\n newPolicyRaw,\n false,\n 'new policy',\n );\n\n const roleMetadata =\n await this.roleMetadata.findRoleMetadata(entityRef);\n if (entityRef.startsWith('role:default') && !roleMetadata) {\n throw new Error(`Corresponding role ${entityRef} was not found`);\n }\n\n await this.enforcer.updatePolicies(\n processedOldPolicy,\n processedNewPolicy,\n );\n\n await this.aLog.auditLog<PermissionAuditInfo>({\n message: `Updated permission policies`,\n eventName: PermissionEvents.UPDATE_POLICY,\n metadata: { policies: processedNewPolicy, source: 'rest' },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200 },\n });\n\n response.status(200).end();\n },\n );\n\n // Role CRUD\n\n router.get('/roles', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const roles = await this.enforcer.getGroupingPolicy();\n\n const body = await this.transformRoleArray(...roles);\n\n await this.aLog.auditLog({\n message: `Return list roles`,\n eventName: RoleEvents.GET_ROLE,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get('/roles/:kind/:namespace/:name', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n const roleEntityRef = this.getEntityReference(request, true);\n\n const role = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n\n if (role.length !== 0) {\n const body = await this.transformRoleArray(...role);\n\n await this.aLog.auditLog({\n message: `Return ${body[0].name}`,\n eventName: RoleEvents.GET_ROLE,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n } else {\n throw new NotFoundError(); // 404\n }\n });\n\n router.post('/roles', async (request, response) => {\n const uniqueItems = new Set<string>();\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n const roleRaw: Role = request.body;\n let err = validateRole(roleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid role definition. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(roleRaw);\n\n const rMetadata = await this.roleMetadata.findRoleMetadata(roleRaw.name);\n\n err = await validateSource('rest', rMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to add role: ${err.message}`);\n }\n\n const roles = this.transformRoleToArray(roleRaw);\n\n for (const role of roles) {\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n throw new ConflictError(); // 409\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n const modifiedBy = credentials.principal.userEntityRef;\n const metadata: RoleMetadataDao = {\n roleEntityRef: roleRaw.name,\n source: 'rest',\n description: roleRaw.metadata?.description ?? '',\n author: modifiedBy,\n modifiedBy,\n };\n\n await this.enforcer.addGroupingPolicies(roles, metadata);\n\n await this.aLog.auditLog<RoleAuditInfo>({\n message: `Created ${metadata.roleEntityRef}`,\n eventName: RoleEvents.CREATE_ROLE,\n metadata: {\n ...metadata,\n members: roles.map(gp => gp[0]),\n },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 201 },\n });\n\n response.status(201).end();\n });\n\n router.put('/roles/:kind/:namespace/:name', async (request, response) => {\n const uniqueItems = new Set<string>();\n const decision = await this.authorize(\n request,\n policyEntityUpdatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n const roleEntityRef = this.getEntityReference(request, true);\n\n const oldRoleRaw: Role = request.body.oldRole;\n\n if (!oldRoleRaw) {\n throw new InputError(`'oldRole' object must be present`); // 400\n }\n const newRoleRaw: Role = request.body.newRole;\n if (!newRoleRaw) {\n throw new InputError(`'newRole' object must be present`); // 400\n }\n\n oldRoleRaw.name = roleEntityRef;\n let err = validateRole(oldRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid old role object. Cause: ${err.message}`,\n );\n }\n err = validateRole(newRoleRaw);\n if (err) {\n throw new InputError( // 400\n `Invalid new role object. Cause: ${err.message}`,\n );\n }\n this.transformMemberReferencesToLowercase(oldRoleRaw);\n this.transformMemberReferencesToLowercase(newRoleRaw);\n\n const oldRole = this.transformRoleToArray(oldRoleRaw);\n const newRole = this.transformRoleToArray(newRoleRaw);\n // todo shell we allow newRole with an empty array?...\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n const newMetadata: RoleMetadataDao = {\n ...newRoleRaw.metadata,\n source: newRoleRaw.metadata?.source ?? 'rest',\n roleEntityRef: newRoleRaw.name,\n modifiedBy: credentials.principal.userEntityRef,\n };\n\n const oldMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n if (!oldMetadata) {\n throw new NotFoundError(`Unable to find metadata for ${roleEntityRef}`);\n }\n\n err = await validateSource('rest', oldMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to edit role: ${err.message}`);\n }\n\n if (\n isEqual(oldRole, newRole) &&\n deepSortedEqual(oldMetadata, newMetadata, [\n 'author',\n 'modifiedBy',\n 'createdAt',\n 'lastModified',\n ])\n ) {\n // no content: old role and new role are equal and their metadata too\n response.status(204).end();\n return;\n }\n\n for (const role of newRole) {\n const hasRole = oldRole.some(element => {\n return isEqual(element, role);\n });\n // if the role is already part of old role and is a grouping policy we want to skip returning a conflict error\n // to allow for other roles to be checked and added\n if (await this.enforcer.hasGroupingPolicy(...role)) {\n if (!hasRole) {\n throw new ConflictError(); // 409\n }\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n uniqueItems.clear();\n for (const role of oldRole) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(\n `Member reference: ${role[0]} was not found for role ${roleEntityRef}`,\n ); // 404\n }\n const roleString = JSON.stringify(role);\n\n if (uniqueItems.has(roleString)) {\n throw new ConflictError(\n `Duplicate role members found; ${role.at(0)}, ${role.at(\n 1,\n )} is a duplicate`,\n );\n } else {\n uniqueItems.add(roleString);\n }\n }\n\n await this.enforcer.updateGroupingPolicies(oldRole, newRole, newMetadata);\n\n let message = `Updated ${oldMetadata.roleEntityRef}.`;\n if (newMetadata.roleEntityRef !== oldMetadata.roleEntityRef) {\n message = `${message}. Role entity reference renamed to ${newMetadata.roleEntityRef}`;\n }\n await this.aLog.auditLog<RoleAuditInfo>({\n message,\n eventName: RoleEvents.UPDATE_ROLE,\n metadata: {\n ...newMetadata,\n members: newRole.map(gp => gp[0]),\n },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200 },\n });\n\n response.status(200).end();\n });\n\n router.delete(\n '/roles/:kind/:namespace/:name',\n async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityDeletePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const roleEntityRef = this.getEntityReference(request, true);\n\n let roleMembers = [];\n if (request.query.memberReferences) {\n const memberReference = this.getFirstQuery(\n request.query.memberReferences!,\n ).toLocaleLowerCase('en-US');\n const gp = await this.enforcer.getFilteredGroupingPolicy(\n 0,\n memberReference,\n roleEntityRef,\n );\n if (gp.length > 0) {\n roleMembers.push(gp[0]);\n } else {\n throw new NotFoundError(\n `role member '${memberReference}' was not found`,\n ); // 404\n }\n } else {\n roleMembers = await this.enforcer.getFilteredGroupingPolicy(\n 1,\n roleEntityRef,\n );\n }\n\n for (const role of roleMembers) {\n if (!(await this.enforcer.hasGroupingPolicy(...role))) {\n throw new NotFoundError(`role member '${role[0]}' was not found`);\n }\n }\n\n const currentMetadata =\n await this.roleMetadata.findRoleMetadata(roleEntityRef);\n const err = await validateSource('rest', currentMetadata);\n if (err) {\n throw new NotAllowedError(`Unable to delete role: ${err.message}`);\n }\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n const metadata: RoleMetadataDao = {\n roleEntityRef,\n source: 'rest',\n modifiedBy: credentials.principal.userEntityRef,\n };\n\n await this.enforcer.removeGroupingPolicies(\n roleMembers,\n metadata,\n false,\n );\n\n await this.aLog.auditLog<RoleAuditInfo>({\n message: `Deleted ${metadata.roleEntityRef}`,\n eventName: RoleEvents.DELETE_ROLE,\n metadata: {\n ...metadata,\n members: roleMembers.map(gp => gp[0]),\n },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 204 },\n });\n\n response.status(204).end();\n },\n );\n\n router.get('/plugins/policies', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const body = await this.pluginPermMetaData.getPluginPolicies(\n this.options.auth,\n );\n\n await this.aLog.auditLog({\n message: `Return list plugin policies`,\n eventName: ListPluginPoliciesEvents.GET_PLUGINS_POLICIES,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get('/plugins/condition-rules', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const body = await this.pluginPermMetaData.getPluginConditionRules(\n this.options.auth,\n );\n\n await this.aLog.auditLog({\n message: `Return list conditional rules and schemas`,\n eventName: ListConditionEvents.GET_CONDITION_RULES,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.get('/roles/conditions', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const conditions = await this.conditionalStorage.filterConditions(\n this.getFirstQuery(request.query.roleEntityRef),\n this.getFirstQuery(request.query.pluginId),\n this.getFirstQuery(request.query.resourceType),\n this.getActionQueries(request.query.actions),\n );\n\n const body: RoleConditionalPolicyDecision<PermissionAction>[] =\n conditions.map(condition => {\n return {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n });\n\n await this.aLog.auditLog({\n message: `Return list conditional permission policies`,\n eventName: ConditionEvents.GET_CONDITION,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.post('/roles/conditions', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToCreate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n this.options.auth,\n );\n\n const id =\n await this.conditionalStorage.createCondition(conditionToCreate);\n\n const body = { id: id };\n\n await this.aLog.auditLog<ConditionAuditInfo>({\n message: `Created conditional permission policy`,\n eventName: ConditionEvents.CREATE_CONDITION,\n metadata: { condition: roleConditionPolicy },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 201, body },\n });\n\n response.status(201).json(body);\n });\n\n router.get('/roles/conditions/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityReadPermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError();\n }\n\n const body: RoleConditionalPolicyDecision<PermissionAction> = {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n\n await this.aLog.auditLog({\n message: `Return conditional permission policy by id`,\n eventName: ConditionEvents.GET_CONDITION,\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200, body },\n });\n\n response.json(body);\n });\n\n router.delete('/roles/conditions/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityDeletePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const condition = await this.conditionalStorage.getCondition(id);\n if (!condition) {\n throw new NotFoundError(`Condition with id ${id} was not found`);\n }\n const conditionToDelete: RoleConditionalPolicyDecision<PermissionAction> =\n {\n ...condition,\n permissionMapping: condition.permissionMapping.map(pm => pm.action),\n };\n\n await this.conditionalStorage.deleteCondition(id);\n\n await this.aLog.auditLog<ConditionAuditInfo>({\n message: `Deleted conditional permission policy`,\n eventName: ConditionEvents.DELETE_CONDITION,\n metadata: { condition: conditionToDelete },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 204 },\n });\n\n response.status(204).end();\n });\n\n router.put('/roles/conditions/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityUpdatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n const id: number = parseInt(request.params.id, 10);\n if (isNaN(id)) {\n throw new InputError('Id is not a valid number.');\n }\n\n const roleConditionPolicy: RoleConditionalPolicyDecision<PermissionAction> =\n request.body;\n\n validateRoleCondition(roleConditionPolicy);\n\n const conditionToUpdate = await processConditionMapping(\n roleConditionPolicy,\n this.pluginPermMetaData,\n this.options.auth,\n );\n\n await this.conditionalStorage.updateCondition(id, conditionToUpdate);\n\n await this.aLog.auditLog<ConditionAuditInfo>({\n message: `Updated conditional permission policy`,\n eventName: ConditionEvents.UPDATE_CONDITION,\n metadata: { condition: roleConditionPolicy },\n stage: SEND_RESPONSE_STAGE,\n status: 'succeeded',\n request,\n response: { status: 200 },\n });\n\n response.status(200).end();\n });\n\n router.post('/refresh/:id', async (request, response) => {\n const decision = await this.authorize(\n request,\n policyEntityCreatePermission,\n );\n\n if (decision.result === AuthorizeResult.DENY) {\n throw new NotAllowedError(); // 403\n }\n\n if (!this.rbacProviders) {\n throw new NotFoundError(`No RBAC providers were found`);\n }\n\n const idProvider = this.rbacProviders.find(provider => {\n const id = provider.getProviderName();\n return id === request.params.id;\n });\n\n if (!idProvider) {\n throw new NotFoundError(\n `The RBAC provider ${request.params.id} was not found`,\n );\n }\n\n await idProvider.refresh();\n response.status(200).end();\n });\n\n router.use(logAuditError(this.aLog));\n\n return router;\n }\n\n getEntityReference(request: Request, role?: boolean): string {\n const kind = request.params.kind;\n const namespace = request.params.namespace;\n const name = request.params.name;\n const entityRef = `${kind}:${namespace}/${name}`;\n\n const err = validateEntityReference(entityRef, role);\n if (err) {\n throw new InputError(err.message);\n }\n\n return entityRef;\n }\n\n async transformPolicyArray(\n ...policies: string[][]\n ): Promise<RoleBasedPolicy[]> {\n const roleToSourceMap = await buildRoleSourceMap(\n policies,\n this.roleMetadata,\n );\n\n const roleBasedPolices: RoleBasedPolicy[] = [];\n for (const p of policies) {\n const [entityReference, permission, policy, effect] = p;\n roleBasedPolices.push({\n entityReference,\n permission,\n policy,\n effect,\n metadata: { source: roleToSourceMap.get(entityReference)! },\n });\n }\n\n return roleBasedPolices;\n }\n\n async transformRoleArray(...roles: string[][]): Promise<Role[]> {\n const combinedRoles: { [key: string]: string[] } = {};\n\n roles.forEach(([value, role]) => {\n if (combinedRoles.hasOwnProperty(role)) {\n combinedRoles[role].push(value);\n } else {\n combinedRoles[role] = [value];\n }\n });\n\n const result: Role[] = await Promise.all(\n Object.entries(combinedRoles).map(async ([role, value]) => {\n const metadataDao = await this.roleMetadata.findRoleMetadata(role);\n const metadata = metadataDao ? daoToMetadata(metadataDao) : undefined;\n return Promise.resolve({\n memberReferences: value,\n name: role,\n metadata,\n });\n }),\n );\n return result;\n }\n\n transformPolicyToArray(policy: RoleBasedPolicy): string[] {\n return [\n policy.entityReference!,\n policy.permission!,\n policy.policy!,\n policy.effect!,\n ];\n }\n\n transformRoleToArray(role: Role): string[][] {\n const roles: string[][] = [];\n for (const entity of role.memberReferences) {\n roles.push([entity, role.name]);\n }\n return roles;\n }\n\n transformMemberReferencesToLowercase(role: Role) {\n role.memberReferences = role.memberReferences.map(member =>\n member.toLocaleLowerCase('en-US'),\n );\n }\n\n getActionQueries(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): PermissionAction[] | undefined {\n if (!queryValue) {\n return undefined;\n }\n if (Array.isArray(queryValue)) {\n const permissionNames: PermissionAction[] = [];\n for (const permissionQuery of queryValue) {\n if (\n typeof permissionQuery === 'string' &&\n isPermissionAction(permissionQuery)\n ) {\n permissionNames.push(permissionQuery);\n } else {\n throw new InputError(\n `Invalid permission action query value: ${permissionQuery}. Permission name should be string.`,\n );\n }\n }\n return permissionNames;\n }\n\n if (typeof queryValue === 'string' && isPermissionAction(queryValue)) {\n return [queryValue];\n }\n throw new InputError(\n `Invalid permission action query value: ${queryValue}. Permission name should be string.`,\n );\n }\n\n getFirstQuery(\n queryValue: string | string[] | ParsedQs | ParsedQs[] | undefined,\n ): string {\n if (!queryValue) {\n return '';\n }\n if (Array.isArray(queryValue)) {\n if (typeof queryValue[0] === 'string') {\n return queryValue[0].toString();\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n if (typeof queryValue === 'string') {\n return queryValue;\n }\n throw new InputError(`This api doesn't support nested query`);\n }\n\n isPolicyFilterEnabled(request: Request): boolean {\n return (\n !!request.query.entityRef ||\n !!request.query.permission ||\n !!request.query.policy ||\n !!request.query.effect\n );\n }\n\n async processPolicies(\n policyArray: RoleBasedPolicy[],\n isOld?: boolean,\n errorMessage?: string,\n ): Promise<string[][]> {\n const policies: string[][] = [];\n const uniqueItems = new Set<string>();\n for (const policy of policyArray) {\n let err = validatePolicy(policy);\n if (err) {\n throw new InputError(\n `Invalid ${errorMessage ?? 'policy'} definition. Cause: ${\n err.message\n }`,\n ); // 400\n }\n\n const metadata = await this.roleMetadata.findRoleMetadata(\n policy.entityReference!,\n );\n\n let action = errorMessage ? 'edit' : 'delete';\n action = isOld ? action : 'add';\n\n err = await validateSource('rest', metadata);\n if (err) {\n throw new NotAllowedError(\n `Unable to ${action} policy ${policy.entityReference},${policy.permission},${policy.policy},${policy.effect}: ${err.message}`,\n );\n }\n\n const transformedPolicy = this.transformPolicyToArray(policy);\n if (isOld && !(await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new NotFoundError(\n `Policy '${policyToString(transformedPolicy)}' not found`,\n ); // 404\n }\n\n if (!isOld && (await this.enforcer.hasPolicy(...transformedPolicy))) {\n throw new ConflictError(\n `Policy '${policyToString(\n transformedPolicy,\n )}' has been already stored`,\n ); // 409\n }\n\n // We want to ensure that there are not duplicate permission policies\n const rowString = JSON.stringify(transformedPolicy);\n if (uniqueItems.has(rowString)) {\n throw new ConflictError(\n `Duplicate polices found; ${policy.entityReference}, ${policy.permission}, ${policy.policy}, ${policy.effect} is a duplicate`,\n );\n } else {\n uniqueItems.add(rowString);\n policies.push(transformedPolicy);\n }\n }\n return policies;\n }\n\n nameSort(nameA: string, nameB: string): number {\n if (nameA.toLocaleUpperCase('en-US') < nameB.toLocaleUpperCase('en-US')) {\n return -1;\n }\n if (nameA.toLocaleUpperCase('en-US') > nameB.toLocaleUpperCase('en-US')) {\n return 1;\n }\n return 0;\n }\n}\n"],"names":["policyEntityReadPermission","NotAllowedError","createRouter","ServiceUnavailableError","createPermissionIntegrationRouter","RESOURCE_TYPE_POLICY_ENTITY","policyEntityPermissions","AuthorizeResult","PermissionEvents","SEND_RESPONSE_STAGE","NotFoundError","policyEntityDeletePermission","isEmpty","InputError","policyEntityCreatePermission","policyEntityUpdatePermission","isEqual","RoleEvents","validateRole","validateSource","ConflictError","deepSortedEqual","ListPluginPoliciesEvents","ListConditionEvents","ConditionEvents","validateRoleCondition","processConditionMapping","logAuditError","validateEntityReference","buildRoleSourceMap","daoToMetadata","isPermissionAction","validatePolicy","policyToString"],"mappings":"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"}
|
|
@@ -7,14 +7,14 @@ var pluginRbacCommon = require('@backstage-community/plugin-rbac-common');
|
|
|
7
7
|
|
|
8
8
|
const validateSource = async (source, roleMetadata) => {
|
|
9
9
|
if (!roleMetadata) {
|
|
10
|
-
return
|
|
10
|
+
return undefined;
|
|
11
11
|
}
|
|
12
12
|
if (roleMetadata.source !== source && roleMetadata.source !== "legacy") {
|
|
13
13
|
return new Error(
|
|
14
14
|
`source does not match originating role ${roleMetadata.roleEntityRef}, consider making changes to the '${roleMetadata.source.toLocaleUpperCase()}'`
|
|
15
15
|
);
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return undefined;
|
|
18
18
|
};
|
|
19
19
|
function validatePolicy(policy) {
|
|
20
20
|
const err = validateEntityReference(policy.entityReference);
|
|
@@ -38,7 +38,7 @@ function validatePolicy(policy) {
|
|
|
38
38
|
`'effect' has invalid value: '${policy.effect}'. It should be: '${pluginPermissionCommon.AuthorizeResult.ALLOW.toLocaleLowerCase()}' or '${pluginPermissionCommon.AuthorizeResult.DENY.toLocaleLowerCase()}'`
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
|
-
return
|
|
41
|
+
return undefined;
|
|
42
42
|
}
|
|
43
43
|
function validateRole(role) {
|
|
44
44
|
if (!role.name) {
|
|
@@ -57,7 +57,7 @@ function validateRole(role) {
|
|
|
57
57
|
return err;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
return
|
|
60
|
+
return undefined;
|
|
61
61
|
}
|
|
62
62
|
function isValidEffectValue(effect) {
|
|
63
63
|
return effect === pluginPermissionCommon.AuthorizeResult.ALLOW.toLocaleLowerCase() || effect === pluginPermissionCommon.AuthorizeResult.DENY.toLocaleLowerCase();
|
|
@@ -106,7 +106,7 @@ function validateEntityReference(entityRef, role) {
|
|
|
106
106
|
`The namespace '${entityRefCompound.namespace}' in the entity reference must be a string that is sequences of [a-z0-9] separated by [-], at most 63 characters in total`
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
|
-
return
|
|
109
|
+
return undefined;
|
|
110
110
|
}
|
|
111
111
|
async function validateGroupingPolicy(groupPolicy, roleMetadataStorage, source) {
|
|
112
112
|
if (groupPolicy.length !== 2) {
|
|
@@ -148,7 +148,7 @@ async function validateGroupingPolicy(groupPolicy, roleMetadataStorage, source)
|
|
|
148
148
|
`Unable to validate role ${groupPolicy}. Cause: ${err.message}`
|
|
149
149
|
);
|
|
150
150
|
}
|
|
151
|
-
return
|
|
151
|
+
return undefined;
|
|
152
152
|
}
|
|
153
153
|
const checkForDuplicatePolicies = async (fileEnf, policy, policyFile) => {
|
|
154
154
|
const duplicates = await fileEnf.getFilteredPolicy(0, ...policy);
|
|
@@ -172,7 +172,7 @@ const checkForDuplicatePolicies = async (fileEnf, policy, policyFile) => {
|
|
|
172
172
|
`Duplicate policy: ${policy[0]}, ${policy[1]}, ${policy[2]} with different effect found in the file ${policyFile}`
|
|
173
173
|
);
|
|
174
174
|
}
|
|
175
|
-
return
|
|
175
|
+
return undefined;
|
|
176
176
|
};
|
|
177
177
|
const checkForDuplicateGroupPolicies = async (fileEnf, policy, policyFile) => {
|
|
178
178
|
const duplicates = await fileEnf.getFilteredGroupingPolicy(0, ...policy);
|
|
@@ -181,7 +181,7 @@ const checkForDuplicateGroupPolicies = async (fileEnf, policy, policyFile) => {
|
|
|
181
181
|
`Duplicate role: ${policy} found in the file ${policyFile}`
|
|
182
182
|
);
|
|
183
183
|
}
|
|
184
|
-
return
|
|
184
|
+
return undefined;
|
|
185
185
|
};
|
|
186
186
|
|
|
187
187
|
exports.checkForDuplicateGroupPolicies = checkForDuplicateGroupPolicies;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policies-validation.cjs.js","sources":["../../src/validation/policies-validation.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 { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model';\nimport { NotAllowedError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\n\nimport { Enforcer } from 'casbin';\n\nimport {\n isValidPermissionAction,\n PermissionActionValues,\n Role,\n RoleBasedPolicy,\n Source,\n} from '@backstage-community/plugin-rbac-common';\n\nimport {\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\n\n/**\n * validateSource validates the source to the role that is being modified. This includes comparing the source from the\n * originating role to the source that the modification is coming from.\n * We do this to ensure consistency between permissions and roles and where they are originally defined.\n * This is a strict comparison where the source of all new roles (grouping policies) and permissions must match\n * the source of the first role that was created.\n * We are not strict for permission policies defined with an originating role source of configuration.\n * @param source The source in which the modification is coming from\n * @param roleMetadata The original role that was created\n * @returns An error in the event that the source does not match the originating role\n */\nexport const validateSource = async (\n source: Source,\n roleMetadata: RoleMetadataDao | undefined,\n): Promise<Error | undefined> => {\n if (!roleMetadata) {\n return undefined; // Role does not exist yet, there is no conflict with the source\n }\n\n if (roleMetadata.source !== source && roleMetadata.source !== 'legacy') {\n return new Error(\n `source does not match originating role ${\n roleMetadata.roleEntityRef\n }, consider making changes to the '${roleMetadata.source.toLocaleUpperCase()}'`,\n );\n }\n\n return undefined;\n};\n\n// This should be called on add and edit and delete\nexport function validatePolicy(policy: RoleBasedPolicy): Error | undefined {\n const err = validateEntityReference(policy.entityReference);\n if (err) {\n return err;\n }\n\n if (!policy.permission) {\n return new Error(`'permission' field must not be empty`);\n }\n\n if (!policy.policy) {\n return new Error(`'policy' field must not be empty`);\n } else if (!isValidPermissionAction(policy.policy)) {\n return new Error(\n `'policy' has invalid value: '${\n policy.policy\n }'. It should be one of: ${PermissionActionValues.join(', ')}`,\n );\n }\n\n if (!policy.effect) {\n return new Error(`'effect' field must not be empty`);\n } else if (!isValidEffectValue(policy.effect)) {\n return new Error(\n `'effect' has invalid value: '${\n policy.effect\n }'. It should be: '${AuthorizeResult.ALLOW.toLocaleLowerCase()}' or '${AuthorizeResult.DENY.toLocaleLowerCase()}'`,\n );\n }\n\n return undefined;\n}\n\nexport function validateRole(role: Role): Error | undefined {\n if (!role.name) {\n return new Error(`'name' field must not be empty`);\n }\n\n let err = validateEntityReference(role.name, true);\n if (err) {\n return err;\n }\n\n if (!role.memberReferences || role.memberReferences.length === 0) {\n return new Error(`'memberReferences' field must not be empty`);\n }\n\n for (const member of role.memberReferences) {\n err = validateEntityReference(member);\n if (err) {\n return err;\n }\n }\n return undefined;\n}\n\nfunction isValidEffectValue(effect: string): boolean {\n return (\n effect === AuthorizeResult.ALLOW.toLocaleLowerCase() ||\n effect === AuthorizeResult.DENY.toLocaleLowerCase()\n );\n}\n\nfunction isValidEntityName(name: string): boolean {\n const validNamePattern = /^[a-zA-Z0-9]+([._-][a-zA-Z0-9]+)*$/;\n return validNamePattern.test(name) && name.length <= 63;\n}\n\nfunction isValidEntityNamespace(namespace: string): boolean {\n const validNamespacePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n return validNamespacePattern.test(namespace) && namespace.length <= 63;\n}\n\n// We supports only full form entity reference: [<kind>:][<namespace>/]<name>\nexport function validateEntityReference(\n entityRef?: string,\n role?: boolean,\n): Error | undefined {\n if (!entityRef) {\n return new Error(`'entityReference' must not be empty`);\n }\n\n let entityRefCompound: CompoundEntityRef;\n try {\n entityRefCompound = parseEntityRef(entityRef);\n } catch (err) {\n return err as Error;\n }\n\n const entityRefFull = `${entityRefCompound.kind}:${entityRefCompound.namespace}/${entityRefCompound.name}`;\n if (entityRefFull !== entityRef) {\n return new Error(\n `entity reference '${entityRef}' does not match the required format [<kind>:][<namespace>/]<name>. Provide, please, full entity reference.`,\n );\n }\n\n if (role && entityRefCompound.kind !== 'role') {\n return new Error(\n `Unsupported kind ${entityRefCompound.kind}. Supported value should be \"role\"`,\n );\n }\n\n if (\n entityRefCompound.kind !== 'user' &&\n entityRefCompound.kind !== 'group' &&\n entityRefCompound.kind !== 'role'\n ) {\n return new Error(\n `Unsupported kind ${entityRefCompound.kind}. List supported values [\"user\", \"group\", \"role\"]`,\n );\n }\n\n if (!isValidEntityName(entityRefCompound.name)) {\n return new Error(\n `The name '${entityRefCompound.name}' in the entity reference must be a string that is sequences of [a-zA-Z0-9] separated by any of [-_.], at most 63 characters in total`,\n );\n }\n\n if (!isValidEntityNamespace(entityRefCompound.namespace)) {\n return new Error(\n `The namespace '${entityRefCompound.namespace}' in the entity reference must be a string that is sequences of [a-z0-9] separated by [-], at most 63 characters in total`,\n );\n }\n\n return undefined;\n}\n\nexport async function validateGroupingPolicy(\n groupPolicy: string[],\n roleMetadataStorage: RoleMetadataStorage,\n source: Source,\n): Promise<Error | undefined> {\n if (groupPolicy.length !== 2) {\n return new Error(`Group policy should have length 2`);\n }\n\n const member = groupPolicy[0];\n let err = validateEntityReference(member);\n if (err) {\n return new Error(\n `Failed to validate group policy ${groupPolicy}. Cause: ${err.message}`,\n );\n }\n const parent = groupPolicy[1];\n err = validateEntityReference(parent);\n if (err) {\n return new Error(\n `Failed to validate group policy ${groupPolicy}. Cause: ${err.message}`,\n );\n }\n if (member.startsWith(`role:`)) {\n return new Error(\n `Group policy is invalid: ${groupPolicy}. rbac-backend plugin doesn't support role inheritance.`,\n );\n }\n if (member.startsWith(`group:`) && parent.startsWith(`group:`)) {\n return new Error(\n `Group policy is invalid: ${groupPolicy}. Group inheritance information could be provided only with help of Catalog API.`,\n );\n }\n if (member.startsWith(`user:`) && parent.startsWith(`group:`)) {\n return new Error(\n `Group policy is invalid: ${groupPolicy}. User membership information could be provided only with help of Catalog API.`,\n );\n }\n\n const metadata = await roleMetadataStorage.findRoleMetadata(parent);\n\n err = await validateSource(source, metadata);\n if (metadata && err) {\n return new NotAllowedError(\n `Unable to validate role ${groupPolicy}. Cause: ${err.message}`,\n );\n }\n\n return undefined;\n}\n\nexport const checkForDuplicatePolicies = async (\n fileEnf: Enforcer,\n policy: string[],\n policyFile: string,\n): Promise<Error | undefined> => {\n const duplicates = await fileEnf.getFilteredPolicy(0, ...policy);\n if (duplicates.length > 1) {\n return new Error(\n `Duplicate policy: ${policy} found in the file ${policyFile}`,\n );\n }\n\n const flipPolicyEffect = [\n policy[0],\n policy[1],\n policy[2],\n policy[3] === 'deny' ? 'allow' : 'deny',\n ];\n\n // Check if the same policy exists but with a different effect\n const dupWithDifferentEffect = await fileEnf.getFilteredPolicy(\n 0,\n ...flipPolicyEffect,\n );\n\n if (dupWithDifferentEffect.length > 0) {\n return new Error(\n `Duplicate policy: ${policy[0]}, ${policy[1]}, ${policy[2]} with different effect found in the file ${policyFile}`,\n );\n }\n\n return undefined;\n};\n\nexport const checkForDuplicateGroupPolicies = async (\n fileEnf: Enforcer,\n policy: string[],\n policyFile: string,\n): Promise<Error | undefined> => {\n const duplicates = await fileEnf.getFilteredGroupingPolicy(0, ...policy);\n\n if (duplicates.length > 1) {\n return new Error(\n `Duplicate role: ${policy} found in the file ${policyFile}`,\n );\n }\n return undefined;\n};\n"],"names":["isValidPermissionAction","PermissionActionValues","AuthorizeResult","parseEntityRef","NotAllowedError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"policies-validation.cjs.js","sources":["../../src/validation/policies-validation.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 { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model';\nimport { NotAllowedError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\n\nimport { Enforcer } from 'casbin';\n\nimport {\n isValidPermissionAction,\n PermissionActionValues,\n Role,\n RoleBasedPolicy,\n Source,\n} from '@backstage-community/plugin-rbac-common';\n\nimport {\n RoleMetadataDao,\n RoleMetadataStorage,\n} from '../database/role-metadata';\n\n/**\n * validateSource validates the source to the role that is being modified. This includes comparing the source from the\n * originating role to the source that the modification is coming from.\n * We do this to ensure consistency between permissions and roles and where they are originally defined.\n * This is a strict comparison where the source of all new roles (grouping policies) and permissions must match\n * the source of the first role that was created.\n * We are not strict for permission policies defined with an originating role source of configuration.\n * @param source The source in which the modification is coming from\n * @param roleMetadata The original role that was created\n * @returns An error in the event that the source does not match the originating role\n */\nexport const validateSource = async (\n source: Source,\n roleMetadata: RoleMetadataDao | undefined,\n): Promise<Error | undefined> => {\n if (!roleMetadata) {\n return undefined; // Role does not exist yet, there is no conflict with the source\n }\n\n if (roleMetadata.source !== source && roleMetadata.source !== 'legacy') {\n return new Error(\n `source does not match originating role ${\n roleMetadata.roleEntityRef\n }, consider making changes to the '${roleMetadata.source.toLocaleUpperCase()}'`,\n );\n }\n\n return undefined;\n};\n\n// This should be called on add and edit and delete\nexport function validatePolicy(policy: RoleBasedPolicy): Error | undefined {\n const err = validateEntityReference(policy.entityReference);\n if (err) {\n return err;\n }\n\n if (!policy.permission) {\n return new Error(`'permission' field must not be empty`);\n }\n\n if (!policy.policy) {\n return new Error(`'policy' field must not be empty`);\n } else if (!isValidPermissionAction(policy.policy)) {\n return new Error(\n `'policy' has invalid value: '${\n policy.policy\n }'. It should be one of: ${PermissionActionValues.join(', ')}`,\n );\n }\n\n if (!policy.effect) {\n return new Error(`'effect' field must not be empty`);\n } else if (!isValidEffectValue(policy.effect)) {\n return new Error(\n `'effect' has invalid value: '${\n policy.effect\n }'. It should be: '${AuthorizeResult.ALLOW.toLocaleLowerCase()}' or '${AuthorizeResult.DENY.toLocaleLowerCase()}'`,\n );\n }\n\n return undefined;\n}\n\nexport function validateRole(role: Role): Error | undefined {\n if (!role.name) {\n return new Error(`'name' field must not be empty`);\n }\n\n let err = validateEntityReference(role.name, true);\n if (err) {\n return err;\n }\n\n if (!role.memberReferences || role.memberReferences.length === 0) {\n return new Error(`'memberReferences' field must not be empty`);\n }\n\n for (const member of role.memberReferences) {\n err = validateEntityReference(member);\n if (err) {\n return err;\n }\n }\n return undefined;\n}\n\nfunction isValidEffectValue(effect: string): boolean {\n return (\n effect === AuthorizeResult.ALLOW.toLocaleLowerCase() ||\n effect === AuthorizeResult.DENY.toLocaleLowerCase()\n );\n}\n\nfunction isValidEntityName(name: string): boolean {\n const validNamePattern = /^[a-zA-Z0-9]+([._-][a-zA-Z0-9]+)*$/;\n return validNamePattern.test(name) && name.length <= 63;\n}\n\nfunction isValidEntityNamespace(namespace: string): boolean {\n const validNamespacePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n return validNamespacePattern.test(namespace) && namespace.length <= 63;\n}\n\n// We supports only full form entity reference: [<kind>:][<namespace>/]<name>\nexport function validateEntityReference(\n entityRef?: string,\n role?: boolean,\n): Error | undefined {\n if (!entityRef) {\n return new Error(`'entityReference' must not be empty`);\n }\n\n let entityRefCompound: CompoundEntityRef;\n try {\n entityRefCompound = parseEntityRef(entityRef);\n } catch (err) {\n return err as Error;\n }\n\n const entityRefFull = `${entityRefCompound.kind}:${entityRefCompound.namespace}/${entityRefCompound.name}`;\n if (entityRefFull !== entityRef) {\n return new Error(\n `entity reference '${entityRef}' does not match the required format [<kind>:][<namespace>/]<name>. Provide, please, full entity reference.`,\n );\n }\n\n if (role && entityRefCompound.kind !== 'role') {\n return new Error(\n `Unsupported kind ${entityRefCompound.kind}. Supported value should be \"role\"`,\n );\n }\n\n if (\n entityRefCompound.kind !== 'user' &&\n entityRefCompound.kind !== 'group' &&\n entityRefCompound.kind !== 'role'\n ) {\n return new Error(\n `Unsupported kind ${entityRefCompound.kind}. List supported values [\"user\", \"group\", \"role\"]`,\n );\n }\n\n if (!isValidEntityName(entityRefCompound.name)) {\n return new Error(\n `The name '${entityRefCompound.name}' in the entity reference must be a string that is sequences of [a-zA-Z0-9] separated by any of [-_.], at most 63 characters in total`,\n );\n }\n\n if (!isValidEntityNamespace(entityRefCompound.namespace)) {\n return new Error(\n `The namespace '${entityRefCompound.namespace}' in the entity reference must be a string that is sequences of [a-z0-9] separated by [-], at most 63 characters in total`,\n );\n }\n\n return undefined;\n}\n\nexport async function validateGroupingPolicy(\n groupPolicy: string[],\n roleMetadataStorage: RoleMetadataStorage,\n source: Source,\n): Promise<Error | undefined> {\n if (groupPolicy.length !== 2) {\n return new Error(`Group policy should have length 2`);\n }\n\n const member = groupPolicy[0];\n let err = validateEntityReference(member);\n if (err) {\n return new Error(\n `Failed to validate group policy ${groupPolicy}. Cause: ${err.message}`,\n );\n }\n const parent = groupPolicy[1];\n err = validateEntityReference(parent);\n if (err) {\n return new Error(\n `Failed to validate group policy ${groupPolicy}. Cause: ${err.message}`,\n );\n }\n if (member.startsWith(`role:`)) {\n return new Error(\n `Group policy is invalid: ${groupPolicy}. rbac-backend plugin doesn't support role inheritance.`,\n );\n }\n if (member.startsWith(`group:`) && parent.startsWith(`group:`)) {\n return new Error(\n `Group policy is invalid: ${groupPolicy}. Group inheritance information could be provided only with help of Catalog API.`,\n );\n }\n if (member.startsWith(`user:`) && parent.startsWith(`group:`)) {\n return new Error(\n `Group policy is invalid: ${groupPolicy}. User membership information could be provided only with help of Catalog API.`,\n );\n }\n\n const metadata = await roleMetadataStorage.findRoleMetadata(parent);\n\n err = await validateSource(source, metadata);\n if (metadata && err) {\n return new NotAllowedError(\n `Unable to validate role ${groupPolicy}. Cause: ${err.message}`,\n );\n }\n\n return undefined;\n}\n\nexport const checkForDuplicatePolicies = async (\n fileEnf: Enforcer,\n policy: string[],\n policyFile: string,\n): Promise<Error | undefined> => {\n const duplicates = await fileEnf.getFilteredPolicy(0, ...policy);\n if (duplicates.length > 1) {\n return new Error(\n `Duplicate policy: ${policy} found in the file ${policyFile}`,\n );\n }\n\n const flipPolicyEffect = [\n policy[0],\n policy[1],\n policy[2],\n policy[3] === 'deny' ? 'allow' : 'deny',\n ];\n\n // Check if the same policy exists but with a different effect\n const dupWithDifferentEffect = await fileEnf.getFilteredPolicy(\n 0,\n ...flipPolicyEffect,\n );\n\n if (dupWithDifferentEffect.length > 0) {\n return new Error(\n `Duplicate policy: ${policy[0]}, ${policy[1]}, ${policy[2]} with different effect found in the file ${policyFile}`,\n );\n }\n\n return undefined;\n};\n\nexport const checkForDuplicateGroupPolicies = async (\n fileEnf: Enforcer,\n policy: string[],\n policyFile: string,\n): Promise<Error | undefined> => {\n const duplicates = await fileEnf.getFilteredGroupingPolicy(0, ...policy);\n\n if (duplicates.length > 1) {\n return new Error(\n `Duplicate role: ${policy} found in the file ${policyFile}`,\n );\n }\n return undefined;\n};\n"],"names":["isValidPermissionAction","PermissionActionValues","AuthorizeResult","parseEntityRef","NotAllowedError"],"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": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -34,17 +34,17 @@
|
|
|
34
34
|
"postpack": "backstage-cli package postpack"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@backstage-community/plugin-rbac-common": "^1.
|
|
38
|
-
"@backstage-community/plugin-rbac-node": "^1.
|
|
39
|
-
"@backstage/backend-defaults": "^0.
|
|
40
|
-
"@backstage/backend-plugin-api": "^1.
|
|
41
|
-
"@backstage/catalog-client": "^1.
|
|
42
|
-
"@backstage/catalog-model": "^1.7.
|
|
43
|
-
"@backstage/errors": "^1.2.
|
|
44
|
-
"@backstage/plugin-auth-node": "^0.5.
|
|
45
|
-
"@backstage/plugin-permission-backend": "^0.5.
|
|
46
|
-
"@backstage/plugin-permission-common": "^0.8.
|
|
47
|
-
"@backstage/plugin-permission-node": "^0.8.
|
|
37
|
+
"@backstage-community/plugin-rbac-common": "^1.13.0",
|
|
38
|
+
"@backstage-community/plugin-rbac-node": "^1.9.0",
|
|
39
|
+
"@backstage/backend-defaults": "^0.7.0",
|
|
40
|
+
"@backstage/backend-plugin-api": "^1.1.1",
|
|
41
|
+
"@backstage/catalog-client": "^1.9.1",
|
|
42
|
+
"@backstage/catalog-model": "^1.7.3",
|
|
43
|
+
"@backstage/errors": "^1.2.7",
|
|
44
|
+
"@backstage/plugin-auth-node": "^0.5.6",
|
|
45
|
+
"@backstage/plugin-permission-backend": "^0.5.53",
|
|
46
|
+
"@backstage/plugin-permission-common": "^0.8.4",
|
|
47
|
+
"@backstage/plugin-permission-node": "^0.8.7",
|
|
48
48
|
"@dagrejs/graphlib": "^2.1.13",
|
|
49
49
|
"@janus-idp/backstage-plugin-audit-log-node": "^1.7.1",
|
|
50
50
|
"casbin": "^5.27.1",
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
"typeorm-adapter": "^1.6.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@backstage/backend-test-utils": "1.
|
|
61
|
-
"@backstage/cli": "0.
|
|
62
|
-
"@backstage/config": "1.2
|
|
63
|
-
"@backstage/core-plugin-api": "1.10.
|
|
64
|
-
"@backstage/types": "1.
|
|
60
|
+
"@backstage/backend-test-utils": "^1.2.1",
|
|
61
|
+
"@backstage/cli": "^0.29.5",
|
|
62
|
+
"@backstage/config": "^1.3.2",
|
|
63
|
+
"@backstage/core-plugin-api": "^1.10.3",
|
|
64
|
+
"@backstage/types": "^1.2.1",
|
|
65
65
|
"@spotify/prettier-config": "^15.0.0",
|
|
66
66
|
"@types/express": "4.17.21",
|
|
67
67
|
"@types/knex": "^0.16.1",
|
|
@@ -105,5 +105,12 @@
|
|
|
105
105
|
"*.{json,md}": [
|
|
106
106
|
"prettier --write"
|
|
107
107
|
]
|
|
108
|
+
},
|
|
109
|
+
"typesVersions": {
|
|
110
|
+
"*": {
|
|
111
|
+
"index": [
|
|
112
|
+
"dist/index.d.ts"
|
|
113
|
+
]
|
|
114
|
+
}
|
|
108
115
|
}
|
|
109
116
|
}
|