Files
Stend_mont/README.md

155 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Portal Stand Access (MVP)
MVP-портал доступа к стендам в Proxmox через единый вход `https://stend.4mont.ru`.
## 1. Архитектура
- `traefik`: входная точка TLS, маршрутизация на API и динамические сессионные контейнеры.
- `api` (FastAPI): auth, ACL, админ API, создание runtime-сессий, cleanup.
- `db` (PostgreSQL): пользователи, сервисы, ACL, сессии, аудит.
- `portal-kiosk` image: Chromium kiosk + noVNC (для WEB target).
- `portal-rdp-proxy` image: xfreerdp + websockify/noVNC proxy до удаленного RDP host:port.
- `portal-universal-runtime` image: универсальный runtime (WEB/RDP), используется общим warm pool `UNIVERSAL_POOL_SIZE`.
- Опциональный prewarm pool:
- глобальный fallback `PREWARM_POOL_SIZE`;
- приоритетный `warm_pool_size` на каждом сервисе в админке.
Поток:
1. Пользователь логинится на `/`.
2. Dashboard показывает разрешённые сервисы.
3. Клик по `/go/<slug>` -> ACL check + проверка `expires_at` + создание записи `sessions` + старт отдельного контейнера.
4. Пользователь редиректится на `/s/<session_id>/`.
5. Traefik отправляет `/s/<session_id>/...` в конкретный runtime контейнер по dynamic labels.
6. Runtime страница шлёт heartbeat в `/api/sessions/<session_id>/touch`.
7. Фоновый cleanup завершает сессии при idle > 30 минут.
При prewarm:
- создаются warm-контейнеры с маршрутом `/svc/<slug>/`;
- клик по плитке использует prewarmed runtime без задержки cold start;
- сессии в БД создаются, но контейнеры остаются пулом (без стопа на каждую сессию).
- в `/admin` есть:
- отдельные разделы Users / WEB / RDP (список + форма выбранной записи);
- `pool size` на сервис;
- кнопка `Prewarm now`;
- health `running/desired` по каждому пулу.
- авто-генерация `slug` из названия (поддержка кириллицы -> латиница).
## 2. Схема БД
Основные таблицы:
- `users`
- `services`
- `user_service_access`
- `sessions`
Дополнительно:
- `audit_logs`
SQL-схема: `scripts/schema.sql`.
## 3. Безопасность
- Пароли: `argon2` (`passlib[argon2]`).
- Cookie auth: `HttpOnly`, `Secure`, `SameSite=Strict`.
- CSRF:
- формы (`/login`) через hidden token + cookie;
- admin JSON API через `X-CSRF-Token`.
- Проверки при каждом запросе:
- пользователь `active=true`;
- `expires_at > now()`;
- ACL на `/go/<slug>`.
- Аудит: события входа и создания сессий в `audit_logs`.
## 4. Файлы
- `docker-compose.yml`
- `traefik/traefik.yml`
- `traefik/dynamic/security.yml`
- `app/main.py`
- `kiosk/Dockerfile`, `kiosk/entrypoint.sh`
- `rdp-proxy/Dockerfile`, `rdp-proxy/entrypoint.sh`
## 5. Запуск
```bash
cp .env.example .env
mkdir -p traefik/letsencrypt
touch traefik/letsencrypt/acme.json
chmod 600 traefik/letsencrypt/acme.json
```
Собрать runtime образы:
```bash
docker compose --profile build-only build kiosk-image rdp-proxy-image universal-runtime-image
```
Поднять систему:
```bash
docker compose up -d --build
```
Проверка:
```bash
docker compose ps
docker compose logs -f api traefik
```
Дефолтный админ берётся из `.env` (`ADMIN_USERNAME`, `ADMIN_PASSWORD`).
## 6. Примеры admin API
1) Создать сервис WEB:
```bash
curl -k -X POST "https://stend.4mont.ru/api/admin/services" \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: <csrf_from_cookie>" \
-H "Cookie: portal_auth=<cookie>; csrf_token=<csrf>" \
-d '{"name":"CRM","slug":"crm","type":"WEB","target":"http://192.168.1.10:3000","active":true}'
```
2) Создать сервис RDP:
```bash
curl -k -X POST "https://stend.4mont.ru/api/admin/services" \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: <csrf_from_cookie>" \
-H "Cookie: portal_auth=<cookie>; csrf_token=<csrf>" \
-d '{"name":"Windows Desktop","slug":"win-rdp1","type":"RDP","target":"192.168.1.60:3389","active":true}'
```
Для RDP `target` также поддерживает креды и параметры:
```text
rdp://user:password@192.168.1.60:3389?domain=AD&sec=nla
```
3) Создать пользователя:
```bash
curl -k -X POST "https://stend.4mont.ru/api/admin/users" \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: <csrf_from_cookie>" \
-H "Cookie: portal_auth=<cookie>; csrf_token=<csrf>" \
-d '{"username":"user1","password":"Passw0rd!","expires_at":"2026-12-31T23:59:59+00:00","active":true}'
```
4) Назначить ACL:
```bash
curl -k -X PUT "https://stend.4mont.ru/api/admin/users/2/acl" \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: <csrf_from_cookie>" \
-H "Cookie: portal_auth=<cookie>; csrf_token=<csrf>" \
-d '{"service_ids":[1,2]}'
```
## 7. Ограничения MVP
- Нет отдельной UI-админки (есть admin API).
- TTL неактивности основан на heartbeat runtime-страницы.
- Для production стоит добавить Alembic-миграции, rate limiting и централизованный логинг.