diff --git a/docs/features/software-templates/authorizing-parameters-steps-and-actions.md b/docs/features/software-templates/authorizing-parameters-steps-and-actions.md new file mode 100644 index 0000000000..1351676c37 --- /dev/null +++ b/docs/features/software-templates/authorizing-parameters-steps-and-actions.md @@ -0,0 +1,175 @@ +--- +id: authorizing-parameters-steps-and-actions +title: 'Authorizing parameters, steps and actions' +description: How to authorize part of a template +--- + +The scaffolder plugin integrates with the Backstage [permission framework](../../permissions/overview.md), which allows you to control access to certain parameters and steps in your templates based on the user executing the template. + +### Authorizing parameters and steps + +To mark specific parameters or steps as requiring permission, add the `backstage:permissions` property to the parameter or step with one or more tags. For example: + +```yaml +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: my_custom_template + parameters: + - title: Provide some simple information + properties: + title: + title: Title + type: string + - title: Extra information + properties: + description: + title: Description + type: string + backstage:permissions: + tags: + - secret + steps: + - id: step1 + name: First log + action: debug:log + input: + message: hello + - id: step2 + name: Log message + action: debug:log + input: + message: hello + backstage:permissions: + tags: + - secret +``` + +In this example, the `description` parameter and the `step2` step are marked with the `secret` tag. + +To conditionally authorize parameters and steps based on the user executing the template, [edit your permission policy](../../permissions/writing-a-policy.md), by targeting `templateParameterReadPermission` and `templateStepReadPermission` permissions, which are provided by the scaffolder plugin. For example: + +```ts title="packages/backend/src/plugins/permission.ts" +/* highlight-add-start */ +import { + templateParameterReadPermission, + templateStepReadPermission, +} from '@backstage/plugin-scaffolder-common/alpha'; +import { + createScaffolderActionConditionalDecision, + scaffolderTemplateConditions, +} from '@backstage/plugin-scaffolder-backend/alpha'; +/* highlight-add-end */ + +class ExamplePermissionPolicy implements PermissionPolicy { + async handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise { + /* highlight-add-start */ + if ( + isPermission(request.permission, templateParameterReadPermission) || + isPermission(request.permission, templateStepReadPermission) + ) { + if (user?.identity.userEntityRef === 'user:default/spiderman') + return createScaffolderTemplateConditionalDecision(request.permission, { + not: scaffolderTemplateConditions.hasTag({ tag: 'secret' }), + }); + } + /* highlight-add-end */ + + return { + result: AuthorizeResult.ALLOW, + }; + } +} +``` + +In this example, the user `spiderman` is not authorized to read parameters or steps marked with the `secret` tag. + +By combining this feature with restricting the ingestion of templates in the Catalog as recommended in our threat model, you can create a solid system to restrict certain actions. + +### Authorizing actions + +Similar to parameters and steps, the scaffolder plugin exposes permissions to restrict access to certain actions. This can be useful if you want to secure your templates. + +To restrict access to a particular action, you can modify your permission policy as follows: + +```ts title="packages/backend/src/plugins/permission.ts" +/* highlight-add-start */ +import { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha'; +import { + createScaffolderActionConditionalDecision, + scaffolderActionConditions, +} from '@backstage/plugin-scaffolder-backend/alpha'; +/* highlight-add-end */ + +class ExamplePermissionPolicy implements PermissionPolicy { + async handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise { + /* highlight-add-start */ + if (isPermission(request.permission, actionExecutePermission)) { + if (user?.identity.userEntityRef === 'user:default/spiderman') { + return createScaffolderActionConditionalDecision(request.permission, { + not: scaffolderActionConditions.hasActionId({ + actionId: 'debug:log', + }), + }); + } + } + /* highlight-add-end */ + + return { + result: AuthorizeResult.ALLOW, + }; + } +} +``` + +With this permission policy, the user `spiderman` won't be able to execute the debug:log action. + +You can also restrict the input provided to the action by combining multiple rules. +In the example below, `spiderman` won't be able to execute debug:log when passing `{ "message": "not-this!" }` as action input: + +```ts title="packages/backend/src/plugins/permission.ts" +/* highlight-add-start */ +import { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha'; +import { + createScaffolderActionConditionalDecision, + scaffolderActionConditions, +} from '@backstage/plugin-scaffolder-backend/alpha'; +/* highlight-add-end */ + +class ExamplePermissionPolicy implements PermissionPolicy { + async handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise { + /* highlight-add-start */ + if (isPermission(request.permission, actionExecutePermission)) { + if (user?.identity.userEntityRef === 'user:default/spiderman') { + return createScaffolderActionConditionalDecision(request.permission, { + not: { + allOf: [ + scaffolderActionConditions.hasActionId({ actionId: 'debug:log' }), + scaffolderActionConditions.hasProperty({ + key: 'message', + value: 'not-this!', + }), + ], + }, + }); + } + } + /* highlight-add-end */ + + return { + result: AuthorizeResult.ALLOW, + }; + } +} +``` + +Although the rules exported by the scaffolder are simple, combining them can help you achieve more complex cases. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 5e9629733d..cf2f9b7b56 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -108,6 +108,7 @@ "features/software-templates/writing-custom-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", + "features/software-templates/authorizing-parameters-steps-and-actions", "features/software-templates/testing-scaffolder-alpha", "features/software-templates/migrating-from-v1beta2-to-v1beta3" ]