permission-node: update policy handler to work with new auth system
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-permission-backend-module-allow-all-policy': patch
|
||||
---
|
||||
|
||||
Internal refactor to use new `PolicyQueryUser` type.
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
'@backstage/plugin-permission-backend': patch
|
||||
'@backstage/plugin-permission-node': patch
|
||||
---
|
||||
|
||||
The `PermissionPolicy` interface has been updated to align with the recent changes to the Backstage auth system. The second argument to the `handle` method is now of the new `PolicyQueryUser` type. This type maintains the old fields from the `BackstageIdentityResponse`, which are now all deprecated. Instead, two new fields have been added, which allows access to the same information:
|
||||
|
||||
- `credentials` - A `BackstageCredentials` object, which is useful for making requests to other services on behalf of the user as part of evaluating the policy. This replaces the deprecated `token` field. See the [Auth Service documentation](https://backstage.io/docs/backend-system/core-services/auth#creating-request-tokens) for information about how to create a token using these credentials.
|
||||
- `info` - A `BackstageUserInfo` object, which contains the same information as the deprecated `identity`, except for the `type` field that was redundant.
|
||||
|
||||
Most existing policies can be updated by replacing the `BackstageIdentityResponse` type with `PolicyQueryUser`, which is exported from `@backstage/plugin-permission-node`, as well as replacing any occurrences of `user?.identity` with `user?.info`.
|
||||
@@ -1254,7 +1254,6 @@ In order to add your own permission policy you'll need to do the following:
|
||||
|
||||
```ts
|
||||
import { createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
PolicyDecision,
|
||||
AuthorizeResult,
|
||||
@@ -1262,13 +1261,14 @@ import {
|
||||
import {
|
||||
PermissionPolicy,
|
||||
PolicyQuery,
|
||||
PolicyQueryUser,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
import { policyExtensionPoint } from '@backstage/plugin-permission-node/alpha';
|
||||
|
||||
class CustomPermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
// TODO: Add code here that inspects the incoming request and user, and returns AuthorizeResult.ALLOW, AuthorizeResult.DENY, or AuthorizeResult.CONDITIONAL as needed. See the docs at https://backstage.io/docs/permissions/writing-a-policy for more information
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ This feature assumes your backstage instance has enabled the [permissions framew
|
||||
A sample policy like:
|
||||
|
||||
```typescript
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
AuthorizeResult,
|
||||
PolicyDecision,
|
||||
@@ -68,12 +67,13 @@ import {
|
||||
import {
|
||||
PermissionPolicy,
|
||||
PolicyQuery,
|
||||
PolicyQueryUser,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
|
||||
class KubernetesDenyAllProxyEndpointPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
if (request.permission.name === 'kubernetes.proxy') {
|
||||
return {
|
||||
|
||||
@@ -66,14 +66,14 @@ import {
|
||||
class ExamplePermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
/* highlight-add-start */
|
||||
if (
|
||||
isPermission(request.permission, templateParameterReadPermission) ||
|
||||
isPermission(request.permission, templateStepReadPermission)
|
||||
) {
|
||||
if (user?.identity.userEntityRef === 'user:default/spiderman')
|
||||
if (user?.info.userEntityRef === 'user:default/spiderman')
|
||||
return createScaffolderTemplateConditionalDecision(request.permission, {
|
||||
not: scaffolderTemplateConditions.hasTag({ tag: 'secret' }),
|
||||
});
|
||||
@@ -109,11 +109,11 @@ import {
|
||||
class ExamplePermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
/* highlight-add-start */
|
||||
if (isPermission(request.permission, actionExecutePermission)) {
|
||||
if (user?.identity.userEntityRef === 'user:default/spiderman') {
|
||||
if (user?.info.userEntityRef === 'user:default/spiderman') {
|
||||
return createScaffolderActionConditionalDecision(request.permission, {
|
||||
not: scaffolderActionConditions.hasActionId({
|
||||
actionId: 'debug:log',
|
||||
@@ -147,11 +147,11 @@ import {
|
||||
class ExamplePermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
/* highlight-add-start */
|
||||
if (isPermission(request.permission, actionExecutePermission)) {
|
||||
if (user?.identity.userEntityRef === 'user:default/spiderman') {
|
||||
if (user?.info.userEntityRef === 'user:default/spiderman') {
|
||||
return createScaffolderActionConditionalDecision(request.permission, {
|
||||
not: {
|
||||
allOf: [
|
||||
@@ -190,25 +190,25 @@ import {
|
||||
class ExamplePermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
/* highlight-add-start */
|
||||
if (isPermission(request.permission, taskCreatePermission)) {
|
||||
if (user?.identity.userEntityRef === 'user:default/spiderman') {
|
||||
if (user?.info.userEntityRef === 'user:default/spiderman') {
|
||||
return {
|
||||
result: AuthorizeResult.ALLOW,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (isPermission(request.permission, taskCancelPermission)) {
|
||||
if (user?.identity.userEntityRef === 'user:default/spiderman') {
|
||||
if (user?.info.userEntityRef === 'user:default/spiderman') {
|
||||
return {
|
||||
result: AuthorizeResult.ALLOW,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (isPermission(request.permission, taskReadPermission)) {
|
||||
if (user?.identity.userEntityRef === 'user:default/spiderman') {
|
||||
if (user?.info.userEntityRef === 'user:default/spiderman') {
|
||||
return {
|
||||
result: AuthorizeResult.ALLOW,
|
||||
};
|
||||
@@ -239,7 +239,6 @@ Instead of the changes in `permission.ts` noted in the above example you will ma
|
||||
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
import { createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
PolicyDecision,
|
||||
AuthorizeResult,
|
||||
@@ -247,13 +246,14 @@ import {
|
||||
import {
|
||||
PermissionPolicy,
|
||||
PolicyQuery,
|
||||
PolicyQueryUser,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
import { policyExtensionPoint } from '@backstage/plugin-permission-node/alpha';
|
||||
|
||||
class ExamplePermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
// Various scaffolder permission checks ...
|
||||
|
||||
|
||||
@@ -66,9 +66,8 @@ import { catalogConditions, createCatalogConditionalDecision, createCatalogPermi
|
||||
/* highlight-remove-next-line */
|
||||
import { createConditionFactory } from '@backstage/plugin-permission-node';
|
||||
/* highlight-add-next-line */
|
||||
import { PermissionPolicy, PolicyQuery, createConditionFactory } from '@backstage/plugin-permission-node';
|
||||
import { PermissionPolicy, PolicyQuery, PolicyQueryUser, createConditionFactory } from '@backstage/plugin-permission-node';
|
||||
/* highlight-add-start */
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import { AuthorizeResult, PolicyDecision, isResourcePermission } from '@backstage/plugin-permission-common';
|
||||
/* highlight-add-end */
|
||||
...
|
||||
@@ -102,21 +101,21 @@ const isInSystem = createConditionFactory(isInSystemRule);
|
||||
class TestPermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
if (isResourcePermission(request.permission, 'catalog-entity')) {
|
||||
return createCatalogConditionalDecision(
|
||||
request.permission,
|
||||
/* highlight-remove-start */
|
||||
catalogConditions.isEntityOwner({
|
||||
claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
claims: user?.info.ownershipEntityRefs ?? [],
|
||||
}),
|
||||
/* highlight-remove-end */
|
||||
/* highlight-add-start */
|
||||
{
|
||||
anyOf: [
|
||||
catalogConditions.isEntityOwner({
|
||||
claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
claims: user?.info.ownershipEntityRefs ?? [],
|
||||
}),
|
||||
isInSystem({ systemRef: 'interviewing' }),
|
||||
],
|
||||
|
||||
@@ -169,15 +169,12 @@ Before running this step, please make sure you followed the steps described in [
|
||||
In order to test the logic above, the integrators of your backstage instance need to change their permission policy to return `DENY` for our newly-created permission:
|
||||
|
||||
```ts title="packages/backend/src/plugins/permission.ts"
|
||||
/* highlight-add-start */
|
||||
import {
|
||||
BackstageIdentityResponse,
|
||||
} from '@backstage/plugin-auth-node';
|
||||
/* highlight-add-end */
|
||||
import {
|
||||
PermissionPolicy,
|
||||
/* highlight-add-next-line */
|
||||
/* highlight-add-start */
|
||||
PolicyQuery,
|
||||
PolicyQueryUser,
|
||||
/* highlight-add-end */
|
||||
} from '@backstage/plugin-permission-node';
|
||||
/* highlight-add-start */
|
||||
import { isPermission } from '@backstage/plugin-permission-common';
|
||||
@@ -190,7 +187,7 @@ class TestPermissionPolicy implements PermissionPolicy {
|
||||
/* highlight-add-start */
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
_user?: BackstageIdentityResponse,
|
||||
_user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
if (isPermission(request.permission, todoListCreatePermission)) {
|
||||
return {
|
||||
|
||||
@@ -237,12 +237,12 @@ Let's go back to the permission policy's handle function and try to authorize ou
|
||||
|
||||
```ts title="packages/backend/src/plugins/permission.ts"
|
||||
import {
|
||||
BackstageIdentityResponse,
|
||||
IdentityClient
|
||||
} from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
PermissionPolicy,
|
||||
PolicyQuery,
|
||||
PolicyQueryUser,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
import { isPermission } from '@backstage/plugin-permission-common';
|
||||
/* highlight-remove-next-line */
|
||||
@@ -262,9 +262,9 @@ import {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
/* highlight-remove-next-line */
|
||||
_user?: BackstageIdentityResponse,
|
||||
_user?: PolicyQueryUser,
|
||||
/* highlight-add-next-line */
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
if (isPermission(request.permission, todoListCreatePermission)) {
|
||||
return {
|
||||
@@ -276,7 +276,7 @@ async handle(
|
||||
return createTodoListConditionalDecision(
|
||||
request.permission,
|
||||
todoListConditions.isOwner({
|
||||
userId: user?.identity.userEntityRef ?? '',
|
||||
userId: user?.info.userEntityRef ?? '',
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@ That policy looked like this:
|
||||
|
||||
```typescript title="packages/backend/src/plugins/permission.ts"
|
||||
class TestPermissionPolicy implements PermissionPolicy {
|
||||
async handle(request: PolicyQuery): Promise<PolicyDecision> {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
_user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
if (request.permission.name === 'catalog.entity.delete') {
|
||||
return {
|
||||
result: AuthorizeResult.DENY,
|
||||
@@ -35,14 +38,6 @@ As we confirmed in the previous section, we know that this now prevents us from
|
||||
Let's change the policy to the following:
|
||||
|
||||
```ts
|
||||
/* highlight-remove-next-line */
|
||||
import { IdentityClient } from '@backstage/plugin-auth-node';
|
||||
/* highlight-add-start */
|
||||
import {
|
||||
BackstageIdentityResponse,
|
||||
IdentityClient
|
||||
} from '@backstage/plugin-auth-node';
|
||||
/* highlight-add-end */
|
||||
import {
|
||||
AuthorizeResult,
|
||||
PolicyDecision,
|
||||
@@ -65,7 +60,7 @@ class TestPermissionPolicy implements PermissionPolicy {
|
||||
/* highlight-add-start */
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
/* highlight-add-end */
|
||||
/* highlight-remove-next-line */
|
||||
@@ -81,7 +76,7 @@ class TestPermissionPolicy implements PermissionPolicy {
|
||||
return createCatalogConditionalDecision(
|
||||
request.permission,
|
||||
catalogConditions.isEntityOwner({
|
||||
claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
claims: user?.info.ownershipEntityRefs ?? [],
|
||||
}),
|
||||
);
|
||||
/* highlight-add-end */
|
||||
@@ -95,7 +90,7 @@ Let's walk through the new code that we just added.
|
||||
|
||||
Instead of returning an Definitive Policy Decision, we use factory methods to construct a [Conditional Policy Decision](https://backstage.io/docs/reference/plugin-permission-common.conditionalpolicydecision) (See the [Concepts page](./concepts.md) for more details). Since the policy doesn't have enough information to determine if `user` is the entity owner, this criteria is encapsulated within the conditional decision. However, `createCatalogConditionalDecision` will not compile unless `request.permission` is a catalog entity [`ResourcePermission`](https://backstage.io/docs/reference/plugin-permission-common.resourcepermission). This type constraint ensures that policies return conditional decisions that are compatible with the requested permission. To address this, we use [`isPermission`](https://backstage.io/docs/reference/plugin-permission-common.ispermission) to ["narrow"](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) the type of `request.permission` to `ResourcePermission<'catalog-entity'>`. This matches the runtime behavior that was in place before, but you'll notice that the type of `request.permission` has changed within the scope of that `if` statement.
|
||||
|
||||
The `catalogConditions` object contains all of the rules defined by the catalog plugin. These rules can be combined to form a [`PermissionCriteria`](https://backstage.io/docs/reference/plugin-permission-common.permissioncriteria) object, but for this case we only need to use the `isEntityOwner` rule. This rule accepts a list of entity refs that represent User identity and Group membership used to determine ownership. The second argument to `PermissionPolicy#handle` provides us with a `BackstageIdentityResponse` object, from which we can grab the user's `ownershipEntityRefs`. We provide an empty array as a fallback since the user may be anonymous.
|
||||
The `catalogConditions` object contains all of the rules defined by the catalog plugin. These rules can be combined to form a [`PermissionCriteria`](https://backstage.io/docs/reference/plugin-permission-common.permissioncriteria) object, but for this case we only need to use the `isEntityOwner` rule. This rule accepts a list of entity refs that represent User identity and Group membership used to determine ownership. The second argument to `PermissionPolicy#handle` provides us with a `PolicyQueryUser` object, from which we can grab the user's `ownershipEntityRefs`. We provide an empty array as a fallback since the user may be anonymous.
|
||||
|
||||
You should now be able to see in your Backstage app that the unregister entity button is enabled for entities that you own, but disabled for all other entities!
|
||||
|
||||
@@ -125,7 +120,7 @@ import {
|
||||
class TestPermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
/* highlight-remove-next-line */
|
||||
if (isPermission(request.permission, catalogEntityDeletePermission)) {
|
||||
@@ -134,7 +129,7 @@ class TestPermissionPolicy implements PermissionPolicy {
|
||||
return createCatalogConditionalDecision(
|
||||
request.permission,
|
||||
catalogConditions.isEntityOwner({
|
||||
claims: user?.identity.ownershipEntityRefs ?? [],
|
||||
claims: user?.info.ownershipEntityRefs ?? [],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
AuthorizeResult,
|
||||
PolicyDecision,
|
||||
@@ -22,12 +21,13 @@ import {
|
||||
import {
|
||||
PermissionPolicy,
|
||||
PolicyQuery,
|
||||
PolicyQueryUser,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
|
||||
export class AllowAllPermissionPolicy implements PermissionPolicy {
|
||||
async handle(
|
||||
_request: PolicyQuery,
|
||||
_user?: BackstageIdentityResponse,
|
||||
_user?: PolicyQueryUser,
|
||||
): Promise<PolicyDecision> {
|
||||
return {
|
||||
result: AuthorizeResult.ALLOW,
|
||||
|
||||
@@ -186,6 +186,13 @@ describe('createRouter', () => {
|
||||
mockCredentials.user().principal.userEntityRef,
|
||||
],
|
||||
},
|
||||
info: {
|
||||
userEntityRef: mockCredentials.user().principal.userEntityRef,
|
||||
ownershipEntityRefs: [
|
||||
mockCredentials.user().principal.userEntityRef,
|
||||
],
|
||||
},
|
||||
credentials: mockCredentials.user(),
|
||||
},
|
||||
);
|
||||
expect(response.body).toEqual({
|
||||
|
||||
@@ -22,10 +22,7 @@ import {
|
||||
errorHandler,
|
||||
} from '@backstage/backend-common';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import {
|
||||
BackstageIdentityResponse,
|
||||
IdentityApi,
|
||||
} from '@backstage/plugin-auth-node';
|
||||
import { IdentityApi } from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
AuthorizeResult,
|
||||
EvaluatePermissionRequest,
|
||||
@@ -40,6 +37,7 @@ import {
|
||||
ApplyConditionsRequestEntry,
|
||||
ApplyConditionsResponseEntry,
|
||||
PermissionPolicy,
|
||||
PolicyQueryUser,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
import { PermissionIntegrationClient } from './PermissionIntegrationClient';
|
||||
import { memoize } from 'lodash';
|
||||
@@ -130,9 +128,9 @@ const handleRequest = async (
|
||||
);
|
||||
});
|
||||
|
||||
let user: BackstageIdentityResponse | undefined;
|
||||
let user: PolicyQueryUser | undefined;
|
||||
if (auth.isPrincipal(credentials, 'user')) {
|
||||
const { ownershipEntityRefs } = await userInfo.getUserInfo(credentials);
|
||||
const info = await userInfo.getUserInfo(credentials);
|
||||
const { token } = await auth.getPluginRequestToken({
|
||||
onBehalfOf: credentials,
|
||||
targetPluginId: 'catalog', // TODO: unknown at this point
|
||||
@@ -141,9 +139,11 @@ const handleRequest = async (
|
||||
identity: {
|
||||
type: 'user',
|
||||
userEntityRef: credentials.principal.userEntityRef,
|
||||
ownershipEntityRefs,
|
||||
ownershipEntityRefs: info.ownershipEntityRefs,
|
||||
},
|
||||
token,
|
||||
credentials,
|
||||
info,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ import { AnyOfCriteria } from '@backstage/plugin-permission-common';
|
||||
import { AuthorizePermissionRequest } from '@backstage/plugin-permission-common';
|
||||
import { AuthorizePermissionResponse } from '@backstage/plugin-permission-common';
|
||||
import { AuthService } from '@backstage/backend-plugin-api';
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import { BackstageCredentials } from '@backstage/backend-plugin-api';
|
||||
import { BackstageUserIdentity } from '@backstage/plugin-auth-node';
|
||||
import { BackstageUserInfo } from '@backstage/backend-plugin-api';
|
||||
import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DefinitivePolicyDecision } from '@backstage/plugin-permission-common';
|
||||
@@ -246,10 +248,7 @@ export type PermissionIntegrationRouterOptions<
|
||||
// @public
|
||||
export interface PermissionPolicy {
|
||||
// (undocumented)
|
||||
handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
): Promise<PolicyDecision>;
|
||||
handle(request: PolicyQuery, user?: PolicyQueryUser): Promise<PolicyDecision>;
|
||||
}
|
||||
|
||||
// @public
|
||||
@@ -272,6 +271,15 @@ export type PolicyQuery = {
|
||||
permission: Permission;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type PolicyQueryUser = {
|
||||
token: string;
|
||||
expiresInSeconds?: number;
|
||||
identity: BackstageUserIdentity;
|
||||
credentials: BackstageCredentials;
|
||||
info: BackstageUserInfo;
|
||||
};
|
||||
|
||||
// @public
|
||||
export class ServerPermissionClient implements PermissionsService {
|
||||
// (undocumented)
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type { PermissionPolicy, PolicyQuery } from './types';
|
||||
export type { PermissionPolicy, PolicyQuery, PolicyQueryUser } from './types';
|
||||
|
||||
@@ -18,7 +18,11 @@ import {
|
||||
Permission,
|
||||
PolicyDecision,
|
||||
} from '@backstage/plugin-permission-common';
|
||||
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
|
||||
import { BackstageUserIdentity } from '@backstage/plugin-auth-node';
|
||||
import {
|
||||
BackstageCredentials,
|
||||
BackstageUserInfo,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/**
|
||||
* A query to be evaluated by the {@link PermissionPolicy}.
|
||||
@@ -34,6 +38,44 @@ export type PolicyQuery = {
|
||||
permission: Permission;
|
||||
};
|
||||
|
||||
/**
|
||||
* The context within which a policy query is evaluated.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PolicyQueryUser = {
|
||||
/**
|
||||
* The token used to authenticate the user within Backstage.
|
||||
*
|
||||
* @deprecated User the `credentials` field in combination with `coreServices.auth` to generate a request token instead.
|
||||
*/
|
||||
token: string;
|
||||
|
||||
/**
|
||||
* The number of seconds until the token expires. If not set, it can be assumed that the token does not expire.
|
||||
*
|
||||
* @deprecated This field is deprecated and will be removed in a future release.
|
||||
*/
|
||||
expiresInSeconds?: number;
|
||||
|
||||
/**
|
||||
* A plaintext description of the identity that is encapsulated within the token.
|
||||
*
|
||||
* @deprecated Use the `info` field instead.
|
||||
*/
|
||||
identity: BackstageUserIdentity;
|
||||
|
||||
/**
|
||||
* The credentials of the user making the request.
|
||||
*/
|
||||
credentials: BackstageCredentials;
|
||||
|
||||
/**
|
||||
* The information for the user making the request.
|
||||
*/
|
||||
info: BackstageUserInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* A policy to evaluate authorization requests for any permissioned action performed in Backstage.
|
||||
*
|
||||
@@ -51,8 +93,5 @@ export type PolicyQuery = {
|
||||
* @public
|
||||
*/
|
||||
export interface PermissionPolicy {
|
||||
handle(
|
||||
request: PolicyQuery,
|
||||
user?: BackstageIdentityResponse,
|
||||
): Promise<PolicyDecision>;
|
||||
handle(request: PolicyQuery, user?: PolicyQueryUser): Promise<PolicyDecision>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user