86 lines
6.7 KiB
Markdown
86 lines
6.7 KiB
Markdown
# План разработки — IP WhiteList Microservice
|
||
|
||
> **Автор:** GitHub Copilot (Gemini 3.1 Pro Preview)
|
||
> **Дата:** 2026-05-29
|
||
|
||
---
|
||
|
||
## 1. Анализ предыдущих планов и моё видение
|
||
|
||
Я изучил ТЗ и варианты коллег (DeepSeek, Claude, GPT-5.4).
|
||
- **DeepSeek** предложил избыточный Async/ORM подход.
|
||
- **Claude** упростил до psycopg2 и HTMX, но оставил много "белых пятен" в работе с Keycloak.
|
||
- **GPT-5.4** дал отличный продуктовый разбор рисков (гонки, лимиты, нормализация), но оставил проект заблокированным до "уточнения с командой Keycloak".
|
||
|
||
**Мой подход (Gemini 3.1 Pro):**
|
||
Мы не будем блокировать разработку в ожидании ответов от админов Keycloak. Разночтения с форматами claims (как выглядит админ, как выглядит мульти-аккаунт) мы вынесем в **гибкую конфигурацию (.env)**. Если формат токена изменится, нам не придется править код, мы просто поменяем переменные окружения.
|
||
Также мы откажемся от сторонней библиотеки `netaddr`, так как встроенный модуль Python `ipaddress` имеет встроенную функцию `collapse_addresses()`, которая идеально решает задачу агрегации по ТЗ.
|
||
|
||
---
|
||
|
||
## 2. Технологический стек
|
||
|
||
* **Бэкенд:** FastAPI (Python 3.11+). Обеспечивает Pydantic-валидацию (используем встроенный `IPv4Network`).
|
||
* **СУБД:** PostgreSQL.
|
||
* **Доступ к данным:** SQLModel (надстройка над SQLAlchemy). Дает удобство ORM без избыточной сложности, синхронный режим.
|
||
* **Суммаризация (Агрегация):** Standard Library Python `ipaddress.collapse_addresses`.
|
||
* **Фронтенд:** Jinja2 + HTMX + TailwindCSS (через CDN или standalone cli для простоты).
|
||
* **Авторизация:** Dependency injection в FastAPI для OIDC/JWT. Заглушка (MockOIDC) для локальной разработки.
|
||
|
||
---
|
||
|
||
## 3. Решение узких мест (Архитектурные решения)
|
||
|
||
**Проблема 1: Как определять администратора и принадлежность к компаниям из токена?**
|
||
*Решение:* Выносим структуру токена в `Config`.
|
||
```env
|
||
OIDC_COMPANY_CLAIM="client_id" # Может быть списком или строкой, обработаем оба варианта
|
||
OIDC_ADMIN_CLAIM_KEY="roles"
|
||
OIDC_ADMIN_CLAIM_VALUE="whitelist-admin"
|
||
```
|
||
Код будет динамически проверять, совпали ли значения, указанные в конфиге, с данными из токена.
|
||
|
||
**Проблема 2: Гонки при записи и лимиты**
|
||
*Решение:*
|
||
1. Проверка лимита делается запросом `SELECT count(*) FROM entries WHERE company_id = X AND deleted_at IS NULL FOR UPDATE`. Блокировка на чтение защитит транзакцию от гонок.
|
||
2. В БД создадим уникальный индекс `CREATE UNIQUE INDEX unique_active_cidr ON entries (company_id, value_cidr) WHERE deleted_at IS NULL;` для защиты от дубликатов на уровне СУБД.
|
||
|
||
**Проблема 3: Пересечения внутри компании**
|
||
*Решение:* Перед INSERT/UPDATE выгружаем все активные подсети компании и проверяем через `new_cidr.overlaps(existing_cidr)`. Выгрузка делается в рамках заблокированной транзакции (см. пункт выше).
|
||
|
||
---
|
||
|
||
## 4. Поэтапный план реализации
|
||
|
||
### Этап 1. Ядро и База данных (Бизнес-логика)
|
||
- [ ] Инициализация FastAPI проекта, настройка SQLModel.
|
||
- [ ] Определение сущностей БД: `Company`, `WhitelistEntry` (CIDR хранится как `String`, но Pydantic проверяет `IPv4Network`), `AuditLog`.
|
||
- [ ] Валидаторы (запрещенные списки Приложения А, маска /32 - /22). Нормализация `strict=False` в `ipaddress`, чтобы `192.168.1.5/24` автоматически перегонялось в `192.168.1.0/24`.
|
||
- [ ] Написание Unit-тестов для валидаторов.
|
||
|
||
### Этап 2. Слой данных (CRUD) и защита от гонок
|
||
- [ ] Сервис создания записи: проверка макс. лимита (15 по умолчанию или `company.custom_limit`), поиск пересечений, запись AuditLog.
|
||
- [ ] Сервис Soft-Delete и редактирования.
|
||
- [ ] Тесты CRUD-сервисов.
|
||
|
||
### Этап 3. Авторизация (Keycloak)
|
||
- [ ] Настройка `auth/jwt.py` для валидации RS256 подписей.
|
||
- [ ] Парсинг токена на основе гибких правил из `.env` (роли, список компаний).
|
||
- [ ] FastAPI Security Depends (`get_current_user`).
|
||
|
||
### Этап 4. Внешний API (Export Endpoint)
|
||
- [ ] Роут `GET /api/v1/export/whitelist.txt`.
|
||
- [ ] Выборка всех `value_cidr` где `deleted_at IS NULL`.
|
||
- [ ] Агрегация: `[str(net) for net in ipaddress.collapse_addresses(net_list)]`.
|
||
- [ ] Middleware для ограничения доступа по списку разрешенных `EXPORT_ALLOWED_IPS`.
|
||
|
||
### Этап 5. Пользовательский Интерфейс (UI)
|
||
- [ ] Jinja2 шаблоны и использование HTMX для добавления/удаления строк таблицы без перезагрузки всей страницы.
|
||
- [ ] Отображение предупреждений (нормализация, превышение лимита).
|
||
- [ ] Селектор активной компании.
|
||
- [ ] Панель администратора (все компании, настройка `custom_limit`, просмотр аудита).
|
||
|
||
### Этап 6. Инфраструктура
|
||
- [ ] Dockerfile.
|
||
- [ ] docker-compose окружение (App + Postgres).
|
||
- [ ] Документация (README с описанием переменных окружения). |