From cfbe1fceda9d62edc365b5241ab7e16a293beb41 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Sat, 18 Jul 2026 23:24:00 +0700 Subject: [PATCH] =?UTF-8?q?docs(README):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8E=20=D1=81=20EvoBGP=20=D0=B2=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8E;?= =?UTF-8?q?=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20BGP=20=D0=B8?= =?UTF-8?q?=20=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B5=D0=BD=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=D0=BB=D0=BE=D0=B3=20=D1=80=D0=B0=D0=B7=D1=80?= =?UTF-8?q?=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + docs/integrate-evobgp.md | 98 +++++++++++++++++++++++++++ packages/shared/src/contracts/auth.ts | 22 ++++-- 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 docs/integrate-evobgp.md diff --git a/README.md b/README.md index 41cd20a..8aabeec 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ pnpm --filter web dev # :5175 См. [`docs/integrate-cfdm.md`](docs/integrate-cfdm.md) — то же для Cloudflare Domain Manager (`cfdm:*`, порт Vite `5174`). +См. [`docs/integrate-evobgp.md`](docs/integrate-evobgp.md) — EvoBGP (`bgp:*`), dual auth JWT + API keys, ownership modules/peers/firewall. + Корень: ```bash diff --git a/docs/integrate-evobgp.md b/docs/integrate-evobgp.md new file mode 100644 index 0000000..e9d1060 --- /dev/null +++ b/docs/integrate-evobgp.md @@ -0,0 +1,98 @@ +# Интеграция auth-portal ↔ EvoBGP + +Единый вход: пользователь логинится на auth-portal, получает JWT, переходит в EvoBGP с токеном в URL fragment. EvoBGP API проверяет JWT и права `bgp:*`. API-ключи EvoBGP (viewer/editor/operator/node/firewall) остаются для автоматизации и нод. + +## Архитектура + +``` +Browser → EvoBGP UI (нет token) + → redirect AUTH_PORTAL_URL/?return_to=…/auth/callback + → login + → redirect return_to#access_token=… + → EvoBGP /auth/callback сохраняет token + → API Authorization: Bearer +``` + +Общий секрет: `JWT_SECRET` / `AUTH_JWT_SECRET` (HS256). Issuer: `ISSUER` / `AUTH_ISSUER`. + +App id в портале: **`bgp`**. + +## Permissions ↔ UI + +| Permission | UI | +|------------|-----| +| `bgp:dashboard:read` | `/dashboard` | +| `bgp:modules:read` / `write` | `/modules` | +| `bgp:lookup:read` | `/lookup` | +| `bgp:network:read` / `write` | `/network` (пиры и спикеры) | +| `bgp:directories:read` / `write` | `/directories` | +| `bgp:operations:read` / `write` / `admin` | `/operations` (admin = apply/rollback) | +| `bgp:firewall:read` / `write` | `/firewall` | +| `bgp:schedule:read` / `write` | `/schedule` | +| `bgp:monitoring:read` | `/monitoring` | +| `bgp:access:admin` | `/access` (API-ключи) | +| `bgp:tenant_settings:admin` | `/tenant-settings` | +| `bgp:settings:read` | `/settings` | + +Иерархия: `admin` ⊃ `write` ⊃ `read` в рамках одной секции. + +Пример обычного пользователя: app `bgp` + только `bgp:dashboard:read` и `bgp:lookup:read`. + +### Ownership + +Ресурсы modules / peers / firewall (clients, rules), созданные через JWT, имеют `created_by_user_id`. Видят и редактируют: создатель и portal `is_admin` (или API key `operator`). API keys без user id — tenant-wide scope. + +## Локальный запуск + +### 1. auth-portal + +```bash +cd auth-portal +pnpm install +# JWT_SECRET=dev-secret-change-me +# RETURN_TO_ALLOWLIST=.shnt.top,localhost,http://localhost:5173,…EvoBGP web origin +pnpm --filter @authportal/api dev # :8080 +pnpm --filter web dev # :5175 +``` + +```env +# apps/web/.env.local +VITE_BGP_APP_URL=http://localhost:5176 +``` + +Bootstrap: выдайте app **bgp** и нужные `bgp:*` permissions. + +### 2. EvoBGP + +```env +AUTH_REQUIRED=true +AUTH_JWT_SECRET=dev-secret-change-me +AUTH_ISSUER=https://auth.shnt.top +AUTH_PORTAL_URL=http://localhost:5175 +EVOBGP_PORTAL_TENANT_ID= +``` + +```env +# apps/web/.env.local +VITE_AUTH_ENABLED=true +VITE_AUTH_PORTAL_URL=http://localhost:5175 +``` + +## App Switcher + +Публичный конфиг: `GET {AUTH_PORTAL_URL}/api/v1/app-switcher`. +`CURRENT_APP_ID = bgp`. Редактор ссылок — portal `/admin/apps`. + +## Logout (SSO) + +Очистить локальный JWT → `AUTH_PORTAL_URL/logout` (не `/?return_to=`). + +## Troubleshooting + +| Симптом | Причина | +|---------|---------| +| 401 на API | Нет/битый Bearer; разные `JWT_SECRET` | +| 403 нет доступа к приложению | В portal не выдан app `bgp` | +| 403 на раздел | Нет `bgp:
:…` | +| JWT без tenant | Не задан `EVOBGP_PORTAL_TENANT_ID` | +| return_to rejected | origin EvoBGP не в `RETURN_TO_ALLOWLIST` | diff --git a/packages/shared/src/contracts/auth.ts b/packages/shared/src/contracts/auth.ts index 45624b2..a5c4596 100644 --- a/packages/shared/src/contracts/auth.ts +++ b/packages/shared/src/contracts/auth.ts @@ -31,7 +31,7 @@ export const APPS: AppMeta[] = [ { id: 'bgp', title: 'EvoBGP', - description: 'Модули, peers, сеть и apply', + description: 'Модули, сеть, операции и мониторинг BGP', url: 'https://bgp.shnt.top', }, ] @@ -90,12 +90,24 @@ export const PERMISSION_CATALOG: AppPermissionCatalog[] = [ appId: 'bgp', title: 'EvoBGP', sections: [ + section('dashboard', 'Панель', 'KPI и обзор', ['read']), section('modules', 'Модули', 'Модули префиксов'), - section('peers', 'Peers', 'BGP peers'), - section('network', 'Сеть', 'Спикеры и сеть'), - section('apply', 'Apply', 'Apply / rollback', ['write']), + section('lookup', 'Проверка', 'IP/домен в списках и community', ['read']), + section('network', 'Сеть', 'BGP-пиры и спикеры'), + section('directories', 'Справочники', 'Communities и DoH'), + section('operations', 'Операции', 'Ревизии (read/write) и apply/rollback (admin)', [ + 'read', + 'write', + 'admin', + ]), + section('firewall', 'Файрвол', 'Клиенты и правила'), + section('schedule', 'Задачи', 'Расписание refresh'), + section('monitoring', 'Мониторинг', 'Health и BIRD', ['read']), section('access', 'Доступ', 'API-ключи', ['admin']), - section('settings', 'Настройки', 'Настройки tenant', ['admin']), + section('tenant_settings', 'Настройки BIRD', 'Tenant BIRD config', [ + 'admin', + ]), + section('settings', 'Настройки UI', 'Токен и подключение', ['read']), ], }, ]