@backstage/plugin-permission-node 0.6.6-next.0 → 0.7.0-next.2

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 CHANGED
@@ -1,5 +1,55 @@
1
1
  # @backstage/plugin-permission-node
2
2
 
3
+ ## 0.7.0-next.2
4
+
5
+ ### Minor Changes
6
+
7
+ - 46b4a72cee: **BREAKING**: When defining permission rules, it's now necessary to provide a [ZodSchema](https://github.com/colinhacks/zod) that specifies the parameters the rule expects. This has been added to help better describe the parameters in the response of the metadata endpoint and to validate the parameters before a rule is executed.
8
+
9
+ To help with this, we have also made a change to the API of permission rules. Before, the permission rules `toQuery` and `apply` signature expected parameters to be separate arguments, like so...
10
+
11
+ ```ts
12
+ createPermissionRule({
13
+ apply: (resource, foo, bar) => true,
14
+ toQuery: (foo, bar) => {},
15
+ });
16
+ ```
17
+
18
+ The API has now changed to expect the parameters as a single object
19
+
20
+ ```ts
21
+ createPermissionRule({
22
+ paramSchema: z.object({
23
+ foo: z.string().describe('Foo value to match'),
24
+ bar: z.string().describe('Bar value to match'),
25
+ }),
26
+ apply: (resource, { foo, bar }) => true,
27
+ toQuery: ({ foo, bar }) => {},
28
+ });
29
+ ```
30
+
31
+ One final change made is to limit the possible values for a parameter to primitives and arrays of primitives.
32
+
33
+ ### Patch Changes
34
+
35
+ - Updated dependencies
36
+ - @backstage/backend-common@0.15.2-next.2
37
+ - @backstage/plugin-permission-common@0.7.0-next.2
38
+ - @backstage/plugin-auth-node@0.2.6-next.2
39
+ - @backstage/config@1.0.3-next.2
40
+ - @backstage/errors@1.1.2-next.2
41
+
42
+ ## 0.6.6-next.1
43
+
44
+ ### Patch Changes
45
+
46
+ - Updated dependencies
47
+ - @backstage/backend-common@0.15.2-next.1
48
+ - @backstage/config@1.0.3-next.1
49
+ - @backstage/errors@1.1.2-next.1
50
+ - @backstage/plugin-auth-node@0.2.6-next.1
51
+ - @backstage/plugin-permission-common@0.6.5-next.1
52
+
3
53
  ## 0.6.6-next.0
4
54
 
5
55
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -3,22 +3,28 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var pluginPermissionCommon = require('@backstage/plugin-permission-common');
6
+ var errors = require('@backstage/errors');
6
7
  var express = require('express');
7
8
  var Router = require('express-promise-router');
8
9
  var zod = require('zod');
9
- var errors = require('@backstage/errors');
10
+ var zodToJsonSchema = require('zod-to-json-schema');
10
11
  var backendCommon = require('@backstage/backend-common');
11
12
 
12
13
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
14
 
14
15
  var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
15
16
  var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
17
+ var zodToJsonSchema__default = /*#__PURE__*/_interopDefaultLegacy(zodToJsonSchema);
16
18
 
17
- const createConditionFactory = (rule) => (...params) => ({
18
- rule: rule.name,
19
- resourceType: rule.resourceType,
20
- params
21
- });
19
+ const createConditionFactory = (rule) => {
20
+ return (params) => {
21
+ return {
22
+ rule: rule.name,
23
+ resourceType: rule.resourceType,
24
+ params
25
+ };
26
+ };
27
+ };
22
28
 
23
29
  const createConditionExports = (options) => {
24
30
  const { pluginId, resourceType, rules } = options;
@@ -54,6 +60,7 @@ const createGetRule = (rules) => {
54
60
  };
55
61
 
56
62
  const mapConditions = (criteria, getRule) => {
63
+ var _a, _b;
57
64
  if (isAndCriteria(criteria)) {
58
65
  return {
59
66
  allOf: criteria.allOf.map((child) => mapConditions(child, getRule))
@@ -67,7 +74,12 @@ const mapConditions = (criteria, getRule) => {
67
74
  not: mapConditions(criteria.not, getRule)
68
75
  };
69
76
  }
70
- return getRule(criteria.rule).toQuery(...criteria.params);
77
+ const rule = getRule(criteria.rule);
78
+ const result = (_a = rule.paramsSchema) == null ? void 0 : _a.safeParse(criteria.params);
79
+ if (result && !result.success) {
80
+ throw new errors.InputError(`Parameters to rule are invalid`, result.error);
81
+ }
82
+ return rule.toQuery((_b = criteria.params) != null ? _b : {});
71
83
  };
72
84
  const createConditionTransformer = (permissionRules) => {
73
85
  const getRule = createGetRule(permissionRules);
@@ -82,7 +94,7 @@ const permissionCriteriaSchema = zod.z.lazy(
82
94
  zod.z.object({
83
95
  rule: zod.z.string(),
84
96
  resourceType: zod.z.string(),
85
- params: zod.z.array(zod.z.unknown())
97
+ params: zod.z.record(zod.z.any()).optional()
86
98
  })
87
99
  ])
88
100
  );
@@ -97,6 +109,7 @@ const applyConditionsRequestSchema = zod.z.object({
97
109
  )
98
110
  });
99
111
  const applyConditions = (criteria, resource, getRule) => {
112
+ var _a, _b;
100
113
  if (resource === void 0) {
101
114
  return false;
102
115
  }
@@ -111,21 +124,27 @@ const applyConditions = (criteria, resource, getRule) => {
111
124
  } else if (isNotCriteria(criteria)) {
112
125
  return !applyConditions(criteria.not, resource, getRule);
113
126
  }
114
- return getRule(criteria.rule).apply(resource, ...criteria.params);
127
+ const rule = getRule(criteria.rule);
128
+ const result = (_a = rule.paramsSchema) == null ? void 0 : _a.safeParse(criteria.params);
129
+ if (result && !result.success) {
130
+ throw new errors.InputError(`Parameters to rule are invalid`, result.error);
131
+ }
132
+ return rule.apply(resource, (_b = criteria.params) != null ? _b : {});
115
133
  };
