IPAM Manager: API, UI-админка, журнал аудита
Backend (FastAPI, SQLAlchemy 2, Alembic, PostgreSQL 16): - организации, VRF, префиксы (дерево, использование, автоназначение), адреса, операторы связи, устройства и типы устройств; JWT, роли admin/viewer; - VRF принадлежит организации (составной FK), смена VRF у префикса переносит поддерево, имя VRF уникально в организации; - журнал аудита: поиск и фильтры, ротация (срок/количество), очистка по паролю с блокировкой, IP клиента и метаданные запроса (X-Forwarded-For только от TRUSTED_PROXIES). UI (web/, без сборки): экраны и диалоги по макетам «IPAM Manager», кликабельные строки реестров, локальные шрифты IBM Plex, собственные выпадающие списки. Окружение: docker-compose (postgres + app), миграции Alembic 0001-0004, scripts/gen_env.py, scripts/seed_demo.py, 11 автотестов (pytest). Документация: README.md и docs/changes/001-005 (планы и итоги). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
commit
a846d30872
64 files changed
+4194
No files matched your search
@@ -0,0 +1,21 @@
|
||||
# Суммаризация: IP-адрес актора и метаданные запроса в журнале (изменение 004)
|
||||
|
||||
## Сделано
|
||||
- **БД (миграция 0004):** `audit_log` + `client_ip INET` (индекс) и `meta JSONB` (`user_agent`, `method`, `path`, `request_id`). Проверено: `upgrade → check (без дрейфа) → downgrade → upgrade`.
|
||||
- **Backend:** `app/request_context.py` — ASGI-middleware кладёт метаданные запроса в `ContextVar`, `audit()` читает их (30 мест вызова не менялись);
|
||||
заголовок `X-Request-ID` в ответах. `X-Forwarded-For` принимается только от прокси из `TRUSTED_PROXIES` (по умолчанию пусто, справа налево — первый недоверенный адрес), IPv4-mapped нормализуется.
|
||||
Системные события (ротация, даже запущенная из запроса) пишутся без IP.
|
||||
- **API:** `AuditOut.client_ip` / `meta`; `GET /audit?client_ip=` (IP или CIDR, 422 на мусор); `q` ищет и по началу IP.
|
||||
- **UI:** колонка «IP-адрес» в таблице журнала (сетка `… 110px 130px 96px`), поиск «Сообщение, ID или IP», в окне записи — IP (с копированием), «Запрос», «User-Agent».
|
||||
- **Кэш статики:** `Cache-Control: no-cache` (ревалидация по ETag) — браузер больше не держит устаревший `app.js`/`styles.css` после обновления
|
||||
(ответ на «не вижу обновлений»; для уже закэшированной версии один раз нужен Ctrl+F5).
|
||||
|
||||
## Проверка
|
||||
- 11 автотестов (2 новых: запись IP/метаданных, фильтр по IP и подсети, игнорирование поддельного `X-Forwarded-For`, пустой IP у системных событий; юнит-тест разбора цепочки прокси) — **11 passed**.
|
||||
- Через LAN-адрес `192.168.5.9:8088`: создание организации и неудачный вход записались с `client_ip = 192.168.5.9`, User-Agent и путём; фильтр `192.168.5.0/24` и поиск `192.168.5` находят записи; UI — колонка и окно записи проверены в браузере, ошибок JS нет.
|
||||
|
||||
## Допущения и ограничения
|
||||
- IP пишется для всех действий из HTTP-запросов (admin и прочие роли, неудачные входы — как `anonymous`); старые записи — «—».
|
||||
- Через `127.0.0.1` Docker подставляет адрес шлюза сети (`172.x.0.1`) — особенность docker-proxy, не ошибка приложения.
|
||||
- За NAT или прокси виден адрес ближайшего недоверенного узла, а не «настоящего» клиента; с reverse-proxy нужно задать `TRUSTED_PROXIES`.
|
||||
- IP — персональные данные: срок хранения определяется ротацией журнала.
|
||||
Reference in new issue
Block a user