Add authentication: admin/agent bearer tokens for the API, login for the dashboard
control-api: every route now carries a mandatory access level (admin / agent / open) in a route table. All /api/v1/admin/* require the admin token; the write calls of validator-agent and prober (self-check, events, results, complete) require a separate static agent token; register, heartbeat and fetching the assignment stay open. Tokens come from env vars, are compared in constant time and never logged. An empty token leaves that level open with a startup warning (backward compatible). validator-agent / prober: apiclient sends the agent token only to control-api. admin-dashboard: login/password (from env) with a stateless HMAC session cookie, Origin-based CSRF check, per-IP brute-force throttle, HX-Redirect for htmx polls, logout in the sidebar; the dashboard calls control-api with the admin token. Login page layout fixed after review. Also: env plumbing in docker-compose/rxprod-compose/systemd/config examples, e2e script with token assertions, tests, docs (API, SETUP, USAGE, DASHBOARD, README), plan and review under docs/changes/, bin/ rebuilt with new SHA256SUMS. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
972ad47d0c
commit
debf2afed2
67 files changed
+2050
-105
No files matched your search
+33
-9
@@ -4,15 +4,13 @@ Control API — единственная точка входа в систему
|
||||
`prober` и оператора (администратора). Все данные передаются в формате
|
||||
JSON, базовый префикс прикладных методов — `/api/v1`.
|
||||
|
||||
> **Важно.** На данный момент API не защищён аутентификацией/авторизацией
|
||||
> — эндпоинты доступны любому, кто может достучаться до порта control-api
|
||||
> по сети. Это касается и методов из раздела
|
||||
> [«Управление очередью и конфигурацией»](#управление-очередью-и-конфигурацией)
|
||||
> ниже — они меняют, что и как проверяется, без подтверждения личности
|
||||
> вызывающего. Для эксплуатации за пределами доверенного сегмента сети
|
||||
> обязательно ограничьте доступ на уровне сети/файрвола (см.
|
||||
> [SETUP.md](SETUP.md#сетевые-доступы)). Добавление bearer-токена — известное
|
||||
> направление доработки, в текущей версии не реализовано.
|
||||
> **Аутентификация.** Доступ к API определяется двумя статическими
|
||||
> bearer-токенами — см. [«Аутентификация»](#аутентификация). Токен задаётся
|
||||
> переменной окружения; **если токен не задан, соответствующий уровень остаётся
|
||||
> открытым** (control-api стартует с предупреждением в логе) — так сделано для
|
||||
> обратной совместимости. Поэтому для эксплуатации за пределами доверенного
|
||||
> сегмента сети токены нужно задать, а доступ дополнительно ограничить на уровне
|
||||
> сети/файрвола (см. [SETUP.md](SETUP.md#сетевые-доступы)).
|
||||
|
||||
Базовый URL в примерах — `http://control-api.internal:8080`, замените на
|
||||
адрес вашего стенда (см. `server.listen_addr` в конфиге control-api).
|
||||
@@ -23,6 +21,7 @@ JSON, базовый префикс прикладных методов — `/ap
|
||||
|
||||
## Содержание
|
||||
|
||||
- [Аутентификация](#аутентификация)
|
||||
- [Общие соглашения](#общие-соглашения)
|
||||
- [Методы для validator-agent](#методы-для-validator-agent)
|
||||
- [Методы для prober](#методы-для-prober)
|
||||
@@ -33,6 +32,31 @@ JSON, базовый префикс прикладных методов — `/ap
|
||||
- [Модель состояний и связь методов с ней](#модель-состояний-и-связь-методов-с-ней)
|
||||
- [Сквозной пример работы (curl)](#сквозной-пример-работы-curl)
|
||||
|
||||
## Аутентификация
|
||||
|
||||
Токен передаётся заголовком `Authorization: Bearer <токен>`. Токены статические, **без срока жизни**; ротация — смена
|
||||
переменной окружения и перезапуск. Сравнение выполняется в константное время.
|
||||
|
||||
| Уровень | Токен (переменная на control-api) | Какие методы |
|
||||
|---|---|---|
|
||||
| **admin** | `CONTROL_API_ADMIN_TOKEN` | все `/api/v1/admin/*` (очередь, реестр, автоцикл, `config/*`) |
|
||||
| **agent** | `CONTROL_API_AGENT_TOKEN` | запись результатов: `POST /agents/{id}/self-check`, `/events`, `/results`, `/complete` и `POST /probers/{site_id}/results` |
|
||||
| **открыто** | — | `GET /healthz`; `POST /agents/register`, `POST /agents/{id}/heartbeat`, `GET /agents/{id}/assignment`; `POST /probers/register`, `POST /probers/{site_id}/heartbeat`, `GET /probers/{site_id}/assignments` |
|
||||
|
||||
- Токены разные: токен администратора **не** подходит для методов агентов, и наоборот.
|
||||
- Валидатор и пробер могут без токена зарегистрироваться, слать heartbeat и забирать задание (настройку); отправка результатов без токена агентов — `401`.
|
||||
- Имена переменных меняются в секции `auth` конфига control-api (`admin_token_env`, `agent_token_env`); сами значения в YAML не хранятся.
|
||||
- Ответ при отказе: `401 {"error": "unauthorized"}` с заголовком `WWW-Authenticate: Bearer`.
|
||||
- Токен не задан (пустая переменная) — уровень открыт; в логе control-api при старте предупреждение. Токены нужно генерировать случайными: `openssl rand -hex 32`.
|
||||
- Токены уходят открытым текстом, если TLS не терминируется перед control-api, — публикуйте API через reverse-proxy с TLS.
|
||||
|
||||
```bash
|
||||
export ADMIN_TOKEN=... # значение CONTROL_API_ADMIN_TOKEN
|
||||
curl -s -H "Authorization: Bearer $ADMIN_TOKEN" http://<control-api>:8080/api/v1/admin/status
|
||||
```
|
||||
|
||||
> Во всех примерах `curl` ниже заголовок `Authorization` для краткости опущен; если токен администратора задан, добавляйте его к методам `/api/v1/admin/*`.
|
||||
|
||||
## Общие соглашения
|
||||
|
||||
- Тело запроса и ответа — JSON (`Content-Type: application/json`).
|
||||
|
||||
Reference in new issue
Block a user