docs: add design doc for config download token
This commit is contained in:
77
docs/plans/2026-03-01-config-download-token-design.md
Normal file
77
docs/plans/2026-03-01-config-download-token-design.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Config Download Token Design
|
||||
|
||||
**Date:** 2026-03-01
|
||||
**Status:** Approved
|
||||
|
||||
## Problem
|
||||
|
||||
Downloading a generated config ZIP from the command line requires extracting an httpOnly OIDC
|
||||
session cookie from the browser, which is fragile and not scriptable. Users need a stable,
|
||||
per-config token they can embed in automation scripts.
|
||||
|
||||
## Solution
|
||||
|
||||
Add a `download_token` field to each `Config`. The existing generate endpoint accepts this token
|
||||
in the POST body as an alternative to OIDC cookie auth, allowing unauthenticated-but-authorized
|
||||
downloads.
|
||||
|
||||
## Data Model
|
||||
|
||||
- Add `download_token: str` column to `configs` table.
|
||||
- Value: `secrets.token_urlsafe(32)` — 32 bytes of URL-safe random data (43 characters).
|
||||
- Generated automatically on config creation.
|
||||
- Stored as plaintext (the token is low-value; it only grants read access to a single config's
|
||||
generated output).
|
||||
- Alembic migration backfills existing configs with auto-generated tokens.
|
||||
|
||||
## API Changes
|
||||
|
||||
### Modified: `POST /api/configs/{id}/generate`
|
||||
|
||||
Accepts an optional JSON body:
|
||||
|
||||
```json
|
||||
{ "token": "..." }
|
||||
```
|
||||
|
||||
Auth logic (either is sufficient):
|
||||
1. Valid OIDC `access_token` cookie + `owner_id` match
|
||||
2. `token` in body matches `config.download_token` (no owner filter needed)
|
||||
|
||||
Error responses:
|
||||
- No cookie and no/wrong token → 401
|
||||
- Valid token but wrong config ID → 404
|
||||
|
||||
Example curl usage:
|
||||
|
||||
```bash
|
||||
curl -X POST "https://host/api/configs/1/generate?format=zip" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"token": "abc..."}' -o shorewall.zip
|
||||
```
|
||||
|
||||
### New: `POST /api/configs/{id}/regenerate-token`
|
||||
|
||||
- OIDC-protected, owner-only.
|
||||
- Generates a new `secrets.token_urlsafe(32)`, saves it to the config, returns it.
|
||||
- Response: `{ "download_token": "..." }`
|
||||
- Non-owner → 403.
|
||||
|
||||
## Schema Changes
|
||||
|
||||
- `ConfigOut` gains `download_token: str`.
|
||||
- New `GenerateRequest` Pydantic model: `token: Optional[str] = None`.
|
||||
|
||||
## Frontend Changes
|
||||
|
||||
On the Config Detail page header area (above the tabs):
|
||||
|
||||
- Read-only text field showing `download_token`.
|
||||
- Copy-to-clipboard icon button.
|
||||
- "Regenerate" button that calls the new endpoint and updates the displayed value.
|
||||
|
||||
## Migration
|
||||
|
||||
New Alembic migration `0012_config_add_download_token.py`:
|
||||
- Add `download_token` column with `server_default=''`.
|
||||
- Backfill with `secrets.token_urlsafe(32)` for all existing rows via a data migration step.
|
||||
Reference in New Issue
Block a user