diff --git a/docs/repos/cryptify.md b/docs/repos/cryptify.md index 2f6d0a9..28355c0 100644 --- a/docs/repos/cryptify.md +++ b/docs/repos/cryptify.md @@ -80,7 +80,7 @@ When a request would push the sender over the per-upload or the rolling-window l `limit` is either `"per_upload"` or `"rolling_window"`. `resets_at` is an RFC 3339 timestamp for when the oldest counted upload expires from the rolling window. It is `null` for `per_upload` rejections, since the per-upload limit does not reset. -`GET /usage` returns the current state for the authenticated sender, including `used_bytes`, `limit_bytes`, `per_upload_limit_bytes`, `window_days`, and `resets_at`. When the request includes a validated `Authorization: Bearer PG-…`, the response describes the per-tenant bucket (`api-key:`); otherwise it describes the per-email bucket. +`GET /usage` returns the current state for the caller, including `used_bytes`, `limit_bytes`, `per_upload_limit_bytes`, `window_days`, and `resets_at`. It requires a validated `Authorization: Bearer PG-…` API key and describes that key's per-tenant bucket (`api-key:`). A missing or invalid key returns `401`; if the key cannot be confirmed because PKG is unreachable, the endpoint returns `503`. The `email` query parameter is optional and only echoed back in the response, it no longer selects which bucket is reported. [Source: src/store.rs#L11-L15](https://github.com/encryption4all/cryptify/blob/58883a86b369af08d92db93aa1025f9eba3c73eb/src/store.rs#L11-L15) @@ -114,8 +114,24 @@ Cryptify exposes a file upload/download API. An OpenAPI 3.0 specification is ava - `POST /fileupload/finalize/{uuid}`: Finalize the upload (sends the recipient notification email if `notifyRecipients` was `true` on init). - `GET /fileupload/{uuid}/status`: Read rolling-token state to resume an in-flight upload across a page refresh or tab crash. Authenticated via `X-Recovery-Token`. - `GET /filedownload/{uuid}`: Download a file. Supports resumable downloads via the HTTP `Range` header (see [Range support on `/filedownload`](#range-support-on-filedownload) below). +- `GET /email-template`: Return the email template pg-pkg has linked to the caller's API key. Authenticated with the same `Authorization: Bearer PG-…` key as the upload endpoints (see [Email template retrieval](#email-template-retrieval) below). - `GET /metrics`: Prometheus text-format metrics for monitoring (see [Metrics](#metrics) below). Unauthenticated; intended for scraping over a restricted network only. +### Email template retrieval + +`GET /email-template` returns the email template that pg-pkg has linked to the caller's API key. The key is validated through the same `Authorization: Bearer PG-…` flow the upload endpoints use, so no separate auth path is involved. + +| Case | Status | Body | +|---|---|---| +| Valid key with a template configured | `200` | `{ tenant_id, email_template }` | +| Missing or invalid key | `401` | error body | +| Valid key, no template configured | `404` | error body | +| PKG unreachable during validation | `503` | error body | + +The template is resolved on the PKG side and returned as-is, keyed on the validated tenant. + +[Source: api-description.yaml#L434-L465](https://github.com/encryption4all/cryptify/blob/0946c066a805f1dad73c3966fb70b7aba90fea35/api-description.yaml#L434-L465) + ### `POST /fileupload/init` request body | Field | Type | Required | Description | diff --git a/docs/repos/postguard.md b/docs/repos/postguard.md index e5fd906..395b5f8 100644 --- a/docs/repos/postguard.md +++ b/docs/repos/postguard.md @@ -143,7 +143,13 @@ cargo run --release --bin pg-pkg server \ |---|---|---| | `IRMA_SERVER` | Yivi/IRMA server URL | `https://is.yivi.app` | | `DATABASE_URL` | PostgreSQL connection string | none | -| `PKG_ALLOWED_ORIGINS` | Comma-separated CORS allowlist (e.g. `https://postguard.eu,https://postguard.nl`). `*` keeps the legacy any-origin behaviour and logs a warning at startup. Also available as `--allowed-origins`. | `*` | +| `PKG_ALLOWED_ORIGINS` | Comma-separated CORS allowlist (e.g. `https://postguard.eu,https://postguard.nl`). Required: the server refuses to start without it. Pass `*` to deliberately allow any origin (this logs a warning at startup). Also available as `--allowed-origins`. | required | +| `PKG_RATELIMIT_PER_SECOND` | Sustained request rate per client IP for the whole `/v2` scope. Also available as `--ratelimit-per-second`. | `10` | +| `PKG_RATELIMIT_BURST` | Burst allowance for the general `/v2` limit. Also available as `--ratelimit-burst`. | `50` | +| `PKG_RATELIMIT_SENSITIVE_PER_SECOND` | Sustained request rate per client IP for the key-issuing endpoints (`POST /start`, `GET /key`, `GET /key/{timestamp}`, `POST /sign/key`, `GET /api-key/validate`). Also available as `--ratelimit-sensitive-per-second`. | `2` | +| `PKG_RATELIMIT_SENSITIVE_BURST` | Burst allowance for the sensitive-endpoint limit. Also available as `--ratelimit-sensitive-burst`. | `10` | +| `PKG_RATELIMIT_DISABLED` | Set to `true` to build the limiter in permissive mode (every request passes). Use behind a trusted proxy that does its own rate limiting. Also available as `--ratelimit-disabled`. | `false` | +| `PKG_RATELIMIT_TRUST_FORWARDED_FOR` | Set to `true` to key the limiter on the rightmost `X-Forwarded-For` entry instead of the TCP peer address, so per-client limiting works behind a trusted reverse proxy. Off by default so a directly exposed PKG never trusts client-supplied headers. Also available as `--ratelimit-trust-forwarded-for`. | `false` | | `RUST_LOG` | Log level (`debug`, `info`, `warn`, `error`) | none | ### Running the PKG Server @@ -255,6 +261,12 @@ Request body for signing keys: | `GET` | `/health` | Health check. | | `GET` | `/metrics` | Prometheus metrics. | +### Rate limiting + +The `/v2` scope is rate limited per client IP in two tiers. The general tier covers the whole scope; the sensitive tier covers the key-issuing endpoints (`POST /start`, `GET /key`, `GET /key/{timestamp}`, `POST /sign/key`, `GET /api-key/validate`) with a tighter limit, applied before authentication runs. Requests over the limit get `429 Too Many Requests` with a `Retry-After` header. The limits are global across worker processes and tunable through the `PKG_RATELIMIT_*` variables listed under [Environment Variables](#environment-variables). + +The limiter keys on the TCP peer address by default. When the PKG runs behind a trusted reverse proxy, set `PKG_RATELIMIT_TRUST_FORWARDED_FOR=true` so it keys on the rightmost `X-Forwarded-For` entry (the hop the trusted proxy appends) instead of the proxy's own address. Only the rightmost entry is trusted; anything left of it is client-supplied and spoofable. + ### Authentication The PKG supports two authentication methods: