@backstage/plugin-permission-common 0.5.0 → 0.5.3
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 +24 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +220 -0
- package/dist/index.esm.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @backstage/plugin-permission-common
|
|
2
2
|
|
|
3
|
+
## 0.5.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f24ef7864e: Minor typo fixes
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/config@1.0.0
|
|
10
|
+
- @backstage/errors@1.0.0
|
|
11
|
+
|
|
12
|
+
## 0.5.2
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 79b9d8a861: Add api doc comments to `Permission` type properties.
|
|
17
|
+
|
|
18
|
+
## 0.5.1
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Fix for the previous release with missing type declarations.
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @backstage/config@0.1.15
|
|
25
|
+
- @backstage/errors@0.2.2
|
|
26
|
+
|
|
3
27
|
## 0.5.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/PermissionClient.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 { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type Identified<T> = T & { id: string };\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * An individual authorization request for {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeQuery = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of authorization requests from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeRequest = {\n items: Identified<AuthorizeQuery>[];\n};\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represnts a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represnts a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual authorization response from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeDecision =\n | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY }\n | {\n result: AuthorizeResult.CONDITIONAL;\n conditions: PermissionCriteria<PermissionCondition>;\n };\n\n/**\n * A batch of authorization responses from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeResponse = {\n items: Identified<AuthorizeDecision>[];\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 { Permission } from '../types';\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\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 { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n AuthorizeQuery,\n AuthorizeDecision,\n Identified,\n PermissionCriteria,\n PermissionCondition,\n AuthorizeResponse,\n AuthorizeRequest,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: AuthorizeQuery[],\n options?: AuthorizeRequestOptions,\n ): Promise<AuthorizeDecision[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: AuthorizeRequest = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, Identified<AuthorizeDecision>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: AuthorizeRequest,\n json: any,\n ): asserts json is AuthorizeResponse {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":["z","uuid","fetch","ResponseError"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BY,oCAAA,qBAAL;AAIL,6BAAO;AAIP,8BAAQ;AAIR,oCAAc;AAZJ;AAAA;;4BCPuB,YAAwB;AACzD,SAAO,WAAW,WAAW,WAAW;AAAA;0BAOT,YAAwB;AACvD,SAAO,WAAW,WAAW,WAAW;AAAA;4BAOP,YAAwB;AACzD,SAAO,WAAW,WAAW,WAAW;AAAA;4BAOP,YAAwB;AACzD,SAAO,WAAW,WAAW,WAAW;AAAA;;ACV1C,MAAM,2BAEFA,MAAE,KAAK,MACTA,MACG,OAAO;AAAA,EACN,MAAMA,MAAE;AAAA,EACR,QAAQA,MAAE,MAAMA,MAAE;AAAA,GAEnB,SACA,GACCA,MACG,OAAO,EAAE,OAAOA,MAAE,MAAM,0BAA0B,cAClD,UAEJ,GACCA,MACG,OAAO,EAAE,OAAOA,MAAE,MAAM,0BAA0B,cAClD,UAEJ,GAAGA,MAAE,OAAO,EAAE,KAAK,4BAA4B;AAGpD,MAAM,iBAAiBA,MAAE,OAAO;AAAA,EAC9B,OAAOA,MAAE,MACPA,MACG,OAAO;AAAA,IACN,IAAIA,MAAE;AAAA,IACN,QAAQA,MACL,QAAQ,gBAAgB,OACxB,GAAGA,MAAE,QAAQ,gBAAgB;AAAA,KAEjC,GACCA,MAAE,OAAO;AAAA,IACP,IAAIA,MAAE;AAAA,IACN,QAAQA,MAAE,QAAQ,gBAAgB;AAAA,IAClC,YAAY;AAAA;AAAA;uBAUwC;AAAA,EAI5D,YAAY,SAAsD;AAtFpE;AAuFI,SAAK,YAAY,QAAQ;AACzB,SAAK,UACH,cAAQ,OAAO,mBAAmB,0BAAlC,YAA2D;AAAA;AAAA,QAmBzD,UACJ,SACA,SAC8B;AAM9B,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,QAAQ,IAAI,UAAQ,QAAQ,gBAAgB;AAAA;AAGrD,UAAM,UAA4B;AAAA,MAChC,OAAO,QAAQ,IAAI;AAAU,QAC3B,IAAIC,gBAAK;AAAA,WACN;AAAA;AAAA;AAIP,UAAM,gBAAgB,MAAM,KAAK,UAAU,WAAW;AACtD,UAAM,WAAW,MAAMC,0BAAM,GAAG,2BAA2B;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,MACrB,SAAS;AAAA,WACJ,KAAK,uBAAuB,mCAAS;AAAA,QACxC,gBAAgB;AAAA;AAAA;AAGpB,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAMC,qBAAc,aAAa;AAAA;AAGzC,UAAM,eAAe,MAAM,SAAS;AACpC,SAAK,oBAAoB,SAAS;AAElC,UAAM,gBAAgB,aAAa,MAAM,OAAO,CAAC,KAAK,MAAM;AAC1D,UAAI,EAAE,MAAM;AACZ,aAAO;AAAA,OACN;AAEH,WAAO,QAAQ,MAAM,IAAI,WAAS,cAAc,MAAM;AAAA;AAAA,EAGhD,uBAAuB,OAAwC;AACrE,WAAO,QAAQ,EAAE,eAAe,UAAU,YAAY;AAAA;AAAA,EAGhD,oBACN,SACA,MACmC;AACnC,UAAM,sBAAsB,eAAe,MAAM;AACjD,UAAM,cAAc,oBAAoB,MAAM,IAAI,OAAK,EAAE;AACzD,UAAM,mBAAmB,QAAQ,MAAM,MAAM,OAC3C,YAAY,SAAS,EAAE;AAEzB,QAAI,CAAC,kBAAkB;AACrB,YAAM,IAAI,MACR;AAAA;AAAA;AAAA;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/PermissionClient.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 { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type Identified<T> = T & { id: string };\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * An individual authorization request for {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeQuery = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of authorization requests from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeRequest = {\n items: Identified<AuthorizeQuery>[];\n};\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual authorization response from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeDecision =\n | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY }\n | {\n result: AuthorizeResult.CONDITIONAL;\n conditions: PermissionCriteria<PermissionCondition>;\n };\n\n/**\n * A batch of authorization responses from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeResponse = {\n items: Identified<AuthorizeDecision>[];\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 { Permission } from '../types';\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\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 { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n AuthorizeQuery,\n AuthorizeDecision,\n Identified,\n PermissionCriteria,\n PermissionCondition,\n AuthorizeResponse,\n AuthorizeRequest,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: AuthorizeQuery[],\n options?: AuthorizeRequestOptions,\n ): Promise<AuthorizeDecision[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: AuthorizeRequest = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, Identified<AuthorizeDecision>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: AuthorizeRequest,\n json: any,\n ): asserts json is AuthorizeResponse {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":["z","uuid","fetch","ResponseError"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { Config } from '@backstage/config';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The attributes related to a given permission; these should be generic and widely applicable to
|
|
5
|
+
* all permissions in the system.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
declare type PermissionAttributes = {
|
|
9
|
+
action?: 'create' | 'read' | 'update' | 'delete';
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A permission that can be checked through authorization.
|
|
13
|
+
*
|
|
14
|
+
* Permissions are the "what" part of authorization, the action to be performed. This may be reading
|
|
15
|
+
* an entity from the catalog, executing a software template, or any other action a plugin author
|
|
16
|
+
* may wish to protect.
|
|
17
|
+
*
|
|
18
|
+
* To evaluate authorization, a permission is paired with a Backstage identity (the "who") and
|
|
19
|
+
* evaluated using an authorization policy.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
declare type Permission = {
|
|
23
|
+
/**
|
|
24
|
+
* The name of the permission.
|
|
25
|
+
*/
|
|
26
|
+
name: string;
|
|
27
|
+
/**
|
|
28
|
+
* {@link PermissionAttributes} which describe characteristics of the permission, to help
|
|
29
|
+
* policy authors make consistent decisions for similar permissions without referring to them
|
|
30
|
+
* all by name.
|
|
31
|
+
*/
|
|
32
|
+
attributes: PermissionAttributes;
|
|
33
|
+
/**
|
|
34
|
+
* Some permissions can be authorized based on characteristics of a resource
|
|
35
|
+
* such a catalog entity. For these permissions, the resourceType field
|
|
36
|
+
* denotes the type of the resource whose resourceRef should be passed when
|
|
37
|
+
* authorizing.
|
|
38
|
+
*/
|
|
39
|
+
resourceType?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* A client interacting with the permission backend can implement this authorizer interface.
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
interface PermissionAuthorizer {
|
|
46
|
+
authorize(queries: AuthorizeQuery[], options?: AuthorizeRequestOptions): Promise<AuthorizeDecision[]>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Options for authorization requests.
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
52
|
+
declare type AuthorizeRequestOptions = {
|
|
53
|
+
token?: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A request with a UUID identifier, so that batched responses can be matched up with the original
|
|
58
|
+
* requests.
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
declare type Identified<T> = T & {
|
|
62
|
+
id: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* The result of an authorization request.
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
declare enum AuthorizeResult {
|
|
69
|
+
/**
|
|
70
|
+
* The authorization request is denied.
|
|
71
|
+
*/
|
|
72
|
+
DENY = "DENY",
|
|
73
|
+
/**
|
|
74
|
+
* The authorization request is allowed.
|
|
75
|
+
*/
|
|
76
|
+
ALLOW = "ALLOW",
|
|
77
|
+
/**
|
|
78
|
+
* The authorization request is allowed if the provided conditions are met.
|
|
79
|
+
*/
|
|
80
|
+
CONDITIONAL = "CONDITIONAL"
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* An individual authorization request for {@link PermissionClient#authorize}.
|
|
84
|
+
* @public
|
|
85
|
+
*/
|
|
86
|
+
declare type AuthorizeQuery = {
|
|
87
|
+
permission: Permission;
|
|
88
|
+
resourceRef?: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* A batch of authorization requests from {@link PermissionClient#authorize}.
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
declare type AuthorizeRequest = {
|
|
95
|
+
items: Identified<AuthorizeQuery>[];
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* A condition returned with a CONDITIONAL authorization response.
|
|
99
|
+
*
|
|
100
|
+
* Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For
|
|
101
|
+
* example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity
|
|
102
|
+
* claims from a identity token.
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
declare type PermissionCondition<TParams extends unknown[] = unknown[]> = {
|
|
106
|
+
rule: string;
|
|
107
|
+
params: TParams;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Utility type to represent an array with 1 or more elements.
|
|
111
|
+
* @ignore
|
|
112
|
+
*/
|
|
113
|
+
declare type NonEmptyArray<T> = [T, ...T[]];
|
|
114
|
+
/**
|
|
115
|
+
* Represents a logical AND for the provided criteria.
|
|
116
|
+
* @public
|
|
117
|
+
*/
|
|
118
|
+
declare type AllOfCriteria<TQuery> = {
|
|
119
|
+
allOf: NonEmptyArray<PermissionCriteria<TQuery>>;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Represents a logical OR for the provided criteria.
|
|
123
|
+
* @public
|
|
124
|
+
*/
|
|
125
|
+
declare type AnyOfCriteria<TQuery> = {
|
|
126
|
+
anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Represents a negation of the provided criteria.
|
|
130
|
+
* @public
|
|
131
|
+
*/
|
|
132
|
+
declare type NotCriteria<TQuery> = {
|
|
133
|
+
not: PermissionCriteria<TQuery>;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
declare type PermissionCriteria<TQuery> = AllOfCriteria<TQuery> | AnyOfCriteria<TQuery> | NotCriteria<TQuery> | TQuery;
|
|
140
|
+
/**
|
|
141
|
+
* An individual authorization response from {@link PermissionClient#authorize}.
|
|
142
|
+
* @public
|
|
143
|
+
*/
|
|
144
|
+
declare type AuthorizeDecision = {
|
|
145
|
+
result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;
|
|
146
|
+
} | {
|
|
147
|
+
result: AuthorizeResult.CONDITIONAL;
|
|
148
|
+
conditions: PermissionCriteria<PermissionCondition>;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* A batch of authorization responses from {@link PermissionClient#authorize}.
|
|
152
|
+
* @public
|
|
153
|
+
*/
|
|
154
|
+
declare type AuthorizeResponse = {
|
|
155
|
+
items: Identified<AuthorizeDecision>[];
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* This is a copy of the core DiscoveryApi, to avoid importing core.
|
|
160
|
+
*
|
|
161
|
+
* @public
|
|
162
|
+
*/
|
|
163
|
+
declare type DiscoveryApi = {
|
|
164
|
+
getBaseUrl(pluginId: string): Promise<string>;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Check if a given permission is related to a create action.
|
|
169
|
+
* @public
|
|
170
|
+
*/
|
|
171
|
+
declare function isCreatePermission(permission: Permission): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Check if a given permission is related to a read action.
|
|
174
|
+
* @public
|
|
175
|
+
*/
|
|
176
|
+
declare function isReadPermission(permission: Permission): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Check if a given permission is related to an update action.
|
|
179
|
+
* @public
|
|
180
|
+
*/
|
|
181
|
+
declare function isUpdatePermission(permission: Permission): boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Check if a given permission is related to a delete action.
|
|
184
|
+
* @public
|
|
185
|
+
*/
|
|
186
|
+
declare function isDeletePermission(permission: Permission): boolean;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* An isomorphic client for requesting authorization for Backstage permissions.
|
|
190
|
+
* @public
|
|
191
|
+
*/
|
|
192
|
+
declare class PermissionClient implements PermissionAuthorizer {
|
|
193
|
+
private readonly enabled;
|
|
194
|
+
private readonly discovery;
|
|
195
|
+
constructor(options: {
|
|
196
|
+
discovery: DiscoveryApi;
|
|
197
|
+
config: Config;
|
|
198
|
+
});
|
|
199
|
+
/**
|
|
200
|
+
* Request authorization from the permission-backend for the given set of permissions.
|
|
201
|
+
*
|
|
202
|
+
* Authorization requests check that a given Backstage user can perform a protected operation,
|
|
203
|
+
* potentially for a specific resource (such as a catalog entity). The Backstage identity token
|
|
204
|
+
* should be included in the `options` if available.
|
|
205
|
+
*
|
|
206
|
+
* Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.
|
|
207
|
+
*
|
|
208
|
+
* The response will be either ALLOW or DENY when either the permission has no resourceType, or a
|
|
209
|
+
* resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be
|
|
210
|
+
* returned if no resourceRef is provided in the request. Conditional responses are intended only
|
|
211
|
+
* for backends which have access to the data source for permissioned resources, so that filters
|
|
212
|
+
* can be applied when loading collections of resources.
|
|
213
|
+
* @public
|
|
214
|
+
*/
|
|
215
|
+
authorize(queries: AuthorizeQuery[], options?: AuthorizeRequestOptions): Promise<AuthorizeDecision[]>;
|
|
216
|
+
private getAuthorizationHeader;
|
|
217
|
+
private assertValidResponse;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export { AllOfCriteria, AnyOfCriteria, AuthorizeDecision, AuthorizeQuery, AuthorizeRequest, AuthorizeRequestOptions, AuthorizeResponse, AuthorizeResult, DiscoveryApi, Identified, NotCriteria, Permission, PermissionAttributes, PermissionAuthorizer, PermissionClient, PermissionCondition, PermissionCriteria, isCreatePermission, isDeletePermission, isReadPermission, isUpdatePermission };
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/PermissionClient.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 { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type Identified<T> = T & { id: string };\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * An individual authorization request for {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeQuery = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of authorization requests from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeRequest = {\n items: Identified<AuthorizeQuery>[];\n};\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represnts a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represnts a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual authorization response from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeDecision =\n | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY }\n | {\n result: AuthorizeResult.CONDITIONAL;\n conditions: PermissionCriteria<PermissionCondition>;\n };\n\n/**\n * A batch of authorization responses from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeResponse = {\n items: Identified<AuthorizeDecision>[];\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 { Permission } from '../types';\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\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 { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n AuthorizeQuery,\n AuthorizeDecision,\n Identified,\n PermissionCriteria,\n PermissionCondition,\n AuthorizeResponse,\n AuthorizeRequest,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: AuthorizeQuery[],\n options?: AuthorizeRequestOptions,\n ): Promise<AuthorizeDecision[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: AuthorizeRequest = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, Identified<AuthorizeDecision>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: AuthorizeRequest,\n json: any,\n ): asserts json is AuthorizeResponse {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":[],"mappings":";;;;;IA6BY,oCAAA,qBAAL;AAIL,6BAAO;AAIP,8BAAQ;AAIR,oCAAc;AAZJ;AAAA;;4BCPuB,YAAwB;AACzD,SAAO,WAAW,WAAW,WAAW;AAAA;0BAOT,YAAwB;AACvD,SAAO,WAAW,WAAW,WAAW;AAAA;4BAOP,YAAwB;AACzD,SAAO,WAAW,WAAW,WAAW;AAAA;4BAOP,YAAwB;AACzD,SAAO,WAAW,WAAW,WAAW;AAAA;;ACV1C,MAAM,2BAEF,EAAE,KAAK,MACT,EACG,OAAO;AAAA,EACN,MAAM,EAAE;AAAA,EACR,QAAQ,EAAE,MAAM,EAAE;AAAA,GAEnB,SACA,GACC,EACG,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,cAClD,UAEJ,GACC,EACG,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,cAClD,UAEJ,GAAG,EAAE,OAAO,EAAE,KAAK,4BAA4B;AAGpD,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,OAAO,EAAE,MACP,EACG,OAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,QAAQ,EACL,QAAQ,gBAAgB,OACxB,GAAG,EAAE,QAAQ,gBAAgB;AAAA,KAEjC,GACC,EAAE,OAAO;AAAA,IACP,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE,QAAQ,gBAAgB;AAAA,IAClC,YAAY;AAAA;AAAA;uBAUwC;AAAA,EAI5D,YAAY,SAAsD;AAtFpE;AAuFI,SAAK,YAAY,QAAQ;AACzB,SAAK,UACH,cAAQ,OAAO,mBAAmB,0BAAlC,YAA2D;AAAA;AAAA,QAmBzD,UACJ,SACA,SAC8B;AAM9B,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,QAAQ,IAAI,UAAQ,QAAQ,gBAAgB;AAAA;AAGrD,UAAM,UAA4B;AAAA,MAChC,OAAO,QAAQ,IAAI;AAAU,QAC3B,IAAI,KAAK;AAAA,WACN;AAAA;AAAA;AAIP,UAAM,gBAAgB,MAAM,KAAK,UAAU,WAAW;AACtD,UAAM,WAAW,MAAM,MAAM,GAAG,2BAA2B;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,MACrB,SAAS;AAAA,WACJ,KAAK,uBAAuB,mCAAS;AAAA,QACxC,gBAAgB;AAAA;AAAA;AAGpB,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,cAAc,aAAa;AAAA;AAGzC,UAAM,eAAe,MAAM,SAAS;AACpC,SAAK,oBAAoB,SAAS;AAElC,UAAM,gBAAgB,aAAa,MAAM,OAAO,CAAC,KAAK,MAAM;AAC1D,UAAI,EAAE,MAAM;AACZ,aAAO;AAAA,OACN;AAEH,WAAO,QAAQ,MAAM,IAAI,WAAS,cAAc,MAAM;AAAA;AAAA,EAGhD,uBAAuB,OAAwC;AACrE,WAAO,QAAQ,EAAE,eAAe,UAAU,YAAY;AAAA;AAAA,EAGhD,oBACN,SACA,MACmC;AACnC,UAAM,sBAAsB,eAAe,MAAM;AACjD,UAAM,cAAc,oBAAoB,MAAM,IAAI,OAAK,EAAE;AACzD,UAAM,mBAAmB,QAAQ,MAAM,MAAM,OAC3C,YAAY,SAAS,EAAE;AAEzB,QAAI,CAAC,kBAAkB;AACrB,YAAM,IAAI,MACR;AAAA;AAAA;AAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/PermissionClient.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 { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type Identified<T> = T & { id: string };\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * An individual authorization request for {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeQuery = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of authorization requests from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeRequest = {\n items: Identified<AuthorizeQuery>[];\n};\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual authorization response from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeDecision =\n | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY }\n | {\n result: AuthorizeResult.CONDITIONAL;\n conditions: PermissionCriteria<PermissionCondition>;\n };\n\n/**\n * A batch of authorization responses from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeResponse = {\n items: Identified<AuthorizeDecision>[];\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 { Permission } from '../types';\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\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 { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n AuthorizeQuery,\n AuthorizeDecision,\n Identified,\n PermissionCriteria,\n PermissionCondition,\n AuthorizeResponse,\n AuthorizeRequest,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: AuthorizeQuery[],\n options?: AuthorizeRequestOptions,\n ): Promise<AuthorizeDecision[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: AuthorizeRequest = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, Identified<AuthorizeDecision>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: AuthorizeRequest,\n json: any,\n ): asserts json is AuthorizeResponse {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-permission-common",
|
|
3
3
|
"description": "Isomorphic types and client for Backstage permissions and authorization",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.3",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"publishConfig": {
|
|
@@ -41,17 +41,17 @@
|
|
|
41
41
|
"url": "https://github.com/backstage/backstage/issues"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@backstage/config": "^0.
|
|
45
|
-
"@backstage/errors": "^0.
|
|
44
|
+
"@backstage/config": "^1.0.0",
|
|
45
|
+
"@backstage/errors": "^1.0.0",
|
|
46
46
|
"cross-fetch": "^3.1.5",
|
|
47
47
|
"uuid": "^8.0.0",
|
|
48
48
|
"zod": "^3.11.6"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@backstage/cli": "^0.
|
|
51
|
+
"@backstage/cli": "^0.16.0",
|
|
52
52
|
"@types/jest": "^26.0.7",
|
|
53
53
|
"msw": "^0.35.0"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "e9496f746b31600dbfac7fa76987479e66426257",
|
|
56
56
|
"module": "dist/index.esm.js"
|
|
57
57
|
}
|