feat(httpapi): add local audit log with portal dual-write
Локальный audit_log (миграции pg/sqlite), GET /v1/audit, запись на CRUD и async push в auth-portal (source_app=bgp). Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
| `AUTH_JWT_SECRET` / `EVOBGP_AUTH_JWT_SECRET` | Тот же секрет, что `JWT_SECRET` портала (HS256) |
|
||||
| `AUTH_ISSUER` | Issuer JWT (как на портале) |
|
||||
| `AUTH_PORTAL_URL` | URL портала (также `GET /v1/auth/config`) |
|
||||
| `AUTH_AUDIT_INGEST_SECRET` / `EVOBGP_AUTH_AUDIT_INGEST_SECRET` | Shared secret для push CRUD audit в auth-portal (`POST /api/v1/ingest/audit`, `source_app=bgp`) |
|
||||
| `EVOBGP_PORTAL_TENANT_ID` | Fallback tenant для portal JWT, если в токене нет `bgp_tenant_id` / `tenants.bgp` |
|
||||
|
||||
Источник tenant (по приоритету):
|
||||
|
||||
+10
@@ -116,6 +116,16 @@
|
||||
|
||||
`{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`, и т.д.
|
||||
|
||||
@@ -59,6 +59,8 @@ tags:
|
||||
description: Сессия текущего API-ключа (tenant и роль).
|
||||
- name: Monitoring
|
||||
description: Наблюдаемость PostgreSQL и корреляция (instance-level, viewer+). Maintenance — operator.
|
||||
- name: Audit
|
||||
description: Журнал CRUD-изменений tenant (локально + опциональный push в auth-portal). Чтение — bgp:monitoring:read.
|
||||
- name: Maintenance
|
||||
description: Политики обслуживания PostgreSQL (instance-scoped). CRUD и запуск — operator.
|
||||
- name: RuntimeLogs
|
||||
@@ -1297,6 +1299,70 @@ components:
|
||||
has_more:
|
||||
type: boolean
|
||||
|
||||
AuditSeverity:
|
||||
type: string
|
||||
enum: [info, warning, critical]
|
||||
|
||||
AuditLogEntry:
|
||||
type: object
|
||||
required:
|
||||
[id, tenant_id, event_id, source_app, action, severity, summary, created_at]
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/ResourceId"
|
||||
tenant_id:
|
||||
$ref: "#/components/schemas/ResourceId"
|
||||
event_id:
|
||||
type: string
|
||||
description: Stable id for portal ingest deduplication (prefix bgp-).
|
||||
source_app:
|
||||
type: string
|
||||
enum: [bgp]
|
||||
action:
|
||||
type: string
|
||||
description: Machine action key (e.g. bgp.module.create).
|
||||
severity:
|
||||
$ref: "#/components/schemas/AuditSeverity"
|
||||
actor_user_id:
|
||||
type: ["string", "null"]
|
||||
actor_email:
|
||||
type: ["string", "null"]
|
||||
actor_name:
|
||||
type: ["string", "null"]
|
||||
actor_api_key_prefix:
|
||||
type: ["string", "null"]
|
||||
target_type:
|
||||
type: ["string", "null"]
|
||||
enum: [app_resource, null]
|
||||
target_id:
|
||||
type: ["string", "null"]
|
||||
summary:
|
||||
type: string
|
||||
details:
|
||||
type: ["object", "null"]
|
||||
additionalProperties: true
|
||||
ip:
|
||||
type: ["string", "null"]
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
portal_pushed_at:
|
||||
type: ["string", "null"]
|
||||
format: date-time
|
||||
|
||||
AuditLogList:
|
||||
type: object
|
||||
required: [items]
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/AuditLogEntry"
|
||||
next_cursor:
|
||||
type: string
|
||||
has_more:
|
||||
type: boolean
|
||||
|
||||
RuntimeLogAutoPolicy:
|
||||
type: object
|
||||
properties:
|
||||
@@ -4520,6 +4586,40 @@ paths:
|
||||
default:
|
||||
$ref: "#/components/responses/DefaultProblem"
|
||||
|
||||
/v1/audit:
|
||||
get:
|
||||
tags: [Audit]
|
||||
summary: Журнал CRUD audit tenant
|
||||
description: |
|
||||
Локальный журнал изменений (modules, peers, settings, API keys и т.д.).
|
||||
При настроенных `AUTH_PORTAL_URL` + `AUTH_AUDIT_INGEST_SECRET` события также
|
||||
отправляются в auth-portal ingest (`source_app=bgp`).
|
||||
operationId: listAuditLog
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/TenantId"
|
||||
- $ref: "#/components/parameters/Cursor"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
- name: action
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: Filter by action prefix/key (exact match).
|
||||
- name: severity
|
||||
in: query
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuditSeverity"
|
||||
responses:
|
||||
"200":
|
||||
description: Успешно.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuditLogList"
|
||||
"400":
|
||||
$ref: "#/components/responses/BadRequest"
|
||||
default:
|
||||
$ref: "#/components/responses/DefaultProblem"
|
||||
|
||||
/v1/settings:
|
||||
get:
|
||||
tags: [Settings]
|
||||
|
||||
Reference in New Issue
Block a user