116
134
  const createPermissionIntegrationRouter = (options) => {
117
135
  const { resourceType, permissions, rules, getResources } = options;
118
136
  const router = Router__default["default"]();
119
137
  router.use(express__default["default"].json());
120
138
  router.get("/.well-known/backstage/permissions/metadata", (_, res) => {
121
- const serializableRules = rules.map((rule) => ({
122
- name: rule.name,
123
- description: rule.description,
124
- resourceType: rule.resourceType,
125
- parameters: {
126
- count: rule.toQuery.length
127
- }
128
- }));
139
+ const serializableRules = rules.map((rule) => {
140
+ var _a;
141
+ return {
142
+ name: rule.name,
143
+ description: rule.description,
144
+ resourceType: rule.resourceType,
145
+ paramsSchema: zodToJsonSchema__default["default"]((_a = rule.paramsSchema) != null ? _a : zod.z.object({}))
146
+ };
147
+ });
129
148
  return res.json({ permissions, rules: serializableRules });
130
149
  });
131
150
  const getRule = createGetRule(rules);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/integration/createConditionFactory.ts","../src/integration/createConditionExports.ts","../src/integration/util.ts","../src/integration/createConditionTransformer.ts","../src/integration/createPermissionIntegrationRouter.ts","../src/integration/createPermissionRule.ts","../src/ServerPermissionClient.ts"],"sourcesContent":["/*\n * Copyright 2021 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 */\n\nimport { PermissionCondition } from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\n\n/**\n * Creates a condition factory function for a given authorization rule and parameter types.\n *\n * @remarks\n *\n * For example, an isEntityOwner rule for catalog entities might take an array of entityRef strings.\n * The rule itself defines _how_ to check a given resource, whereas a condition also includes _what_\n * to verify.\n *\n * Plugin authors should generally use the {@link createConditionExports} in order to efficiently\n * create multiple condition factories. This helper should generally only be used to construct\n * condition factories for third-party rules that aren't part of the backend plugin with which\n * they're intended to integrate.\n *\n * @public\n */\nexport const createConditionFactory =\n <TResourceType extends string, TParams extends any[]>(\n rule: PermissionRule<unknown, unknown, TResourceType, TParams>,\n ) =>\n (...params: TParams): PermissionCondition<TResourceType, TParams> => ({\n rule: rule.name,\n resourceType: rule.resourceType,\n params,\n });\n","/*\n * Copyright 2021 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 */\n\nimport {\n AuthorizeResult,\n ConditionalPolicyDecision,\n PermissionCondition,\n PermissionCriteria,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\nimport { createConditionFactory } from './createConditionFactory';\n\n/**\n * A utility type for mapping a single {@link PermissionRule} to its\n * corresponding {@link @backstage/plugin-permission-common#PermissionCondition}.\n *\n * @public\n */\nexport type Condition<TRule> = TRule extends PermissionRule<\n any,\n any,\n infer TResourceType,\n infer TParams\n>\n ? (...params: TParams) => PermissionCondition<TResourceType, TParams>\n : never;\n\n/**\n * A utility type for mapping {@link PermissionRule}s to their corresponding\n * {@link @backstage/plugin-permission-common#PermissionCondition}s.\n *\n * @public\n */\nexport type Conditions<\n TRules extends Record<string, PermissionRule<any, any, any>>,\n> = {\n [Name in keyof TRules]: Condition<TRules[Name]>;\n};\n\n/**\n * Creates the recommended condition-related exports for a given plugin based on\n * the built-in {@link PermissionRule}s it supports.\n *\n * @remarks\n *\n * The function returns a `conditions` object containing a\n * {@link @backstage/plugin-permission-common#PermissionCondition} factory for\n * each of the supplied {@link PermissionRule}s, along with a\n * `createConditionalDecision` function which builds the wrapper object needed\n * to enclose conditions when authoring {@link PermissionPolicy}\n * implementations.\n *\n * Plugin authors should generally call this method with all the built-in\n * {@link PermissionRule}s the plugin supports, and export the resulting\n * `conditions` object and `createConditionalDecision` function so that they can\n * be used by {@link PermissionPolicy} authors.\n *\n * @public\n */\nexport const createConditionExports = <\n TResourceType extends string,\n TResource,\n TRules extends Record<string, PermissionRule<TResource, any, TResourceType>>,\n>(options: {\n pluginId: string;\n resourceType: TResourceType;\n rules: TRules;\n}): {\n conditions: Conditions<TRules>;\n createConditionalDecision: (\n permission: ResourcePermission<TResourceType>,\n conditions: PermissionCriteria<PermissionCondition<TResourceType>>,\n ) => ConditionalPolicyDecision;\n} => {\n const { pluginId, resourceType, rules } = options;\n\n return {\n conditions: Object.entries(rules).reduce(\n (acc, [key, rule]) => ({\n ...acc,\n [key]: createConditionFactory(rule),\n }),\n {} as Conditions<TRules>,\n ),\n createConditionalDecision: (\n _permission: ResourcePermission<TResourceType>,\n conditions: PermissionCriteria<PermissionCondition>,\n ) => ({\n result: AuthorizeResult.CONDITIONAL,\n pluginId,\n resourceType,\n conditions,\n }),\n };\n};\n","/*\n * Copyright 2021 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 */\n\nimport {\n AllOfCriteria,\n AnyOfCriteria,\n NotCriteria,\n PermissionCriteria,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\n\n/**\n * Utility function used to parse a PermissionCriteria\n * @param criteria - a PermissionCriteria\n * @alpha\n *\n * @returns `true` if the permission criteria is of type allOf,\n * narrowing down `criteria` to the specific type.\n */\nexport const isAndCriteria = <T>(\n criteria: PermissionCriteria<T>,\n): criteria is AllOfCriteria<T> =>\n Object.prototype.hasOwnProperty.call(criteria, 'allOf');\n\n/**\n * Utility function used to parse a PermissionCriteria of type\n * @param criteria - a PermissionCriteria\n * @alpha\n *\n * @returns `true` if the permission criteria is of type anyOf,\n * narrowing down `criteria` to the specific type.\n */\nexport const isOrCriteria = <T>(\n criteria: PermissionCriteria<T>,\n): criteria is AnyOfCriteria<T> =>\n Object.prototype.hasOwnProperty.call(criteria, 'anyOf');\n\n/**\n * Utility function used to parse a PermissionCriteria\n * @param criteria - a PermissionCriteria\n * @alpha\n *\n * @returns `true` if the permission criteria is of type not,\n * narrowing down `criteria` to the specific type.\n */\nexport const isNotCriteria = <T>(\n criteria: PermissionCriteria<T>,\n): criteria is NotCriteria<T> =>\n Object.prototype.hasOwnProperty.call(criteria, 'not');\n\nexport const createGetRule = <TResource, TQuery>(\n rules: PermissionRule<TResource, TQuery, string>[],\n) => {\n const rulesMap = new Map(Object.values(rules).map(rule => [rule.name, rule]));\n\n return (name: string): PermissionRule<TResource, TQuery, string> => {\n const rule = rulesMap.get(name);\n\n if (!rule) {\n throw new Error(`Unexpected permission rule: ${name}`);\n }\n\n return rule;\n };\n};\n","/*\n * Copyright 2021 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 {\n AllOfCriteria,\n AnyOfCriteria,\n PermissionCondition,\n PermissionCriteria,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\nimport {\n createGetRule,\n isAndCriteria,\n isNotCriteria,\n isOrCriteria,\n} from './util';\n\nconst mapConditions = <TQuery>(\n criteria: PermissionCriteria<PermissionCondition>,\n getRule: (name: string) => PermissionRule<unknown, TQuery, string>,\n): PermissionCriteria<TQuery> => {\n if (isAndCriteria(criteria)) {\n return {\n allOf: criteria.allOf.map(child => mapConditions(child, getRule)),\n } as AllOfCriteria<TQuery>;\n } else if (isOrCriteria(criteria)) {\n return {\n anyOf: criteria.anyOf.map(child => mapConditions(child, getRule)),\n } as AnyOfCriteria<TQuery>;\n } else if (isNotCriteria(criteria)) {\n return {\n not: mapConditions(criteria.not, getRule),\n };\n }\n\n return getRule(criteria.rule).toQuery(...criteria.params);\n};\n\n/**\n * A function which accepts {@link @backstage/plugin-permission-common#PermissionCondition}s\n * logically grouped in a {@link @backstage/plugin-permission-common#PermissionCriteria}\n * object, and transforms the {@link @backstage/plugin-permission-common#PermissionCondition}s\n * into plugin specific query fragments while retaining the enclosing criteria shape.\n *\n * @public\n */\nexport type ConditionTransformer<TQuery> = (\n conditions: PermissionCriteria<PermissionCondition>,\n) => PermissionCriteria<TQuery>;\n\n/**\n * A higher-order helper function which accepts an array of\n * {@link PermissionRule}s, and returns a {@link ConditionTransformer}\n * which transforms input conditions into equivalent plugin-specific\n * query fragments using the supplied rules.\n *\n * @public\n */\nexport const createConditionTransformer = <\n TQuery,\n TRules extends PermissionRule<any, TQuery, string>[],\n>(\n permissionRules: [...TRules],\n): ConditionTransformer<TQuery> => {\n const getRule = createGetRule(permissionRules);\n\n return conditions => mapConditions(conditions, getRule);\n};\n","/*\n * Copyright 2021 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 */\n\nimport express, { Response } from 'express';\nimport Router from 'express-promise-router';\nimport { z } from 'zod';\nimport { InputError } from '@backstage/errors';\nimport { errorHandler } from '@backstage/backend-common';\nimport {\n AuthorizeResult,\n DefinitivePolicyDecision,\n IdentifiedPermissionMessage,\n Permission,\n PermissionCondition,\n PermissionCriteria,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\nimport {\n createGetRule,\n isAndCriteria,\n isNotCriteria,\n isOrCriteria,\n} from './util';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z.union([\n z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }),\n z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }),\n z.object({ not: permissionCriteriaSchema }),\n z.object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.array(z.unknown()),\n }),\n ]),\n);\n\nconst applyConditionsRequestSchema = z.object({\n items: z.array(\n z.object({\n id: z.string(),\n resourceRef: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ),\n});\n\n/**\n * A request to load the referenced resource and apply conditions in order to\n * finalize a conditional authorization response.\n *\n * @public\n */\nexport type ApplyConditionsRequestEntry = IdentifiedPermissionMessage<{\n resourceRef: string;\n resourceType: string;\n conditions: PermissionCriteria<PermissionCondition>;\n}>;\n\n/**\n * A batch of {@link ApplyConditionsRequestEntry} objects.\n *\n * @public\n */\nexport type ApplyConditionsRequest = {\n items: ApplyConditionsRequestEntry[];\n};\n\n/**\n * The result of applying the conditions, expressed as a definitive authorize\n * result of ALLOW or DENY.\n *\n * @public\n */\nexport type ApplyConditionsResponseEntry =\n IdentifiedPermissionMessage<DefinitivePolicyDecision>;\n\n/**\n * A batch of {@link ApplyConditionsResponseEntry} objects.\n *\n * @public\n */\nexport type ApplyConditionsResponse = {\n items: ApplyConditionsResponseEntry[];\n};\n\nconst applyConditions = <TResourceType extends string, TResource>(\n criteria: PermissionCriteria<PermissionCondition<TResourceType>>,\n resource: TResource | undefined,\n getRule: (name: string) => PermissionRule<TResource, unknown, TResourceType>,\n): boolean => {\n // If resource was not found, deny. This avoids leaking information from the\n // apply-conditions API which would allow a user to differentiate between\n // non-existent resources and resources to which they do not have access.\n if (resource === undefined) {\n return false;\n }\n\n if (isAndCriteria(criteria)) {\n return criteria.allOf.every(child =>\n applyConditions(child, resource, getRule),\n );\n } else if (isOrCriteria(criteria)) {\n return criteria.anyOf.some(child =>\n applyConditions(child, resource, getRule),\n );\n } else if (isNotCriteria(criteria)) {\n return !applyConditions(criteria.not, resource, getRule);\n }\n\n return getRule(criteria.rule).apply(resource, ...criteria.params);\n};\n\n/**\n * Prevent use of type parameter from contributing to type inference.\n *\n * https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795\n * @ignore\n */\ntype NoInfer<T> = T extends infer S ? S : never;\n\n/**\n * Create an express Router which provides an authorization route to allow\n * integration between the permission backend and other Backstage backend\n * plugins. Plugin owners that wish to support conditional authorization for\n * their resources should add the router created by this function to their\n * express app inside their `createRouter` implementation.\n *\n * @remarks\n *\n * To make this concrete, we can use the Backstage software catalog as an\n * example. The catalog has conditional rules around access to specific\n * _entities_ in the catalog. The _type_ of resource is captured here as\n * `resourceType`, a string identifier (`catalog-entity` in this example) that\n * can be provided with permission definitions. This is merely a _type_ to\n * verify that conditions in an authorization policy are constructed correctly,\n * not a reference to a specific resource.\n *\n * The `rules` parameter is an array of {@link PermissionRule}s that introduce\n * conditional filtering logic for resources; for the catalog, these are things\n * like `isEntityOwner` or `hasAnnotation`. Rules describe how to filter a list\n * of resources, and the `conditions` returned allow these rules to be applied\n * with specific parameters (such as 'group:default/team-a', or\n * 'backstage.io/edit-url').\n *\n * The `getResources` argument should load resources based on a reference\n * identifier. For the catalog, this is an\n * {@link @backstage/catalog-model#EntityRef}. For other plugins, this can be\n * any serialized format. This is used to construct the\n * `createPermissionIntegrationRouter`, a function to add an authorization route\n * to your backend plugin. This function will be called by the\n * `permission-backend` when authorization conditions relating to this plugin\n * need to be evaluated.\n *\n * @public\n */\nexport const createPermissionIntegrationRouter = <\n TResourceType extends string,\n TResource,\n>(options: {\n resourceType: TResourceType;\n permissions?: Array<Permission>;\n // Do not infer value of TResourceType from supplied rules.\n // instead only consider the resourceType parameter, and\n // consider any rules whose resource type does not match\n // to be an error.\n rules: PermissionRule<TResource, any, NoInfer<TResourceType>>[];\n getResources: (\n resourceRefs: string[],\n ) => Promise<Array<TResource | undefined>>;\n}): express.Router => {\n const { resourceType, permissions, rules, getResources } = options;\n const router = Router();\n router.use(express.json());\n\n router.get('/.well-known/backstage/permissions/metadata', (_, res) => {\n const serializableRules = rules.map(rule => ({\n name: rule.name,\n description: rule.description,\n resourceType: rule.resourceType,\n parameters: {\n count: rule.toQuery.length,\n },\n }));\n\n return res.json({ permissions, rules: serializableRules });\n });\n\n const getRule = createGetRule(rules);\n\n const assertValidResourceTypes = (\n requests: ApplyConditionsRequestEntry[],\n ) => {\n const invalidResourceTypes = requests\n .filter(request => request.resourceType !== resourceType)\n .map(request => request.resourceType);\n\n if (invalidResourceTypes.length) {\n throw new InputError(\n `Unexpected resource types: ${invalidResourceTypes.join(', ')}.`,\n );\n }\n };\n\n router.post(\n '/.well-known/backstage/permissions/apply-conditions',\n async (req, res: Response<ApplyConditionsResponse | string>) => {\n const parseResult = applyConditionsRequestSchema.safeParse(req.body);\n\n if (!parseResult.success) {\n throw new InputError(parseResult.error.toString());\n }\n\n const body = parseResult.data;\n\n assertValidResourceTypes(body.items);\n\n const resourceRefs = Array.from(\n new Set(body.items.map(({ resourceRef }) => resourceRef)),\n );\n const resourceArray = await getResources(resourceRefs);\n const resources = resourceRefs.reduce((acc, resourceRef, index) => {\n acc[resourceRef] = resourceArray[index];\n\n return acc;\n }, {} as Record<string, TResource | undefined>);\n\n return res.json({\n items: body.items.map(request => ({\n id: request.id,\n result: applyConditions(\n request.conditions,\n resources[request.resourceRef],\n getRule,\n )\n ? AuthorizeResult.ALLOW\n : AuthorizeResult.DENY,\n })),\n });\n },\n );\n\n router.use(errorHandler());\n\n return router;\n};\n","/*\n * Copyright 2022 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 */\n\nimport { PermissionRule } from '../types';\n\n/**\n * Helper function to ensure that {@link PermissionRule} definitions are typed correctly.\n *\n * @public\n */\nexport const createPermissionRule = <\n TResource,\n TQuery,\n TResourceType extends string,\n TParams extends unknown[],\n>(\n rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,\n) => rule;\n\n/**\n * Helper for making plugin-specific createPermissionRule functions, that have\n * the TResource and TQuery type parameters populated but infer the params from\n * the supplied rule. This helps ensure that rules created for this plugin use\n * consistent types for the resource and query.\n *\n * @public\n */\nexport const makeCreatePermissionRule =\n <TResource, TQuery, TResourceType extends string>() =>\n <TParams extends unknown[]>(\n rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,\n ) =>\n createPermissionRule(rule);\n","/*\n * Copyright 2021 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 */\n\nimport {\n TokenManager,\n PluginEndpointDiscovery,\n} from '@backstage/backend-common';\nimport { Config } from '@backstage/config';\nimport {\n AuthorizeResult,\n PermissionClient,\n PermissionEvaluator,\n AuthorizePermissionRequest,\n EvaluatorRequestOptions,\n AuthorizePermissionResponse,\n PolicyDecision,\n QueryPermissionRequest,\n} from '@backstage/plugin-permission-common';\n\n/**\n * A thin wrapper around\n * {@link @backstage/plugin-permission-common#PermissionClient} that allows all\n * backend-to-backend requests.\n * @public\n */\nexport class ServerPermissionClient implements PermissionEvaluator {\n private readonly permissionClient: PermissionClient;\n private readonly tokenManager: TokenManager;\n private readonly permissionEnabled: boolean;\n\n static fromConfig(\n config: Config,\n options: {\n discovery: PluginEndpointDiscovery;\n tokenManager: TokenManager;\n },\n ) {\n const { discovery, tokenManager } = options;\n const permissionClient = new PermissionClient({ discovery, config });\n const permissionEnabled =\n config.getOptionalBoolean('permission.enabled') ?? false;\n\n if (\n permissionEnabled &&\n (tokenManager as any).isInsecureServerTokenManager\n ) {\n throw new Error(\n 'Backend-to-backend authentication must be configured before enabling permissions. Read more here https://backstage.io/docs/tutorials/backend-to-backend-auth',\n );\n }\n\n return new ServerPermissionClient({\n permissionClient,\n tokenManager,\n permissionEnabled,\n });\n }\n\n private constructor(options: {\n permissionClient: PermissionClient;\n tokenManager: TokenManager;\n permissionEnabled: boolean;\n }) {\n this.permissionClient = options.permissionClient;\n this.tokenManager = options.tokenManager;\n this.permissionEnabled = options.permissionEnabled;\n }\n\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: EvaluatorRequestOptions,\n ): Promise<PolicyDecision[]> {\n return (await this.isEnabled(options?.token))\n ? this.permissionClient.authorizeConditional(queries, options)\n : queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: EvaluatorRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n return (await this.isEnabled(options?.token))\n ? this.permissionClient.authorize(requests, options)\n : requests.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n private async isValidServerToken(\n token: string | undefined,\n ): Promise<boolean> {\n if (!token) {\n return false;\n }\n return this.tokenManager\n .authenticate(token)\n .then(() => true)\n .catch(() => false);\n }\n\n private async isEnabled(token?: string) {\n // Check if permissions are enabled before validating the server token. That\n // way when permissions are disabled, the noop token manager can be used\n // without fouling up the logic inside the ServerPermissionClient, because\n // the code path won't be reached.\n return this.permissionEnabled && !(await this.isValidServerToken(token));\n }\n}\n"],"names":["AuthorizeResult","z","Router","express","InputError","errorHandler","PermissionClient"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/integration/createConditionFactory.ts","../src/integration/createConditionExports.ts","../src/integration/util.ts","../src/integration/createConditionTransformer.ts","../src/integration/createPermissionIntegrationRouter.ts","../src/integration/createPermissionRule.ts","../src/ServerPermissionClient.ts"],"sourcesContent":["/*\n * Copyright 2021 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 */\n\nimport {\n PermissionCondition,\n PermissionRuleParams,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\n\n/**\n * Creates a condition factory function for a given authorization rule and parameter types.\n *\n * @remarks\n *\n * For example, an isEntityOwner rule for catalog entities might take an array of entityRef strings.\n * The rule itself defines _how_ to check a given resource, whereas a condition also includes _what_\n * to verify.\n *\n * Plugin authors should generally use the {@link createConditionExports} in order to efficiently\n * create multiple condition factories. This helper should generally only be used to construct\n * condition factories for third-party rules that aren't part of the backend plugin with which\n * they're intended to integrate.\n *\n * @public\n */\nexport const createConditionFactory = <\n TResourceType extends string,\n TParams extends PermissionRuleParams = PermissionRuleParams,\n>(\n rule: PermissionRule<unknown, unknown, TResourceType, TParams>,\n) => {\n return (params: TParams): PermissionCondition<TResourceType, TParams> => {\n return {\n rule: rule.name,\n resourceType: rule.resourceType,\n params,\n };\n };\n};\n","/*\n * Copyright 2021 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 */\n\nimport {\n AuthorizeResult,\n ConditionalPolicyDecision,\n PermissionCondition,\n PermissionCriteria,\n ResourcePermission,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\nimport { createConditionFactory } from './createConditionFactory';\n\n/**\n * A utility type for mapping a single {@link PermissionRule} to its\n * corresponding {@link @backstage/plugin-permission-common#PermissionCondition}.\n *\n * @public\n */\nexport type Condition<TRule> = TRule extends PermissionRule<\n any,\n any,\n infer TResourceType,\n infer TParams\n>\n ? undefined extends TParams\n ? () => PermissionCondition<TResourceType, TParams>\n : (params: TParams) => PermissionCondition<TResourceType, TParams>\n : never;\n\n/**\n * A utility type for mapping {@link PermissionRule}s to their corresponding\n * {@link @backstage/plugin-permission-common#PermissionCondition}s.\n *\n * @public\n */\nexport type Conditions<\n TRules extends Record<string, PermissionRule<any, any, any>>,\n> = {\n [Name in keyof TRules]: Condition<TRules[Name]>;\n};\n\n/**\n * Creates the recommended condition-related exports for a given plugin based on\n * the built-in {@link PermissionRule}s it supports.\n *\n * @remarks\n *\n * The function returns a `conditions` object containing a\n * {@link @backstage/plugin-permission-common#PermissionCondition} factory for\n * each of the supplied {@link PermissionRule}s, along with a\n * `createConditionalDecision` function which builds the wrapper object needed\n * to enclose conditions when authoring {@link PermissionPolicy}\n * implementations.\n *\n * Plugin authors should generally call this method with all the built-in\n * {@link PermissionRule}s the plugin supports, and export the resulting\n * `conditions` object and `createConditionalDecision` function so that they can\n * be used by {@link PermissionPolicy} authors.\n *\n * @public\n */\nexport const createConditionExports = <\n TResourceType extends string,\n TResource,\n TRules extends Record<string, PermissionRule<TResource, any, TResourceType>>,\n>(options: {\n pluginId: string;\n resourceType: TResourceType;\n rules: TRules;\n}): {\n conditions: Conditions<TRules>;\n createConditionalDecision: (\n permission: ResourcePermission<TResourceType>,\n conditions: PermissionCriteria<PermissionCondition<TResourceType>>,\n ) => ConditionalPolicyDecision;\n} => {\n const { pluginId, resourceType, rules } = options;\n\n return {\n conditions: Object.entries(rules).reduce(\n (acc, [key, rule]) => ({\n ...acc,\n [key]: createConditionFactory(rule),\n }),\n {} as Conditions<TRules>,\n ),\n createConditionalDecision: (\n _permission: ResourcePermission<TResourceType>,\n conditions: PermissionCriteria<PermissionCondition>,\n ) => ({\n result: AuthorizeResult.CONDITIONAL,\n pluginId,\n resourceType,\n conditions,\n }),\n };\n};\n","/*\n * Copyright 2021 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 */\n\nimport {\n AllOfCriteria,\n AnyOfCriteria,\n NotCriteria,\n PermissionCriteria,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\n\n/**\n * Prevent use of type parameter from contributing to type inference.\n *\n * https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795\n * @ignore\n */\nexport type NoInfer<T> = T extends infer S ? S : never;\n\n/**\n * Utility function used to parse a PermissionCriteria\n * @param criteria - a PermissionCriteria\n * @alpha\n *\n * @returns `true` if the permission criteria is of type allOf,\n * narrowing down `criteria` to the specific type.\n */\nexport const isAndCriteria = <T>(\n criteria: PermissionCriteria<T>,\n): criteria is AllOfCriteria<T> =>\n Object.prototype.hasOwnProperty.call(criteria, 'allOf');\n\n/**\n * Utility function used to parse a PermissionCriteria of type\n * @param criteria - a PermissionCriteria\n * @alpha\n *\n * @returns `true` if the permission criteria is of type anyOf,\n * narrowing down `criteria` to the specific type.\n */\nexport const isOrCriteria = <T>(\n criteria: PermissionCriteria<T>,\n): criteria is AnyOfCriteria<T> =>\n Object.prototype.hasOwnProperty.call(criteria, 'anyOf');\n\n/**\n * Utility function used to parse a PermissionCriteria\n * @param criteria - a PermissionCriteria\n * @alpha\n *\n * @returns `true` if the permission criteria is of type not,\n * narrowing down `criteria` to the specific type.\n */\nexport const isNotCriteria = <T>(\n criteria: PermissionCriteria<T>,\n): criteria is NotCriteria<T> =>\n Object.prototype.hasOwnProperty.call(criteria, 'not');\n\nexport const createGetRule = <TResource, TQuery>(\n rules: PermissionRule<TResource, TQuery, string>[],\n) => {\n const rulesMap = new Map(Object.values(rules).map(rule => [rule.name, rule]));\n\n return (name: string): PermissionRule<TResource, TQuery, string> => {\n const rule = rulesMap.get(name);\n\n if (!rule) {\n throw new Error(`Unexpected permission rule: ${name}`);\n }\n\n return rule;\n };\n};\n","/*\n * Copyright 2021 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 { InputError } from '@backstage/errors';\nimport {\n AllOfCriteria,\n AnyOfCriteria,\n PermissionCondition,\n PermissionCriteria,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\nimport {\n createGetRule,\n isAndCriteria,\n isNotCriteria,\n isOrCriteria,\n} from './util';\n\nconst mapConditions = <TQuery>(\n criteria: PermissionCriteria<PermissionCondition>,\n getRule: (name: string) => PermissionRule<unknown, TQuery, string>,\n): PermissionCriteria<TQuery> => {\n if (isAndCriteria(criteria)) {\n return {\n allOf: criteria.allOf.map(child => mapConditions(child, getRule)),\n } as AllOfCriteria<TQuery>;\n } else if (isOrCriteria(criteria)) {\n return {\n anyOf: criteria.anyOf.map(child => mapConditions(child, getRule)),\n } as AnyOfCriteria<TQuery>;\n } else if (isNotCriteria(criteria)) {\n return {\n not: mapConditions(criteria.not, getRule),\n };\n }\n\n const rule = getRule(criteria.rule);\n const result = rule.paramsSchema?.safeParse(criteria.params);\n\n if (result && !result.success) {\n throw new InputError(`Parameters to rule are invalid`, result.error);\n }\n\n return rule.toQuery(criteria.params ?? {});\n};\n\n/**\n * A function which accepts {@link @backstage/plugin-permission-common#PermissionCondition}s\n * logically grouped in a {@link @backstage/plugin-permission-common#PermissionCriteria}\n * object, and transforms the {@link @backstage/plugin-permission-common#PermissionCondition}s\n * into plugin specific query fragments while retaining the enclosing criteria shape.\n *\n * @public\n */\nexport type ConditionTransformer<TQuery> = (\n conditions: PermissionCriteria<PermissionCondition>,\n) => PermissionCriteria<TQuery>;\n\n/**\n * A higher-order helper function which accepts an array of\n * {@link PermissionRule}s, and returns a {@link ConditionTransformer}\n * which transforms input conditions into equivalent plugin-specific\n * query fragments using the supplied rules.\n *\n * @public\n */\nexport const createConditionTransformer = <\n TQuery,\n TRules extends PermissionRule<any, TQuery, string>[],\n>(\n permissionRules: [...TRules],\n): ConditionTransformer<TQuery> => {\n const getRule = createGetRule(permissionRules);\n\n return conditions => mapConditions(conditions, getRule);\n};\n","/*\n * Copyright 2021 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 */\n\nimport express, { Response } from 'express';\nimport Router from 'express-promise-router';\nimport { z } from 'zod';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport { InputError } from '@backstage/errors';\nimport { errorHandler } from '@backstage/backend-common';\nimport {\n AuthorizeResult,\n DefinitivePolicyDecision,\n IdentifiedPermissionMessage,\n Permission,\n PermissionCondition,\n PermissionCriteria,\n} from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\nimport {\n NoInfer,\n createGetRule,\n isAndCriteria,\n isNotCriteria,\n isOrCriteria,\n} from './util';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z.union([\n z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }),\n z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }),\n z.object({ not: permissionCriteriaSchema }),\n z.object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.record(z.any()).optional(),\n }),\n ]),\n);\n\nconst applyConditionsRequestSchema = z.object({\n items: z.array(\n z.object({\n id: z.string(),\n resourceRef: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ),\n});\n\n/**\n * A request to load the referenced resource and apply conditions in order to\n * finalize a conditional authorization response.\n *\n * @public\n */\nexport type ApplyConditionsRequestEntry = IdentifiedPermissionMessage<{\n resourceRef: string;\n resourceType: string;\n conditions: PermissionCriteria<PermissionCondition>;\n}>;\n\n/**\n * A batch of {@link ApplyConditionsRequestEntry} objects.\n *\n * @public\n */\nexport type ApplyConditionsRequest = {\n items: ApplyConditionsRequestEntry[];\n};\n\n/**\n * The result of applying the conditions, expressed as a definitive authorize\n * result of ALLOW or DENY.\n *\n * @public\n */\nexport type ApplyConditionsResponseEntry =\n IdentifiedPermissionMessage<DefinitivePolicyDecision>;\n\n/**\n * A batch of {@link ApplyConditionsResponseEntry} objects.\n *\n * @public\n */\nexport type ApplyConditionsResponse = {\n items: ApplyConditionsResponseEntry[];\n};\n\nconst applyConditions = <TResourceType extends string, TResource>(\n criteria: PermissionCriteria<PermissionCondition<TResourceType>>,\n resource: TResource | undefined,\n getRule: (name: string) => PermissionRule<TResource, unknown, TResourceType>,\n): boolean => {\n // If resource was not found, deny. This avoids leaking information from the\n // apply-conditions API which would allow a user to differentiate between\n // non-existent resources and resources to which they do not have access.\n if (resource === undefined) {\n return false;\n }\n\n if (isAndCriteria(criteria)) {\n return criteria.allOf.every(child =>\n applyConditions(child, resource, getRule),\n );\n } else if (isOrCriteria(criteria)) {\n return criteria.anyOf.some(child =>\n applyConditions(child, resource, getRule),\n );\n } else if (isNotCriteria(criteria)) {\n return !applyConditions(criteria.not, resource, getRule);\n }\n\n const rule = getRule(criteria.rule);\n const result = rule.paramsSchema?.safeParse(criteria.params);\n\n if (result && !result.success) {\n throw new InputError(`Parameters to rule are invalid`, result.error);\n }\n\n return rule.apply(resource, criteria.params ?? {});\n};\n\n/**\n * Create an express Router which provides an authorization route to allow\n * integration between the permission backend and other Backstage backend\n * plugins. Plugin owners that wish to support conditional authorization for\n * their resources should add the router created by this function to their\n * express app inside their `createRouter` implementation.\n *\n * @remarks\n *\n * To make this concrete, we can use the Backstage software catalog as an\n * example. The catalog has conditional rules around access to specific\n * _entities_ in the catalog. The _type_ of resource is captured here as\n * `resourceType`, a string identifier (`catalog-entity` in this example) that\n * can be provided with permission definitions. This is merely a _type_ to\n * verify that conditions in an authorization policy are constructed correctly,\n * not a reference to a specific resource.\n *\n * The `rules` parameter is an array of {@link PermissionRule}s that introduce\n * conditional filtering logic for resources; for the catalog, these are things\n * like `isEntityOwner` or `hasAnnotation`. Rules describe how to filter a list\n * of resources, and the `conditions` returned allow these rules to be applied\n * with specific parameters (such as 'group:default/team-a', or\n * 'backstage.io/edit-url').\n *\n * The `getResources` argument should load resources based on a reference\n * identifier. For the catalog, this is an\n * {@link @backstage/catalog-model#EntityRef}. For other plugins, this can be\n * any serialized format. This is used to construct the\n * `createPermissionIntegrationRouter`, a function to add an authorization route\n * to your backend plugin. This function will be called by the\n * `permission-backend` when authorization conditions relating to this plugin\n * need to be evaluated.\n *\n * @public\n */\nexport const createPermissionIntegrationRouter = <\n TResourceType extends string,\n TResource,\n>(options: {\n resourceType: TResourceType;\n permissions?: Array<Permission>;\n // Do not infer value of TResourceType from supplied rules.\n // instead only consider the resourceType parameter, and\n // consider any rules whose resource type does not match\n // to be an error.\n rules: PermissionRule<TResource, any, NoInfer<TResourceType>>[];\n getResources: (\n resourceRefs: string[],\n ) => Promise<Array<TResource | undefined>>;\n}): express.Router => {\n const { resourceType, permissions, rules, getResources } = options;\n const router = Router();\n router.use(express.json());\n\n router.get('/.well-known/backstage/permissions/metadata', (_, res) => {\n const serializableRules = rules.map(rule => ({\n name: rule.name,\n description: rule.description,\n resourceType: rule.resourceType,\n paramsSchema: zodToJsonSchema(rule.paramsSchema ?? z.object({})),\n }));\n\n return res.json({ permissions, rules: serializableRules });\n });\n\n const getRule = createGetRule(rules);\n\n const assertValidResourceTypes = (\n requests: ApplyConditionsRequestEntry[],\n ) => {\n const invalidResourceTypes = requests\n .filter(request => request.resourceType !== resourceType)\n .map(request => request.resourceType);\n\n if (invalidResourceTypes.length) {\n throw new InputError(\n `Unexpected resource types: ${invalidResourceTypes.join(', ')}.`,\n );\n }\n };\n\n router.post(\n '/.well-known/backstage/permissions/apply-conditions',\n async (req, res: Response<ApplyConditionsResponse | string>) => {\n const parseResult = applyConditionsRequestSchema.safeParse(req.body);\n\n if (!parseResult.success) {\n throw new InputError(parseResult.error.toString());\n }\n\n const body = parseResult.data;\n\n assertValidResourceTypes(body.items);\n\n const resourceRefs = Array.from(\n new Set(body.items.map(({ resourceRef }) => resourceRef)),\n );\n const resourceArray = await getResources(resourceRefs);\n const resources = resourceRefs.reduce((acc, resourceRef, index) => {\n acc[resourceRef] = resourceArray[index];\n\n return acc;\n }, {} as Record<string, TResource | undefined>);\n\n return res.json({\n items: body.items.map(request => ({\n id: request.id,\n result: applyConditions(\n request.conditions,\n resources[request.resourceRef],\n getRule,\n )\n ? AuthorizeResult.ALLOW\n : AuthorizeResult.DENY,\n })),\n });\n },\n );\n\n router.use(errorHandler());\n\n return router;\n};\n","/*\n * Copyright 2022 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 */\n\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport { PermissionRule } from '../types';\n\n/**\n * Helper function to ensure that {@link PermissionRule} definitions are typed correctly.\n *\n * @public\n */\nexport const createPermissionRule = <\n TResource,\n TQuery,\n TResourceType extends string,\n TParams extends PermissionRuleParams = undefined,\n>(\n rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,\n) => rule;\n\n/**\n * Helper for making plugin-specific createPermissionRule functions, that have\n * the TResource and TQuery type parameters populated but infer the params from\n * the supplied rule. This helps ensure that rules created for this plugin use\n * consistent types for the resource and query.\n *\n * @public\n */\nexport const makeCreatePermissionRule =\n <TResource, TQuery, TResourceType extends string>() =>\n <TParams extends PermissionRuleParams = undefined>(\n rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,\n ) =>\n createPermissionRule(rule);\n","/*\n * Copyright 2021 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 */\n\nimport {\n TokenManager,\n PluginEndpointDiscovery,\n} from '@backstage/backend-common';\nimport { Config } from '@backstage/config';\nimport {\n AuthorizeResult,\n PermissionClient,\n PermissionEvaluator,\n AuthorizePermissionRequest,\n EvaluatorRequestOptions,\n AuthorizePermissionResponse,\n PolicyDecision,\n QueryPermissionRequest,\n} from '@backstage/plugin-permission-common';\n\n/**\n * A thin wrapper around\n * {@link @backstage/plugin-permission-common#PermissionClient} that allows all\n * backend-to-backend requests.\n * @public\n */\nexport class ServerPermissionClient implements PermissionEvaluator {\n private readonly permissionClient: PermissionClient;\n private readonly tokenManager: TokenManager;\n private readonly permissionEnabled: boolean;\n\n static fromConfig(\n config: Config,\n options: {\n discovery: PluginEndpointDiscovery;\n tokenManager: TokenManager;\n },\n ) {\n const { discovery, tokenManager } = options;\n const permissionClient = new PermissionClient({ discovery, config });\n const permissionEnabled =\n config.getOptionalBoolean('permission.enabled') ?? false;\n\n if (\n permissionEnabled &&\n (tokenManager as any).isInsecureServerTokenManager\n ) {\n throw new Error(\n 'Backend-to-backend authentication must be configured before enabling permissions. Read more here https://backstage.io/docs/tutorials/backend-to-backend-auth',\n );\n }\n\n return new ServerPermissionClient({\n permissionClient,\n tokenManager,\n permissionEnabled,\n });\n }\n\n private constructor(options: {\n permissionClient: PermissionClient;\n tokenManager: TokenManager;\n permissionEnabled: boolean;\n }) {\n this.permissionClient = options.permissionClient;\n this.tokenManager = options.tokenManager;\n this.permissionEnabled = options.permissionEnabled;\n }\n\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: EvaluatorRequestOptions,\n ): Promise<PolicyDecision[]> {\n return (await this.isEnabled(options?.token))\n ? this.permissionClient.authorizeConditional(queries, options)\n : queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: EvaluatorRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n return (await this.isEnabled(options?.token))\n ? this.permissionClient.authorize(requests, options)\n : requests.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n private async isValidServerToken(\n token: string | undefined,\n ): Promise<boolean> {\n if (!token) {\n return false;\n }\n return this.tokenManager\n .authenticate(token)\n .then(() => true)\n .catch(() => false);\n }\n\n private async isEnabled(token?: string) {\n // Check if permissions are enabled before validating the server token. That\n // way when permissions are disabled, the noop token manager can be used\n // without fouling up the logic inside the ServerPermissionClient, because\n // the code path won't be reached.\n return this.permissionEnabled && !(await this.isValidServerToken(token));\n }\n}\n"],"names":["AuthorizeResult","InputError","z","Router","express","zodToJsonSchema","errorHandler","PermissionClient"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,46 @@
1
- import { PermissionCriteria, PermissionCondition, ResourcePermission, ConditionalPolicyDecision, IdentifiedPermissionMessage, DefinitivePolicyDecision, Permission, AllOfCriteria, AnyOfCriteria, NotCriteria, PolicyDecision, PermissionEvaluator, QueryPermissionRequest, EvaluatorRequestOptions, AuthorizePermissionRequest, AuthorizePermissionResponse } from '@backstage/plugin-permission-common';
1
+ import * as _backstage_plugin_permission_common from '@backstage/plugin-permission-common';
2
+ import { PermissionCriteria, AllOfCriteria, AnyOfCriteria, NotCriteria, PermissionRuleParams, PermissionCondition, ResourcePermission, ConditionalPolicyDecision, IdentifiedPermissionMessage, DefinitivePolicyDecision, Permission, PolicyDecision, PermissionEvaluator, QueryPermissionRequest, EvaluatorRequestOptions, AuthorizePermissionRequest, AuthorizePermissionResponse } from '@backstage/plugin-permission-common';
3
+ import { z } from 'zod';
2
4
  import express from 'express';
3
5
  import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
4
6
  import { PluginEndpointDiscovery, TokenManager } from '@backstage/backend-common';
5
7
  import { Config } from '@backstage/config';
6
8
 
9
+ /**
10
+ * Prevent use of type parameter from contributing to type inference.
11
+ *
12
+ * https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795
13
+ * @ignore
14
+ */
15
+ declare type NoInfer<T> = T extends infer S ? S : never;
16
+ /**
17
+ * Utility function used to parse a PermissionCriteria
18
+ * @param criteria - a PermissionCriteria
19
+ * @alpha
20
+ *
21
+ * @returns `true` if the permission criteria is of type allOf,
22
+ * narrowing down `criteria` to the specific type.
23
+ */
24
+ declare const isAndCriteria: <T>(criteria: PermissionCriteria<T>) => criteria is AllOfCriteria<T>;
25
+ /**
26
+ * Utility function used to parse a PermissionCriteria of type
27
+ * @param criteria - a PermissionCriteria
28
+ * @alpha
29
+ *
30
+ * @returns `true` if the permission criteria is of type anyOf,
31
+ * narrowing down `criteria` to the specific type.
32
+ */
33
+ declare const isOrCriteria: <T>(criteria: PermissionCriteria<T>) => criteria is AnyOfCriteria<T>;
34
+ /**
35
+ * Utility function used to parse a PermissionCriteria
36
+ * @param criteria - a PermissionCriteria
37
+ * @alpha
38
+ *
39
+ * @returns `true` if the permission criteria is of type not,
40
+ * narrowing down `criteria` to the specific type.
41
+ */
42
+ declare const isNotCriteria: <T>(criteria: PermissionCriteria<T>) => criteria is NotCriteria<T>;
43
+
7
44
  /**
8
45
  * A conditional rule that can be provided in an
9
46
  * {@link @backstage/permission-common#AuthorizeDecision} response to an authorization request.
@@ -20,22 +57,26 @@ import { Config } from '@backstage/config';
20
57
  *
21
58
  * @public
22
59
  */
23
- declare type PermissionRule<TResource, TQuery, TResourceType extends string, TParams extends unknown[] = unknown[]> = {
60
+ declare type PermissionRule<TResource, TQuery, TResourceType extends string, TParams extends PermissionRuleParams = PermissionRuleParams> = {
24
61
  name: string;
25
62
  description: string;
26
63
  resourceType: TResourceType;
64
+ /**
65
+ * A ZodSchema that reflects the structure of the parameters that are passed to
66
+ */
67
+ paramsSchema?: z.ZodSchema<TParams>;
27
68
  /**
28
69
  * Apply this rule to a resource already loaded from a backing data source. The params are
29
70
  * arguments supplied for the rule; for example, a rule could be `isOwner` with entityRefs as the
30
71
  * params.
31
72
  */
32
- apply(resource: TResource, ...params: TParams): boolean;
73
+ apply(resource: TResource, params: NoInfer<TParams>): boolean;
33
74
  /**
34
75
  * Translate this rule to criteria suitable for use in querying a backing data store. The criteria
35
76
  * can be used for loading a collection of resources efficiently with conditional criteria already
36
77
  * applied.
37
78
  */
38
- toQuery(...params: TParams): PermissionCriteria<TQuery>;
79
+ toQuery(params: NoInfer<TParams>): PermissionCriteria<TQuery>;
39
80
  };
40
81
 
41
82
  /**
@@ -54,7 +95,7 @@ declare type PermissionRule<TResource, TQuery, TResourceType extends string, TPa
54
95
  *
55
96
  * @public
56
97
  */
57
- declare const createConditionFactory: <TResourceType extends string, TParams extends any[]>(rule: PermissionRule<unknown, unknown, TResourceType, TParams>) => (...params: TParams) => PermissionCondition<TResourceType, TParams>;
98
+ declare const createConditionFactory: <TResourceType extends string, TParams extends PermissionRuleParams = PermissionRuleParams>(rule: PermissionRule<unknown, unknown, TResourceType, TParams>) => (params: TParams) => PermissionCondition<TResourceType, TParams>;
58
99
 
59
100
  /**
60
101
  * A utility type for mapping a single {@link PermissionRule} to its
@@ -62,7 +103,7 @@ declare const createConditionFactory: <TResourceType extends string, TParams ext
62
103
  *
63
104
  * @public
64
105
  */
65
- declare type Condition<TRule> = TRule extends PermissionRule<any, any, infer TResourceType, infer TParams> ? (...params: TParams) => PermissionCondition<TResourceType, TParams> : never;
106
+ declare type Condition<TRule> = TRule extends PermissionRule<any, any, infer TResourceType, infer TParams> ? undefined extends TParams ? () => PermissionCondition<TResourceType, TParams> : (params: TParams) => PermissionCondition<TResourceType, TParams> : never;
66
107
  /**
67
108
  * A utility type for mapping {@link PermissionRule}s to their corresponding
68
109
  * {@link @backstage/plugin-permission-common#PermissionCondition}s.
@@ -92,13 +133,13 @@ declare type Conditions<TRules extends Record<string, PermissionRule<any, any, a
92
133
  *
93
134
  * @public
94
135
  */
95
- declare const createConditionExports: <TResourceType extends string, TResource, TRules extends Record<string, PermissionRule<TResource, any, TResourceType, unknown[]>>>(options: {
136
+ declare const createConditionExports: <TResourceType extends string, TResource, TRules extends Record<string, PermissionRule<TResource, any, TResourceType, _backstage_plugin_permission_common.PermissionRuleParams>>>(options: {
96
137
  pluginId: string;
97
138
  resourceType: TResourceType;
98
139
  rules: TRules;
99
140
  }) => {
100
141
  conditions: Conditions<TRules>;
101
- createConditionalDecision: (permission: ResourcePermission<TResourceType>, conditions: PermissionCriteria<PermissionCondition<TResourceType, unknown[]>>) => ConditionalPolicyDecision;
142
+ createConditionalDecision: (permission: ResourcePermission<TResourceType>, conditions: PermissionCriteria<PermissionCondition<TResourceType, _backstage_plugin_permission_common.PermissionRuleParams>>) => ConditionalPolicyDecision;
102
143
  };
103
144
 
104
145
  /**
@@ -118,7 +159,7 @@ declare type ConditionTransformer<TQuery> = (conditions: PermissionCriteria<Perm
118
159
  *
119
160
  * @public
120
161
  */
121
- declare const createConditionTransformer: <TQuery, TRules extends PermissionRule<any, TQuery, string, unknown[]>[]>(permissionRules: [...TRules]) => ConditionTransformer<TQuery>;
162
+ declare const createConditionTransformer: <TQuery, TRules extends PermissionRule<any, TQuery, string, _backstage_plugin_permission_common.PermissionRuleParams>[]>(permissionRules: [...TRules]) => ConditionTransformer<TQuery>;
122
163
 
123
164
  /**
124
165
  * A request to load the referenced resource and apply conditions in order to
@@ -154,13 +195,6 @@ declare type ApplyConditionsResponseEntry = IdentifiedPermissionMessage<Definiti
154
195
  declare type ApplyConditionsResponse = {
155
196
  items: ApplyConditionsResponseEntry[];
156
197
  };
157
- /**
158
- * Prevent use of type parameter from contributing to type inference.
159
- *
160
- * https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795
161
- * @ignore
162
- */
163
- declare type NoInfer<T> = T extends infer S ? S : never;
164
198
  /**
165
199
  * Create an express Router which provides an authorization route to allow
166
200
  * integration between the permission backend and other Backstage backend
@@ -199,7 +233,7 @@ declare type NoInfer<T> = T extends infer S ? S : never;
199
233
  declare const createPermissionIntegrationRouter: <TResourceType extends string, TResource>(options: {
200
234
  resourceType: TResourceType;
201
235
  permissions?: Permission[] | undefined;
202
- rules: PermissionRule<TResource, any, NoInfer<TResourceType>, unknown[]>[];
236
+ rules: PermissionRule<TResource, any, NoInfer<TResourceType>, _backstage_plugin_permission_common.PermissionRuleParams>[];
203
237
  getResources: (resourceRefs: string[]) => Promise<(TResource | undefined)[]>;
204
238
  }) => express.Router;
205
239
 
@@ -208,7 +242,7 @@ declare const createPermissionIntegrationRouter: <TResourceType extends string,
208
242
  *
209
243
  * @public
210
244
  */
211
- declare const createPermissionRule: <TResource, TQuery, TResourceType extends string, TParams extends unknown[]>(rule: PermissionRule<TResource, TQuery, TResourceType, TParams>) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
245
+ declare const createPermissionRule: <TResource, TQuery, TResourceType extends string, TParams extends PermissionRuleParams = undefined>(rule: PermissionRule<TResource, TQuery, TResourceType, TParams>) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
212
246
  /**
213
247
  * Helper for making plugin-specific createPermissionRule functions, that have
214
248
  * the TResource and TQuery type parameters populated but infer the params from
@@ -217,35 +251,7 @@ declare const createPermissionRule: <TResource, TQuery, TResourceType extends st
217
251
  *
218
252
  * @public
219
253
  */
220
- declare const makeCreatePermissionRule: <TResource, TQuery, TResourceType extends string>() => <TParams extends unknown[]>(rule: PermissionRule<TResource, TQuery, TResourceType, TParams>) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
221
-
222
- /**
223
- * Utility function used to parse a PermissionCriteria
224
- * @param criteria - a PermissionCriteria
225
- * @alpha
226
- *
227
- * @returns `true` if the permission criteria is of type allOf,
228
- * narrowing down `criteria` to the specific type.
229
- */
230
- declare const isAndCriteria: <T>(criteria: PermissionCriteria<T>) => criteria is AllOfCriteria<T>;
231
- /**
232
- * Utility function used to parse a PermissionCriteria of type
233
- * @param criteria - a PermissionCriteria
234
- * @alpha
235
- *
236
- * @returns `true` if the permission criteria is of type anyOf,
237
- * narrowing down `criteria` to the specific type.
238
- */
239
- declare const isOrCriteria: <T>(criteria: PermissionCriteria<T>) => criteria is AnyOfCriteria<T>;
240
- /**
241
- * Utility function used to parse a PermissionCriteria
242
- * @param criteria - a PermissionCriteria
243
- * @alpha
244
- *
245
- * @returns `true` if the permission criteria is of type not,
246
- * narrowing down `criteria` to the specific type.
247
- */
248
- declare const isNotCriteria: <T>(criteria: PermissionCriteria<T>) => criteria is NotCriteria<T>;
254
+ declare const makeCreatePermissionRule: <TResource, TQuery, TResourceType extends string>() => <TParams extends PermissionRuleParams = undefined>(rule: PermissionRule<TResource, TQuery, TResourceType, TParams>) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
249
255
 
250
256
  /**
251
257
  * A query to be evaluated by the {@link PermissionPolicy}.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/plugin-permission-node",
3
3
  "description": "Common permission and authorization utilities for backend plugins",
4
- "version": "0.6.6-next.0",
4
+ "version": "0.7.0-next.2",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -33,19 +33,20 @@
33
33
  "start": "backstage-cli package start"
34
34
  },
35
35
  "dependencies": {
36
- "@backstage/backend-common": "^0.15.2-next.0",
37
- "@backstage/config": "^1.0.3-next.0",
38
- "@backstage/errors": "^1.1.2-next.0",
39
- "@backstage/plugin-auth-node": "^0.2.6-next.0",
40
- "@backstage/plugin-permission-common": "^0.6.5-next.0",
36
+ "@backstage/backend-common": "^0.15.2-next.2",
37
+ "@backstage/config": "^1.0.3-next.2",
38
+ "@backstage/errors": "^1.1.2-next.2",
39
+ "@backstage/plugin-auth-node": "^0.2.6-next.2",
40
+ "@backstage/plugin-permission-common": "^0.7.0-next.2",
41
41
  "@types/express": "^4.17.6",
42
42
  "express": "^4.17.1",
43
43
  "express-promise-router": "^4.1.0",
44
- "zod": "^3.11.6"
44
+ "zod": "^3.11.6",
45
+ "zod-to-json-schema": "^3.18.1"
45
46
  },
46
47
  "devDependencies": {
47
- "@backstage/backend-test-utils": "^0.1.29-next.0",
48
- "@backstage/cli": "^0.20.0-next.0",
48
+ "@backstage/backend-test-utils": "^0.1.29-next.2",
49
+ "@backstage/cli": "^0.20.0-next.2",
49
50
  "@types/supertest": "^2.0.8",
50
51
  "msw": "^0.47.0",
51
52
  "supertest": "^6.1.3"