Локальный audit_log (миграции pg/sqlite), GET /v1/audit, запись на CRUD и async push в auth-portal (source_app=bgp). Co-authored-by: Cursor <cursoragent@cursor.com>
168 lines
8.8 KiB
Markdown
168 lines
8.8 KiB
Markdown
# REST API: обзор и ссылки
|
||
|
||
Полный контракт запросов и ответов описан в **[openapi.yaml](openapi.yaml)** (OpenAPI 3.1). Этот файл — **источник правды**. Краткий контекст и ранние таблицы — в [evobgp-api-sketches.md](evobgp-api-sketches.md) (черновик, не заменяет OpenAPI).
|
||
|
||
## Базовый URL и версия
|
||
|
||
- Все функциональные маршруты API используют префикс **`/v1`** (например `https://api.example.com/v1/modules`).
|
||
- Версия сборки: **`GET /v1/version`** (публичный маршрут, без Bearer).
|
||
|
||
## Публичные маршруты (без `Authorization`)
|
||
|
||
| Метод | Путь | Назначение |
|
||
|-------|------|------------|
|
||
| `GET` | `/v1/health` | Liveness |
|
||
| `GET` | `/v1/ready` | Readiness (зависимости, например БД) |
|
||
| `GET` | `/v1/version` | Версия / метаданные сборки |
|
||
|
||
Дополнительно на корне сервера (вне `/v1`):
|
||
|
||
| Метод | Путь | Назначение |
|
||
|-------|------|------------|
|
||
| `GET` | `/metrics` | Метрики Prometheus |
|
||
|
||
Все остальные запросы под **`/v1/...`**, кроме перечисленных выше трёх `GET`, проходят через middleware и требуют **`Authorization: Bearer <api_key>`** (см. [access.md](access.md)).
|
||
|
||
## Группы маршрутов (соответствие тегам OpenAPI)
|
||
|
||
Ниже — обзор того, что реализовано в коде (`internal/httpapi/routes.go`, `routes_crud.go`). Детали тел, кодов ответов и схем — только в OpenAPI.
|
||
|
||
### Modules
|
||
|
||
- `GET /v1/modules`, `GET /v1/modules/{module_id}`
|
||
- `POST /v1/modules`, `PATCH /v1/modules/{module_id}`, `DELETE /v1/modules/{module_id}`
|
||
- `GET|POST|PATCH|DELETE` для `.../cdn-sources`, `.../as-entries`, `.../domain-entries`, `.../ip-range-entries`
|
||
- `POST /v1/modules/{module_id}/refresh`
|
||
- `GET /v1/router-lists/catalog` — агрегированный каталог модулей/entries/communities
|
||
|
||
### Lookup
|
||
|
||
- `GET /v1/lookup?q=` — быстрая проверка IP или FQDN в списках (viewer+).
|
||
- Слой `entry`: `IP_RANGES` (`CIDR.Contains`) / `DOMAINS` (нормализованный FQDN).
|
||
- Слой `snapshot`: материализованные `module_prefix_snapshot` (для IP — Contains по всем модулям; для домена — `source=domain` у matched DOMAINS-модулей).
|
||
- В каждом матче — community (`community_id` / значение / title).
|
||
- Live DoH не выполняется. Контракт: OpenAPI `lookupMembership`.
|
||
|
||
### DoH profiles
|
||
|
||
- `GET|POST /v1/doh-profiles`
|
||
- `GET|PATCH|DELETE /v1/doh-profiles/{id}`
|
||
|
||
### Communities
|
||
|
||
- `GET|POST /v1/communities`
|
||
- `GET|PATCH|DELETE /v1/communities/{id}`
|
||
|
||
### API keys
|
||
|
||
- `GET /v1/auth/session` — tenant и роль текущего ключа
|
||
- `GET|POST /v1/api-keys` — список и создание (operator)
|
||
- `GET|PATCH|DELETE /v1/api-keys/{id}`, `POST /v1/api-keys/{id}/rotate`
|
||
|
||
### Peers
|
||
|
||
- `GET /v1/peers`, `POST /v1/peers`
|
||
- `GET|PATCH|DELETE /v1/peers/{id}`
|
||
- Для `POST|PATCH|DELETE` peer запускается быстрый job `peer_reconcile` (без module ingest/сбора префиксов); после него автоматически ставится apply на спикеры.
|
||
|
||
### Speakers
|
||
|
||
- `GET /v1/speakers`, `POST /v1/speakers`
|
||
- `GET|PATCH /v1/speakers/{speaker_id}` (в коде идентификатор в пути — `speaker_id`; в части маршрутов apply используется `{id}` — смотрите OpenAPI и реализацию)
|
||
|
||
Уточнение по коду: для apply на одном спикере зарегистрирован маршрут `POST /speakers/{id}/apply` внутри v1 mux → **`POST /v1/speakers/{id}/apply`**.
|
||
|
||
### Revisions
|
||
|
||
- `GET /v1/revisions`, `GET /v1/revisions/{revision_id}`
|
||
- `GET /v1/revisions/{revision_id}/prefixes`
|
||
- `GET /v1/revisions/{revision_id}/preview`
|
||
- `GET /v1/revisions/{revision_a}/diff/{revision_b}`
|
||
- `POST /v1/revisions/{revision_id}/rollback`
|
||
|
||
### Deploy и BIRD
|
||
|
||
- `POST /v1/apply`
|
||
- `POST /v1/speakers/{id}/apply`
|
||
- `POST /v1/bird/reload`
|
||
|
||
### Jobs
|
||
|
||
- `GET /v1/jobs`, `GET /v1/jobs/{job_id}`
|
||
- `POST /v1/jobs/{job_id}/cancel`
|
||
|
||
### Node (роль `node`)
|
||
|
||
- `GET /v1/speakers/{speaker_id}/revisions/latest`
|
||
- `GET /v1/speakers/{speaker_id}/bundle/{revision_id}`
|
||
- `POST /v1/nodes/enroll`
|
||
|
||
### Settings
|
||
|
||
- `GET /v1/settings`, `PATCH /v1/settings` — tenant KV (`global_settings`): BIRD, `revision_retention_minutes`, `runtime_logs_*` (автоочистка FS), произвольные ключи. Чтение — viewer+; `PATCH` — operator+.
|
||
|
||
### RuntimeLogs
|
||
|
||
Файловые логи Docker-сервисов (sidecar `stack-runtime-logs`). FS API **только** в процессе **`evobgp-all`** при `EVOBGP_SERVICE=evobgp-all` и `EVOBGP_RUNTIME_LOGS_DIR` (см. [access.md](access.md)). Иначе `GET`/`DELETE` по файлам → **503** (`runtime_logs_unavailable`).
|
||
|
||
| Метод | Путь | Роль | Назначение |
|
||
|-------|------|------|------------|
|
||
| `GET` | `/v1/runtime-logs/files` | viewer+ | Список `*.log` (имя, размер, mtime) |
|
||
| `GET` | `/v1/runtime-logs/files/{filename}` | viewer+ | Хвост файла (`?lines=`, `?bytes=`, `?grep=`) |
|
||
| `DELETE` | `/v1/runtime-logs/files/{filename}` | operator+ | Синхронная очистка (`?mode=truncate\|delete`, default truncate); max 512 MiB |
|
||
| `GET` | `/v1/runtime-logs/cleanup-audit` | viewer+ | Пагинированный audit очистки (`cursor`, `limit`); **без FS volume** |
|
||
| `GET` | `/v1/runtime-logs/auto-estimate` | operator+ | Файлы выше порога из tenant settings |
|
||
| `POST` | `/v1/runtime-logs/auto-run` | operator+ | Немедленный прогон (`?dry_run=true`); audit с `actor_prefix=auto:scheduler` |
|
||
|
||
`{filename}` — только basename, паттерн `^[a-z0-9][a-z0-9_.-]*\.log$`. Очистка пишет строку в таблицу `runtime_log_cleanup_audit` (миграция `000026`).
|
||
|
||
## CRUD audit (`/v1/audit`)
|
||
|
||
Локальный журнал изменений CRUD (modules, peers, settings, API keys, …). Миграция `000030_audit_log`. Чтение — `bgp:monitoring:read` (viewer+).
|
||
|
||
| Метод | Путь | Роль | Назначение |
|
||
|-------|------|------|------------|
|
||
| `GET` | `/v1/audit` | viewer+ | Пагинированный audit (`cursor`, `limit`, опционально `action`, `severity`) |
|
||
|
||
При `AUTH_PORTAL_URL` + `AUTH_AUDIT_INGEST_SECRET` каждая запись дополнительно отправляется в auth-portal (`POST /api/v1/ingest/audit`, `source_app=bgp`).
|
||
|
||
## Соглашения из OpenAPI
|
||
|
||
- Ошибки в стиле **RFC 9457** (`application/problem+json`): `type`, `title`, `status`, `detail`, и т.д.
|
||
- Пагинация списков: query-параметры `cursor`, `limit`; в ответе часто `items`, `next_cursor`, `has_more`.
|
||
- Заголовок **`Idempotency-Key`** для идемпотентных мутаций (рекомендации — в описаниях операций в OpenAPI).
|
||
- Заголовок **`X-Tenant-Id`** описан в спецификации для супер-ролей; в **текущей реализации Go** tenant берётся **только из API-ключа**, заголовок в обработчиках не переключает контекст (см. [access.md](access.md)).
|
||
|
||
## Как смотреть документацию API
|
||
|
||
- Статическая страница Redoc: [openapi.html](openapi.html) (инструкции для Gitea и пересборки — [OPENAPI-GITEA.md](OPENAPI-GITEA.md)).
|
||
- Пересборка после правок YAML (из корня репозитория, PowerShell):
|
||
|
||
```powershell
|
||
.\scripts\build-openapi-html.ps1
|
||
```
|
||
|
||
## Примеры вызовов
|
||
|
||
PowerShell, список модулей (подставьте свой токен и URL):
|
||
|
||
```powershell
|
||
$base = "http://localhost:8080"
|
||
$token = "opkey"
|
||
$h = @{ Authorization = "Bearer $token" }
|
||
Invoke-RestMethod -Uri "$base/v1/modules" -Headers $h
|
||
```
|
||
|
||
Эквивалент с `curl` (если установлен):
|
||
|
||
```text
|
||
curl -s -H "Authorization: Bearer opkey" http://localhost:8080/v1/modules
|
||
```
|
||
|
||
CORS для браузерных клиентов настраивается переменной **`EVOBGP_CORS_ORIGINS`** на стороне API.
|
||
|
||
## Связанные документы
|
||
|
||
- [access.md](access.md) — ключи и роли.
|
||
- [overview.md](overview.md) — продуктовые возможности.
|