feat(scaffolder): implementing secrets schema for scaffolder templates (#32320)

* feat: implementing secrets schema for scaffolder templates

Signed-off-by: benjdlambert <ben@blam.sh>

* chore: fix and regenerate openapi
Signed-off-by: benjdlambert <ben@blam.sh>

Signed-off-by: benjdlambert <ben@blam.sh>

* chore: fix review feedback

Signed-off-by: benjdlambert <ben@blam.sh>

* fix: address code review feedback for secrets validation

- Extract validateSecrets helper to deduplicate validation logic
- Add auditorEvent.fail() call on secrets validation failure
- Sanitize instance field in error responses to prevent secret leakage
- Add retry endpoint test coverage for secrets validation
- Split changeset into per-package entries

Signed-off-by: benjdlambert <ben@blam.sh>

* refactor: nest secrets schema under secrets.schema

Move the JSON Schema definition from spec.secrets to
spec.secrets.schema to leave room for future extensions
like secret sources.

Signed-off-by: benjdlambert <ben@blam.sh>

* chore: update API reports

Signed-off-by: benjdlambert <ben@blam.sh>

* chore: use InputError for secrets validation audit event

Signed-off-by: benjdlambert <ben@blam.sh>

---------

Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
Ben Lambert
2026-03-10 11:47:40 +01:00
committed by GitHub
parent c74b69788e
commit e8736ea2e8
11 changed files with 473 additions and 28 deletions
@@ -325,6 +325,57 @@ spec:
token: ${{ each.value.token }}
```
### Defining a Secrets Schema
You can define a JSON Schema for secrets that will be validated when a task is created. This is useful when secrets are passed programmatically (e.g., via CI/CD pipelines or API calls) rather than through the UI form. The schema ensures that required secrets are provided before task execution begins.
```yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: publish-to-npm
title: Publish to NPM
spec:
owner: backstage/techdocs-core
type: service
# Define required secrets with a JSON Schema
secrets:
schema:
required:
- NPM_TOKEN
properties:
NPM_TOKEN:
type: string
description: NPM authentication token for publishing
parameters:
- title: Package Details
properties:
packageName:
type: string
title: Package Name
steps:
- id: publish
action: npm:publish
input:
packageName: ${{ parameters.packageName }}
token: ${{ secrets.NPM_TOKEN }}
```
When a task is created without the required secrets, the API returns a `400` error with a descriptive message:
```json
{
"errors": [
{
"message": "secrets.NPM_TOKEN is required"
}
]
}
```
### Custom step layouts
If you find that the default layout of the form used in a particular step does not meet your needs then you can supply your own [custom step layout](./writing-custom-step-layouts.md).