From e6af50274b7d5a315da350f549a62e16026ef77e Mon Sep 17 00:00:00 2001 From: root Date: Tue, 25 Nov 2025 10:03:49 +0300 Subject: [PATCH] cleanup --- .../docs/AUTHENTICATION_FLOW.md | 385 ------------ .../docs/AUTO_DEPLOY_GUIDE.md | 351 ----------- .../docs/BULK_OPERATIONS_GUIDE.md | 237 -------- .../docs/BULK_SSH_COMMANDS_GUIDE.md | 238 -------- .../docs/COMPATIBILITY_SUMMARY.md | 202 ------- .../docs/CORS_CONFIGURATION.md | 171 ------ .../docs/CUSTOM_GUACAMOLE_USER.md | 325 ----------- .../docs/DELETE_CONNECTION_FIX.md | 328 ----------- .../docs/DEPLOYMENT_CHECKLIST.md | 186 ------ .../docs/DOCKER_RESTART_GUIDE.md | 403 ------------- .../docs/DOCUMENTATION_INDEX.md | 327 ----------- .../docs/ENDPOINT_AUDIT_REPORT.md | 510 ---------------- .../docs/FINAL_AUDIT_SUMMARY.md | 548 ------------------ .../docs/HARDCODED_PASSWORDS_FIX.md | 298 ---------- .../docs/MIGRATION_SECURITY_UPDATE.md | 195 ------- guacamole_test_11_26/docs/QUICK_CORS_SETUP.md | 39 -- .../docs/QUICK_START_CUSTOM_ADMIN.md | 262 --------- .../docs/TOKEN_FIX_SUMMARY.md | 230 -------- .../docs/Действительноважно.md | 342 ----------- mc_test/.gitignore | 48 ++ mc_test/ENV_SETUP.md | 131 ----- 21 files changed, 48 insertions(+), 5708 deletions(-) delete mode 100755 guacamole_test_11_26/docs/AUTHENTICATION_FLOW.md delete mode 100755 guacamole_test_11_26/docs/AUTO_DEPLOY_GUIDE.md delete mode 100755 guacamole_test_11_26/docs/BULK_OPERATIONS_GUIDE.md delete mode 100755 guacamole_test_11_26/docs/BULK_SSH_COMMANDS_GUIDE.md delete mode 100755 guacamole_test_11_26/docs/COMPATIBILITY_SUMMARY.md delete mode 100755 guacamole_test_11_26/docs/CORS_CONFIGURATION.md delete mode 100755 guacamole_test_11_26/docs/CUSTOM_GUACAMOLE_USER.md delete mode 100755 guacamole_test_11_26/docs/DELETE_CONNECTION_FIX.md delete mode 100755 guacamole_test_11_26/docs/DEPLOYMENT_CHECKLIST.md delete mode 100755 guacamole_test_11_26/docs/DOCKER_RESTART_GUIDE.md delete mode 100755 guacamole_test_11_26/docs/DOCUMENTATION_INDEX.md delete mode 100755 guacamole_test_11_26/docs/ENDPOINT_AUDIT_REPORT.md delete mode 100755 guacamole_test_11_26/docs/FINAL_AUDIT_SUMMARY.md delete mode 100755 guacamole_test_11_26/docs/HARDCODED_PASSWORDS_FIX.md delete mode 100755 guacamole_test_11_26/docs/MIGRATION_SECURITY_UPDATE.md delete mode 100755 guacamole_test_11_26/docs/QUICK_CORS_SETUP.md delete mode 100755 guacamole_test_11_26/docs/QUICK_START_CUSTOM_ADMIN.md delete mode 100755 guacamole_test_11_26/docs/TOKEN_FIX_SUMMARY.md delete mode 100755 guacamole_test_11_26/docs/Действительноважно.md create mode 100755 mc_test/.gitignore delete mode 100755 mc_test/ENV_SETUP.md diff --git a/guacamole_test_11_26/docs/AUTHENTICATION_FLOW.md b/guacamole_test_11_26/docs/AUTHENTICATION_FLOW.md deleted file mode 100755 index e990ff45..00000000 --- a/guacamole_test_11_26/docs/AUTHENTICATION_FLOW.md +++ /dev/null @@ -1,385 +0,0 @@ -# 🔐 Authentication Flow Diagram - -## 📊 Complete Authentication Flow - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ СИСТЕМА АУТЕНТИФИКАЦИИ │ -│ │ -│ ┌───────────────┐ ┌──────────────┐ ┌────────────────────┐ │ -│ │ Environment │ │ Guacamole │ │ Application │ │ -│ │ Variables │───▶│ Database │───▶│ Runtime │ │ -│ │ (.env) │ │ (PostgreSQL) │ │ (FastAPI) │ │ -│ └───────────────┘ └──────────────┘ └────────────────────┘ │ -│ │ │ │ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ SYSTEM_ADMIN_USERNAME / PASSWORD │ │ -│ │ (От вас, НЕ захардкожены) │ │ -│ └─────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 🔄 Startup Sequence - -``` -1️⃣ API STARTUP - ┌─────────────────────────────────────────────────────┐ - │ docker compose up -d │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ GuacamoleAuthenticator.__init__() │ - │ ├─ Read SYSTEM_ADMIN_USERNAME from env │ - │ ├─ Read SYSTEM_ADMIN_PASSWORD from env │ - │ └─ If missing → ValueError ❌ │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ wait_for_guacamole() │ - │ └─ Wait for Guacamole API to be ready │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ cleanup_orphaned_guacamole_connections() │ - │ ├─ Get system token (uses env credentials) │ - │ ├─ List all Guacamole connections │ - │ ├─ Check Redis for each connection │ - │ └─ Delete orphaned connections │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ ✅ API Ready for User Requests │ - └─────────────────────────────────────────────────────┘ -``` - ---- - -## 👤 User Login Flow - -``` -1️⃣ USER LOGIN REQUEST - ┌─────────────────────────────────────────────────────┐ - │ POST /auth/login │ - │ { │ - │ "username": "alice", │ - │ "password": "user_password" │ - │ } │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ guacamole_authenticator.authenticate_user() │ - │ ├─ Send to Guacamole: username="alice" │ - │ ├─ Send to Guacamole: password="user_password" │ - │ ├─ Get Guacamole token for alice │ - │ └─ Get user role and permissions │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ create_jwt_for_user() │ - │ ├─ Create JWT with username="alice" │ - │ ├─ Store Guacamole token in Redis session │ - │ └─ Return JWT to client │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ ✅ User Authenticated │ - │ Client has JWT → Can make API requests │ - └─────────────────────────────────────────────────────┘ -``` - -**ВАЖНО:** -- ❌ НЕ используется `SYSTEM_ADMIN_USERNAME/PASSWORD` -- ✅ Используются credentials самого пользователя (alice) - ---- - -## 🔌 User Creates Connection - -``` -2️⃣ CREATE CONNECTION REQUEST - ┌─────────────────────────────────────────────────────┐ - │ POST /connect │ - │ Authorization: Bearer │ - │ { │ - │ "hostname": "server01", │ - │ "protocol": "rdp", │ - │ "username": "remote_user", │ - │ "password": "remote_password" │ - │ } │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ JWT Middleware │ - │ ├─ Extract session_id from JWT │ - │ ├─ Get Guacamole token from Redis session │ - │ ├─ Get user info (username="alice", role="USER") │ - │ └─ Pass to endpoint handler │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ create_remote_connection() │ - │ ├─ Use alice's Guacamole token │ - │ ├─ Create connection in Guacamole │ - │ ├─ Store connection info in Redis │ - │ └─ Return connection URL │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ ✅ Connection Created │ - │ Owner: alice (from JWT) │ - │ Guacamole Token: alice's token (from Redis) │ - └─────────────────────────────────────────────────────┘ -``` - -**ВАЖНО:** -- ❌ НЕ используется `SYSTEM_ADMIN_USERNAME/PASSWORD` -- ✅ Используется Guacamole token самого пользователя (alice) - ---- - -## 🗑️ User Deletes Connection - -``` -3️⃣ DELETE CONNECTION REQUEST - ┌─────────────────────────────────────────────────────┐ - │ DELETE /connections/{id} │ - │ Authorization: Bearer │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ delete_connection() │ - │ ├─ Get connection from Redis │ - │ ├─ Check ownership (connection.owner == alice) │ - │ ├─ Use alice's Guacamole token from Redis │ - │ └─ Delete from Guacamole │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ ✅ Connection Deleted │ - │ Used: alice's token (NOT system admin) │ - └─────────────────────────────────────────────────────┘ -``` - -**ВАЖНО:** -- ❌ НЕ используется `SYSTEM_ADMIN_USERNAME/PASSWORD` -- ✅ Используется Guacamole token владельца подключения - ---- - -## 🧹 Background Cleanup (System) - -``` -4️⃣ CLEANUP EXPIRED CONNECTIONS - ┌─────────────────────────────────────────────────────┐ - │ Background Task (every 60 seconds) │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ cleanup_expired_connections_once() │ - │ ├─ Get all connections from Redis │ - │ ├─ Find expired connections │ - │ └─ For each expired connection: │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ delete_connection_with_user_token() │ - │ ├─ Get user's token from Redis │ - │ ├─ Delete from Guacamole using user's token │ - │ └─ Delete from Redis │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ ✅ Expired Connections Cleaned │ - │ Used: Each user's token (NOT system admin) │ - └─────────────────────────────────────────────────────┘ -``` - -**ВАЖНО:** -- ✅ Использует токен каждого пользователя (из Redis) -- ❌ НЕ используется `SYSTEM_ADMIN_USERNAME/PASSWORD` - ---- - -## 🔧 Orphaned Cleanup (System) - -``` -5️⃣ CLEANUP ORPHANED CONNECTIONS (Startup Only) - ┌─────────────────────────────────────────────────────┐ - │ API Startup Event │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ cleanup_orphaned_guacamole_connections() │ - │ ├─ Get system token using env credentials │ - │ ├─ List ALL connections from Guacamole │ - │ ├─ Check if each exists in Redis │ - │ └─ Delete if NOT in Redis (orphaned) │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ get_system_token() │ - │ ├─ Read SYSTEM_ADMIN_USERNAME from env │ - │ ├─ Read SYSTEM_ADMIN_PASSWORD from env │ - │ ├─ Authenticate to Guacamole │ - │ └─ Return system token │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ delete_connection_with_system_token() │ - │ └─ Delete orphaned connections │ - └──────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌─────────────────────────────────────────────────────┐ - │ ✅ Orphaned Connections Cleaned │ - │ Used: SYSTEM_ADMIN credentials from env │ - └─────────────────────────────────────────────────────┘ -``` - -**ВАЖНО:** -- ✅ Это ЕДИНСТВЕННОЕ место где используется `SYSTEM_ADMIN` -- ✅ Работает ТОЛЬКО на старте API -- ✅ Credentials берутся из environment variables - ---- - -## 🔐 Security Model - -``` -┌──────────────────────────────────────────────────────────────┐ -│ БЕЗОПАСНОСТЬ CREDENTIALS │ -└──────────────────────────────────────────────────────────────┘ - -┌─────────────────────┬──────────────┬──────────────────────┐ -│ Credential Type │ Storage │ Usage │ -├─────────────────────┼──────────────┼──────────────────────┤ -│ SYSTEM_ADMIN │ .env file │ Startup cleanup │ -│ (username/pass) │ ✅ Required │ (orphaned conns) │ -├─────────────────────┼──────────────┼──────────────────────┤ -│ User Guacamole │ Redis │ User operations │ -│ token │ (ephemeral) │ (create/delete) │ -├─────────────────────┼──────────────┼──────────────────────┤ -│ User JWT │ Client │ API authorization │ -│ token │ (ephemeral) │ (all endpoints) │ -├─────────────────────┼──────────────┼──────────────────────┤ -│ REDIS_PASSWORD │ .env file │ Redis connections │ -│ │ ✅ Required │ (all components) │ -├─────────────────────┼──────────────┼──────────────────────┤ -│ POSTGRES_PASSWORD │ .env file │ DB connections │ -│ │ ✅ Required │ (API + Guacamole) │ -└─────────────────────┴──────────────┴──────────────────────┘ - -КРИТИЧНО: -✅ Все credentials из .env (НЕ захардкожены) -✅ User tokens ephemeral (хранятся в Redis с TTL) -✅ System token используется ТОЛЬКО для cleanup -✅ Нет fallback значений (API упадет если нет .env) -``` - ---- - -## 📊 Token Types Comparison - -``` -┌───────────────────────────────────────────────────────────────┐ -│ ТРИ ТИПА ТОКЕНОВ │ -└───────────────────────────────────────────────────────────────┘ - -1️⃣ JWT TOKEN (User API Token) - ├─ Создается: При login пользователя - ├─ Хранится: На клиенте (LocalStorage/Memory) - ├─ Срок жизни: 60 минут (configurable) - ├─ Используется для: Авторизации API запросов - └─ Содержит: username, role, session_id - -2️⃣ GUACAMOLE TOKEN (User Session Token) - ├─ Создается: При аутентификации в Guacamole - ├─ Хранится: В Redis (по session_id из JWT) - ├─ Срок жизни: Привязан к JWT сессии - ├─ Используется для: Создания/удаления подключений - └─ Содержит: Guacamole authToken - -3️⃣ SYSTEM TOKEN (Service Account Token) - ├─ Создается: При startup API - ├─ Хранится: В памяти GuacamoleAuthenticator - ├─ Срок жизни: До рестарта API - ├─ Используется для: Cleanup orphaned connections - └─ Содержит: Guacamole authToken (for system admin) - -ВАЖНО: -✅ User никогда не видит SYSTEM TOKEN -✅ SYSTEM TOKEN используется ТОЛЬКО внутри API -✅ User operations используют User's Guacamole token -``` - ---- - -## 🎯 Key Takeaways - -### ✅ **Что МОЖНО менять:** -```env -SYSTEM_ADMIN_USERNAME=любое_имя # ✅ Любое имя -SYSTEM_ADMIN_PASSWORD=любой_пароль # ✅ Любой пароль -REDIS_PASSWORD=любой_пароль # ✅ Любой пароль -POSTGRES_PASSWORD=любой_пароль # ✅ Любой пароль -``` - -### ❌ **Что НЕЛЬЗЯ:** -```env -SYSTEM_ADMIN_USERNAME= # ❌ Пустое значение -SYSTEM_ADMIN_PASSWORD=guacadmin # ❌ Дефолтное значение -REDIS_PASSWORD=redis_pass # ❌ Дефолтное значение -``` - -### 🔒 **Где используются credentials:** - -| Credential | Used By | Used For | User Visible? | -|------------|---------|----------|---------------| -| `SYSTEM_ADMIN_USERNAME/PASSWORD` | API (startup) | Orphaned cleanup | ❌ No | -| User's Guacamole token | API (runtime) | User operations | ❌ No (in Redis) | -| User's JWT | Client | API authorization | ✅ Yes (client-side) | - -### 🎯 **Безопасность:** - -1. ✅ **No hardcoded credentials** - Все из .env -2. ✅ **No fallback values** - API упадет без credentials -3. ✅ **System token isolated** - Только для cleanup -4. ✅ **User tokens ephemeral** - Срок жизни ограничен -5. ✅ **Role-based access** - GUEST/USER/ADMIN permissions - ---- - -## 📚 Related Documentation - -- `ENDPOINT_AUDIT_REPORT.md` - Detailed endpoint analysis -- `COMPATIBILITY_SUMMARY.md` - Quick compatibility check -- `DEPLOYMENT_CHECKLIST.md` - Deployment guide - ---- - -**Last Updated:** 2025-10-29 -**Version:** 1.0 -**Status:** ✅ PRODUCTION READY - diff --git a/guacamole_test_11_26/docs/AUTO_DEPLOY_GUIDE.md b/guacamole_test_11_26/docs/AUTO_DEPLOY_GUIDE.md deleted file mode 100755 index 32fc7d27..00000000 --- a/guacamole_test_11_26/docs/AUTO_DEPLOY_GUIDE.md +++ /dev/null @@ -1,351 +0,0 @@ -# 🚀 Автоматический деплой с безопасным администратором - -## 🎯 Что делает автоматический деплой? - -При запуске `deploy.sh` (Linux/Mac) или `deploy.ps1` (Windows) скрипт **автоматически:** - -1. ✅ Проверяет наличие Docker, Python, Docker Compose -2. ✅ Загружает `.env` или `production.env` -3. ✅ **Проверяет пароль администратора** - - Если пароль **не дефолтный** → генерирует SQL с вашим паролем - - Если дефолтный → предупреждает и спрашивает подтверждение -4. ✅ Создает backup оригинального SQL -5. ✅ Заменяет `002-create-admin-user.sql` на сгенерированный -6. ✅ Запускает контейнеры -7. ✅ Ждет готовности сервисов -8. ✅ Проверяет что администратор создался -9. ✅ Выводит итоговую информацию - -**Результат:** Безопасный деплой **одной командой** без ручных действий! - ---- - -## ⚡ Быстрый старт - -### **Linux/Mac:** - -```bash -cd GuacamoleRemoteAccess - -# 1. Обновите production.env с безопасным паролем -nano production.env -# SYSTEM_ADMIN_USERNAME=guacadmin -# SYSTEM_ADMIN_PASSWORD=YourSecurePassword123! - -# 2. Запустите deploy скрипт -chmod +x deploy.sh -./deploy.sh -``` - -### **Windows (PowerShell):** - -```powershell -cd GuacamoleRemoteAccess - -# 1. Обновите production.env с безопасным паролем -notepad production.env -# SYSTEM_ADMIN_USERNAME=guacadmin -# SYSTEM_ADMIN_PASSWORD=YourSecurePassword123! - -# 2. Запустите deploy скрипт -.\deploy.ps1 -``` - -**Вот и всё!** Скрипт сделает остальное. - ---- - -## 📊 Пример работы скрипта - -```bash -$ ./deploy.sh - -========================================== - Remote Access API Deployment -========================================== - -[INFO] Checking requirements... -[OK] All requirements met -[INFO] Loading environment variables... -[INFO] Using production.env -[OK] Environment loaded from production.env -[INFO] Checking admin credentials... -[OK] Custom password detected - generating secure admin SQL -[INFO] Username: guacadmin -[INFO] Password length: 24 characters -[INFO] Creating backup of default SQL... -[OK] Backup created: 002-create-admin-user-DEFAULT-BACKUP.sql -[INFO] Generating SQL with custom password... -[VERIFY] Verifying hash generation... -[OK] Hash generation verified -[OK] Admin SQL generated and applied -[INFO] File: 002-create-admin-user.sql (auto-generated) -[INFO] Validating docker-compose.yml... -[OK] docker-compose.yml is valid -[INFO] Starting containers... -[OK] Containers started successfully -[INFO] Waiting for services to be ready... -[INFO] Waiting for PostgreSQL... -[OK] PostgreSQL is ready -[INFO] Waiting for Guacamole... -[OK] Guacamole is ready -[INFO] Waiting for API... -[OK] API is ready -[INFO] Verifying deployment... -[OK] Admin user 'guacadmin' exists in database -[OK] API successfully authenticated with system credentials - -========================================== - Deployment Complete! -========================================== - -[OK] Services are running - -Access URLs: - - Guacamole UI: http://localhost:8080/guacamole/ - - API Docs: http://localhost:8000/docs (if enabled) - -Admin Credentials: - - Username: guacadmin - - Password: You***rd! (length: 24) - -Useful Commands: - - View logs: docker compose logs -f - - Stop: docker compose down - - Restart: docker compose restart - -[INFO] Original SQL backed up to: 002-create-admin-user-DEFAULT-BACKUP.sql -``` - ---- - -## 🔐 Проверка безопасности - -Скрипт **автоматически проверяет** небезопасные пароли: - -### **❌ Будет предупреждение:** - -```env -SYSTEM_ADMIN_PASSWORD=guacadmin -SYSTEM_ADMIN_PASSWORD=guacadmin_change_in_production -SYSTEM_ADMIN_PASSWORD=CHANGE_ME_SECURE_PASSWORD_HERE_ -``` - -**Вывод:** -``` -[WARNING] Default or placeholder password detected! -[WARNING] Username: guacadmin -[WARNING] Password: guacadmin -[WARNING] -[WARNING] This is INSECURE for production! -[WARNING] Using default 002-create-admin-user.sql -[WARNING] -Continue anyway? (y/N): -``` - -### **✅ Будет генерация:** - -```env -SYSTEM_ADMIN_PASSWORD=MySecureRandomPassword2025! -``` - -**Вывод:** -``` -[OK] Custom password detected - generating secure admin SQL -[INFO] Username: guacadmin -[INFO] Password length: 27 characters -``` - ---- - -## 📁 Что происходит с файлами? - -### **До деплоя:** - -``` -GuacamoleRemoteAccess/ -├── 002-create-admin-user.sql ← Оригинальный (дефолтный пароль) -├── generate_guacamole_user.py -├── production.env -└── deploy.sh -``` - -### **После деплоя:** - -``` -GuacamoleRemoteAccess/ -├── 002-create-admin-user.sql ← ЗАМЕНЕН на сгенерированный -├── 002-create-admin-user-DEFAULT-BACKUP.sql ← Backup оригинала -├── generate_guacamole_user.py -├── production.env -└── deploy.sh -``` - -**Важно:** -- ✅ `002-create-admin-user-DEFAULT-BACKUP.sql` - это backup оригинала (коммитится в git) -- ❌ `002-create-admin-user.sql` - после генерации содержит ваш пароль (**не коммитится!**) - -Если нужно восстановить оригинал: -```bash -cp 002-create-admin-user-DEFAULT-BACKUP.sql 002-create-admin-user.sql -``` - ---- - -## 🔄 Повторный деплой - -При повторном запуске `deploy.sh`: - -1. ✅ Проверяет пароль в `.env` -2. ✅ Если пароль **изменился** → регенерирует SQL -3. ✅ Если пароль **тот же** → использует существующий SQL -4. ✅ Перезапускает контейнеры - -**Backup создается только один раз** (при первом запуске). - ---- - -## 🆘 Troubleshooting - -### Проблема: "SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD must be set!" - -**Решение:** -```bash -# Проверьте что переменные установлены в .env или production.env -grep SYSTEM_ADMIN production.env - -# Должно быть: -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=ваш_пароль -``` - ---- - -### Проблема: "Python 3 not found!" - -**Linux/Mac:** -```bash -# Установите Python 3 -sudo apt install python3 # Ubuntu/Debian -brew install python3 # macOS -``` - -**Windows:** -```powershell -# Скачайте с https://www.python.org/downloads/ -# Или установите через Winget: -winget install Python.Python.3 -``` - ---- - -### Проблема: "Failed to generate SQL!" - -**Возможные причины:** - -1. ❌ Python скрипт содержит ошибки -2. ❌ Недостаточно прав на запись файла -3. ❌ Некорректная кодировка пароля - -**Решение:** -```bash -# Попробуйте запустить скрипт вручную: -python3 generate_guacamole_user.py \ - --username guacadmin \ - --password "YourPassword" \ - --admin \ - --verify - -# Если работает - проблема в deploy.sh/deploy.ps1 -# Если не работает - проблема в скрипте или Python -``` - ---- - -### Проблема: "Admin user does not exist in database" - -**Причины:** - -1. ❌ SQL не применился (PostgreSQL не запустилась) -2. ❌ Пользователь уже существует с другим паролем -3. ❌ Ошибка в SQL синтаксисе - -**Решение:** -```bash -# Проверьте логи PostgreSQL -docker compose logs postgres | grep ERROR - -# Проверьте что SQL файл корректный -cat 002-create-admin-user.sql - -# Попробуйте применить SQL вручную -docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < 002-create-admin-user.sql -``` - ---- - -### Проблема: "API failed to authenticate with system credentials" - -**Причины:** - -1. ❌ Пароль в `production.env` не совпадает с паролем в БД -2. ❌ Пользователь не существует -3. ❌ Guacamole не запустилась - -**Решение:** -```bash -# Проверьте логи API -docker compose logs remote_access_api | grep "System token" - -# Проверьте что пароли совпадают -grep SYSTEM_ADMIN_PASSWORD production.env - -# Попробуйте войти в Guacamole UI с этим паролем -# http://localhost:8080/guacamole/ -``` - ---- - -## 🔧 Ручной режим (без автоматики) - -Если хотите запустить **без автоматической генерации**: - -```bash -# Используйте стандартный docker compose -docker compose up -d - -# Скрипт НЕ будет запущен -# SQL НЕ будет сгенерирован -# Используется существующий 002-create-admin-user.sql -``` - -**Это полезно если:** -- Вы уже сгенерировали SQL вручную -- Хотите использовать дефолтный пароль (dev окружение) -- Тестируете конфигурацию - ---- - -## 📚 Дополнительные ресурсы - -- `QUICK_START_CUSTOM_ADMIN.md` - быстрый старт без автоматики -- `CUSTOM_GUACAMOLE_USER.md` - ручная генерация SQL -- `MIGRATION_SECURITY_UPDATE.md` - миграция для существующих установок -- `generate_guacamole_user.py` - Python скрипт для генерации - ---- - -## ✅ Best Practices - -1. ✅ **Всегда используйте безопасные пароли** (минимум 20 символов) -2. ✅ **Генерируйте пароли случайно:** `openssl rand -base64 32` -3. ✅ **Используйте разные пароли** для dev/staging/prod -4. ✅ **Храните пароли безопасно** (password manager, vault) -5. ✅ **Не коммитьте** `.env` файлы в git -6. ✅ **Проверяйте логи** после деплоя -7. ✅ **Делайте backup** важных файлов - ---- - -**Готово! Теперь деплой безопасен и автоматизирован!** 🎉 - diff --git a/guacamole_test_11_26/docs/BULK_OPERATIONS_GUIDE.md b/guacamole_test_11_26/docs/BULK_OPERATIONS_GUIDE.md deleted file mode 100755 index 744df222..00000000 --- a/guacamole_test_11_26/docs/BULK_OPERATIONS_GUIDE.md +++ /dev/null @@ -1,237 +0,0 @@ -# 📊 Bulk Operations - Массовые операции - -## ✨ Описание фичи - -Bulk Operations позволяют выполнять операции над **группой машин одновременно**, значительно ускоряя административные задачи и мониторинг. - -### **Реализованные функции:** -- ✅ **Bulk Health Check** - проверка доступности нескольких машин параллельно -- ✅ **Bulk SSH Command** - выполнение команды на нескольких серверах с 3 режимами авторизации -- 🔜 **Multi-Connect** - открыть подключения к нескольким машинам (planned) -- 🔜 **Bulk Tags Update** - массовое обновление тегов (planned) - ---- - -## 🎯 Use Cases - -### **1. Проверка доступности prod серверов** -``` -Scenario: Утренний чек перед началом работы -1. Фильтруем по тегу "production" -2. Select All (50 machines) -3. Click "Health Check" -4. Результат: 48 online, 2 offline -5. Быстро идентифицируем проблемы -``` - -### **2. Массовое выполнение SSH команд** -``` -Scenario: Перезапуск сервиса на всех web серверах -1. Фильтруем по тегу "webserver" -2. Select All (15 machines) -3. Click "Run Command" -4. Command: "systemctl restart nginx" -5. Mode: Saved credentials -6. Result: 15/15 success -``` - ---- - -## 🚀 Быстрый старт - -### **Step 1: Enable Bulk Mode** -``` -1. В Sidebar → Click "Bulk Select" -2. Кнопка меняется на "✓ Bulk Mode" -3. Появляются checkboxes возле машин -``` - -### **Step 2: Select Machines** -``` -Опция A: Manual selection - - Click checkboxes вручную - -Опция B: Select All - - Click "Select All" checkbox - - Все машины выбраны - -Опция C: With filter - - Search: "web" - - Select All → только отфильтрованные -``` - -### **Step 3: Choose Operation** -``` -Toolbar появляется внизу: -[Health Check] [Run Command] [Multi-Connect] [Update Tags] -``` - ---- - -## 📖 Детальные руководства - -- **[BULK_SSH_COMMANDS_GUIDE.md](./BULK_SSH_COMMANDS_GUIDE.md)** - SSH Commands с 3 режимами авторизации -- **Health Check** - см. ниже в этом документе - ---- - -## 🏥 Bulk Health Check - -### **Описание:** -Параллельная проверка доступности нескольких машин одновременно. - -**Features:** -- DNS resolution check -- TCP port connectivity check -- Response time measurement -- Role-based limits - -### **API:** -``` -POST /bulk/health-check - -Request: -{ - "machine_ids": ["abc...", "def...", "ghi..."], - "timeout": 5, - "check_port": true -} - -Response: -{ - "total": 3, - "available": 2, - "unavailable": 1, - "execution_time_ms": 1250, - "results": [...] -} -``` - -### **Role Limits:** -- **GUEST:** max 10 machines -- **USER:** max 50 machines -- **ADMIN:** max 200 machines - -### **UI Flow:** -``` -1. Select machines → Bulk mode -2. Click "Health Check" -3. Progress modal shows: "Checking 15/50 machines..." -4. Results modal: - - Tabs: All / Available / Unavailable - - Sortable table - - Export CSV - - Retry Failed -``` - ---- - -## 🔐 Security & Permissions - -### **Role-based Access:** - -| Feature | GUEST | USER | ADMIN | -|---------|-------|------|-------| -| Health Check | 10 machines | 50 machines | 200 machines | -| SSH Command | ❌ Forbidden | 20 machines (whitelist) | 100 machines (any) | -| Multi-Connect | 2 machines | 5 machines | 10 machines | - -### **Audit Logging:** -```json -{ - "action": "bulk_health_check", - "user": "admin", - "machine_count": 50, - "available": 48, - "unavailable": 2, - "execution_time_ms": 3500, - "timestamp": "2025-01-15T10:30:00Z" -} -``` - ---- - -## 📊 Performance - -| Operation | 10 machines | 50 machines | 100 machines | -|-----------|------------|-------------|--------------| -| Health Check | ~500ms | ~2.5s | ~5s | -| SSH Command | ~2s | ~10s | ~20s | - -**Optimization:** -- Parallel execution via `asyncio.gather` -- Configurable timeouts -- Semaphore для SSH (max 10 concurrent) - ---- - -## 🎓 Best Practices - -### **1. Используйте фильтры перед bulk selection** -``` -✅ Good: Filter → Select All filtered → Health Check -❌ Bad: Select All 1000 machines → try to Health Check → error -``` - -### **2. Export результаты для отчетов** -``` -Use case: Weekly infrastructure report -1. Select all prod servers -2. Health Check -3. Export CSV -4. Import to Excel/Dashboard -``` - -### **3. Retry Failed для устранения false negatives** -``` -Scenario: Network glitch -1. Health Check → 5 machines offline -2. Wait 30 seconds -3. Retry Failed → 3 now online -4. Investigate remaining 2 -``` - ---- - -## 🐛 Troubleshooting - -### **Issue: "Selection Limit Exceeded"** -``` -Error: "Role USER can check max 50 machines at once" - -Solution: -1. Проверить свою роль (Header → User Info) -2. Уменьшить выбор машин -3. Запросить upgrade роли у администратора -``` - -### **Issue: All machines show "Unavailable"** -``` -Possible causes: -1. Network issues on server side -2. Firewall blocking ports -3. DNS resolution problems - -Debug: -1. Check API logs: docker compose logs remote_access_api -2. Try single machine health check first -3. Verify network connectivity from API container -``` - ---- - -## 🔗 Related Documentation - -- [BULK_SSH_COMMANDS_GUIDE.md](./BULK_SSH_COMMANDS_GUIDE.md) - 📘 **Детальное руководство по SSH Commands** -- [AUTHENTICATION_FLOW_DETAILED.md](./AUTHENTICATION_FLOW_DETAILED.md) - Role-based permissions -- [PRODUCTION_SECURITY_ARCHITECTURE.md](./PRODUCTION_SECURITY_ARCHITECTURE.md) - Audit logging -- [SAVED_MACHINES_FEATURE.md](./SAVED_MACHINES_FEATURE.md) - Machine management - ---- - -**🎉 Готово! Bulk Operations полностью реализованы и документированы.** - -### **Что реализовано:** -1. ✅ **Bulk Health Check** - Массовая проверка доступности -2. ✅ **Bulk SSH Command** - Массовое выполнение команд с 3 режимами авторизации - diff --git a/guacamole_test_11_26/docs/BULK_SSH_COMMANDS_GUIDE.md b/guacamole_test_11_26/docs/BULK_SSH_COMMANDS_GUIDE.md deleted file mode 100755 index 379162d0..00000000 --- a/guacamole_test_11_26/docs/BULK_SSH_COMMANDS_GUIDE.md +++ /dev/null @@ -1,238 +0,0 @@ -# 🔐 Bulk SSH Commands - Массовое выполнение команд - -## ✨ Описание - -Bulk SSH Commands позволяет выполнять SSH команды на **множестве машин одновременно** с гибкой системой авторизации. - ---- - -## 🎯 **3 Режима Авторизации** - -### **1️⃣ Saved Credentials (Рекомендуется)** -``` -✅ Использование: Saved machines с credentials в БД -✅ Безопасность: Высокая (encrypted в БД) -✅ UX: Простой (нет ввода) -❌ Ограничение: Только для saved machines -``` - -**Как работает:** -- Credentials расшифровываются из БД -- Автоматически применяются для каждой машины -- Не требует ввода пароля - ---- - -### **2️⃣ Global Credentials (Простой)** -``` -✅ Использование: Одинаковые credentials для всех машин -✅ UX: Быстрый (один ввод) -✅ Гибкость: Можно override saved credentials -⚠️ Безопасность: Средняя (один пароль для всех) -``` - -**UI:** -``` -Username: [root ] -Password: [************] -``` - ---- - -### **3️⃣ Custom Credentials (Гибкий)** -``` -✅ Использование: Разные credentials для каждой машины -✅ Безопасность: Высокая -✅ Гибкость: Максимальная -❌ UX: Сложный (много вводить) -``` - -**UI:** -``` -Quick Fill: [username] [password] [Copy to All] - -Machine 1: [username] [password] -Machine 2: [username] [password] -Machine 3: [username] [password] -``` - ---- - -## 🔐 **Role-based Permissions** - -### **Limits:** - -| Role | Max Machines | Commands | -|------|-------------|----------| -| **GUEST** | ❌ 0 | Forbidden | -| **USER** | ✅ 20 | Whitelist only | -| **ADMIN** | ✅ 100 | Any commands | -| **SUPER_ADMIN** | ✅ 100 | Any commands | - -### **USER Whitelist:** -```python -allowed_commands = [ - "uptime", - "df -h", - "free -m", - "top -bn1", - "systemctl status", - "docker ps", - "ps aux", - "ls -la", - "cat /etc/os-release", - "hostname" -] -``` - ---- - -## 📊 **API Reference** - -### **POST /bulk/ssh-command** - -**Request:** -```json -{ - "machine_ids": ["abc123...", "def456..."], - "command": "systemctl restart nginx", - "credentials_mode": "global", - "global_credentials": { - "username": "root", - "password": "secure_password" - }, - "timeout": 30 -} -``` - -**Response:** -```json -{ - "total": 2, - "success": 2, - "failed": 0, - "execution_time_ms": 2400, - "command": "systemctl restart nginx", - "results": [ - { - "machine_id": "abc123...", - "machine_name": "web-01", - "hostname": "192.168.1.10", - "status": "success", - "exit_code": 0, - "stdout": "nginx restarted", - "stderr": "", - "execution_time_ms": 1200 - } - ] -} -``` - ---- - -## 🎨 **UI Flow** - -``` -1. Bulk Select → выбрать машины -2. Click "Run Command" → modal открывается -3. Выбрать режим: [Saved] [Global] [Custom] -4. Ввести команду: "systemctl restart nginx" -5. Заполнить credentials (если нужно) -6. Execute → параллельное выполнение -7. Результаты → expandable stdout/stderr -8. Export CSV / Retry Failed -``` - ---- - -## 🔒 **Security Best Practices** - -1. ✅ **Use Saved Credentials** когда возможно -2. ✅ **Whitelist commands** для USER role -3. ✅ **Command audit logging** для всех операций -4. ✅ **Concurrency limits** (max 10 concurrent SSH) -5. ✅ **Timeout protection** (5-300 seconds) - ---- - -## 📋 **Use Cases** - -### **1. Restart service на всех web серверах** -``` -Select: tags="webserver" (15 machines) -Command: systemctl restart nginx -Mode: Saved credentials -Result: 15/15 success -``` - -### **2. Check disk space на prod серверах** -``` -Select: tags="production" (50 machines) -Command: df -h -Mode: Saved credentials -Result: Export to CSV для анализа -``` - ---- - -## ⚠️ **Production Notes** - -### **SSH Implementation:** -```python -# Current: DEMO mode (sshpass fallback) -# Production: Use paramiko - -pip install paramiko - -import paramiko - -client = paramiko.SSHClient() -client.connect(hostname, username=username, password=password) -stdin, stdout, stderr = client.exec_command(command) -``` - ---- - -## 🐛 **Troubleshooting** - -### **Issue: "Command not in whitelist"** -``` -Error: USER role tried to run "rm -rf /" -Solution: - 1. Contact administrator for command approval - 2. Or request ADMIN role upgrade -``` - -### **Issue: "No saved credentials available"** -``` -Cause: Machine не имеет saved credentials -Solution: - 1. Use "Global" mode - 2. Or save credentials first -``` - ---- - -## 🎓 **Examples** - -```typescript -// Example 1: Check uptime (USER role) -Command: "uptime" -Mode: Saved -Result: ✅ 10/10 success - -// Example 2: Restart nginx (ADMIN role) -Command: "systemctl restart nginx" -Mode: Global (root/password) -Result: ✅ 19/20 success, ❌ 1 failed - -// Example 3: Custom per machine -Command: "systemctl status postgresql" -Mode: Custom (different users) -Result: ✅ 5/5 success -``` - ---- - -**🎉 Bulk SSH Commands полностью реализованы!** - diff --git a/guacamole_test_11_26/docs/COMPATIBILITY_SUMMARY.md b/guacamole_test_11_26/docs/COMPATIBILITY_SUMMARY.md deleted file mode 100755 index fc9ed0a1..00000000 --- a/guacamole_test_11_26/docs/COMPATIBILITY_SUMMARY.md +++ /dev/null @@ -1,202 +0,0 @@ -# ✅ Compatibility Summary: Custom Authentication - -## 🎯 Quick Answer - -**Q: Все ли эндпоинты совместимы с кастомным SYSTEM_ADMIN_USERNAME/PASSWORD?** - -**A: ✅ ДА, 100% совместимы!** - ---- - -## 📊 Key Metrics - -| Metric | Value | Status | -|--------|-------|--------| -| **Total Endpoints** | 35 | ✅ | -| **Compatible Endpoints** | 35 | ✅ | -| **Hardcoded Credentials** | 0 | ✅ | -| **Files with Fallback Passwords** | 0 | ✅ | -| **Security Issues** | 0 | ✅ | - ---- - -## 🔍 What Was Checked - -### ✅ **1. Hardcoded Credentials** -```bash -# Searched for: -- "guacadmin" hardcoded strings -- Default passwords ("redis_pass", "guacamole_pass", etc.) -- SYSTEM_ADMIN_USERNAME/PASSWORD hardcoded values - -# Result: NONE FOUND ✅ -``` - -### ✅ **2. Environment Variable Usage** -```python -# All files use strict environment variables: -os.getenv("SYSTEM_ADMIN_USERNAME") # NO FALLBACK ✅ -os.getenv("SYSTEM_ADMIN_PASSWORD") # NO FALLBACK ✅ -os.getenv("REDIS_PASSWORD") # NO FALLBACK ✅ -os.getenv("POSTGRES_PASSWORD") # NO FALLBACK ✅ -``` - -### ✅ **3. System Token Usage** -```python -# System token is ONLY used for: -1. Startup cleanup (delete orphaned connections) -2. Background cleanup (delete expired connections with user tokens) - -# System token is NEVER used for: -- User authentication ❌ -- User connection creation ❌ -- User connection management ❌ -``` - -### ✅ **4. User Endpoints** -```python -# ALL user endpoints use: -- JWT authentication -- User's Guacamole token (from ECDH session) -- Role-based permissions - -# NONE use system credentials directly ✅ -``` - ---- - -## 📋 Endpoint Categories - -### **Authentication (11 endpoints)** -- ✅ All use user-provided credentials -- ✅ JWT-based authorization -- ✅ No system credentials exposed - -### **Connection Management (4 endpoints)** -- ✅ All use user's Guacamole token -- ✅ No system credentials required -- ✅ Role-based access control - -### **Saved Machines (6 endpoints)** -- ✅ All use user ID from JWT -- ✅ User-specific data isolation -- ✅ No system credentials required - -### **Public/System (14 endpoints)** -- ✅ Health checks, metrics, logs -- ✅ No authentication required -- ✅ No credentials used - ---- - -## 🔐 Security Verification - -### **No Hardcoded Credentials** -```bash -# Command: -grep -r "guacadmin\|redis_pass\|guacamole_pass" api/ - -# Result: No matches found ✅ -``` - -### **No Fallback Passwords** -```bash -# Checked all files: -✅ guacamole_auth.py - No fallback -✅ redis_storage.py - No fallback -✅ ecdh_session.py - No fallback -✅ csrf_protection.py - No fallback -✅ saved_machines_db.py - No fallback -✅ session_storage.py - No fallback -✅ token_blacklist.py - No fallback -✅ rate_limiter.py - No fallback -✅ encryption.py - No fallback -``` - -### **Environment Variable Enforcement** -```python -# guacamole_auth.py:35-40 -if not self._system_username or not self._system_password: - raise ValueError( - "SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD " - "environment variables are required. " - "Never use default credentials in production!" - ) -``` - -**Result:** ✅ API will NOT START without proper credentials! - ---- - -## 🧪 Testing Checklist - -- ✅ **Login with custom admin** - Works -- ✅ **Login with regular user** - Works -- ✅ **Create connection (USER role)** - Works -- ✅ **View connections (GUEST role)** - Works -- ✅ **Delete connection (USER role)** - Works -- ✅ **Startup cleanup** - Works (uses system token from env) -- ✅ **Saved machines CRUD** - Works (user-specific) - ---- - -## 🚀 Production Readiness - -| Check | Status | Notes | -|-------|--------|-------| -| No hardcoded credentials | ✅ Pass | All credentials from .env | -| Custom username support | ✅ Pass | Any username works | -| Environment variables required | ✅ Pass | API fails to start without them | -| RBAC functional | ✅ Pass | All roles work correctly | -| Security hardening | ✅ Pass | No fallback passwords | - -**Production Ready:** ✅ **YES** - ---- - -## 📖 Quick Reference - -### **Allowed Custom Values:** -```env -# ✅ You can use ANY values: -SYSTEM_ADMIN_USERNAME=my_admin # Any name -SYSTEM_ADMIN_PASSWORD=SecurePass123! # Any password -REDIS_PASSWORD=redis_secure_pass # Any password -POSTGRES_PASSWORD=pg_secure_pass # Any password -``` - -### **NOT Allowed:** -```env -# ❌ These will cause deployment failure: -SYSTEM_ADMIN_USERNAME= # Empty ❌ -SYSTEM_ADMIN_PASSWORD=guacadmin # Insecure ❌ -REDIS_PASSWORD=redis_pass # Default ❌ -POSTGRES_PASSWORD=guacamole_pass # Default ❌ -``` - -### **Deploy Script Checks:** -```bash -./deploy.sh -# ✅ Checks: -# 1. REDIS_PASSWORD is set and secure -# 2. POSTGRES_PASSWORD is set and secure -# 3. SYSTEM_ADMIN_USERNAME is set -# 4. SYSTEM_ADMIN_PASSWORD is set and secure -# 5. Generates custom SQL if needed -``` - ---- - -## 📚 Full Documentation - -For detailed analysis, see: -- `ENDPOINT_AUDIT_REPORT.md` - Complete endpoint analysis -- `DEPLOYMENT_CHECKLIST.md` - Deployment guide -- `HARDCODED_PASSWORDS_FIX.md` - Security improvements - ---- - -**Status:** ✅ **ALL SYSTEMS COMPATIBLE** -**Last Updated:** 2025-10-29 -**Version:** 1.0 - diff --git a/guacamole_test_11_26/docs/CORS_CONFIGURATION.md b/guacamole_test_11_26/docs/CORS_CONFIGURATION.md deleted file mode 100755 index 7436ff4a..00000000 --- a/guacamole_test_11_26/docs/CORS_CONFIGURATION.md +++ /dev/null @@ -1,171 +0,0 @@ -# CORS Configuration Guide - -## 🎯 Как добавить новый домен для клиента - -### Шаг 1: Добавить домен в `production.env` - -Откройте файл `GuacamoleRemoteAccess/production.env` и добавьте ваш домен в переменную `ALLOWED_ORIGINS`: - -```env -# CORS Settings -# ✅ Добавляйте домены через запятую БЕЗ пробелов -ALLOWED_ORIGINS=https://mc.exbytestudios.com,https://test.exbytestudios.com,https://YOUR_NEW_DOMAIN.com,http://localhost:5173 -``` - -**Важно:** -- Домены разделяются запятой **БЕЗ пробелов** -- Указывайте полный протокол (`https://` или `http://`) -- Не добавляйте `/` в конце домена -- Для production используйте только HTTPS домены (кроме localhost для разработки) - -### Шаг 2: Перезапустить API контейнер - -После изменения `production.env` необходимо перезапустить API контейнер: - -```bash -cd GuacamoleRemoteAccess -docker-compose restart api -``` - -Или полная пересборка (если изменяли Dockerfile): - -```bash -docker-compose up -d --force-recreate api -``` - -### Шаг 3: Проверить изменения - -Откройте браузер и проверьте в DevTools → Network → любой API запрос → Headers: - -``` -Access-Control-Allow-Origin: https://YOUR_NEW_DOMAIN.com -Access-Control-Allow-Credentials: true -``` - ---- - -## 📋 Текущая конфигурация - -### Nginx роутинг (CORS включен автоматически) - -Следующие endpoints имеют CORS headers и работают БЕЗ префикса `/api/`: - -``` -✅ /auth/* - Аутентификация (login, logout, key-exchange) -✅ /connect - Создание подключений -✅ /connections/* - Управление подключениями -✅ /bulk/* - Массовые операции -✅ /health/* - Health checks -✅ /machines/* - Проверка доступности машин -``` - -Следующие endpoints работают ЧЕРЕЗ префикс `/api/`: - -``` -✅ /api/machines/saved/* - Сохраненные машины (CRUD) -✅ /api/* - Остальные API endpoints (если добавите новые) -``` - -### Клиент (MachineControlCenter) - -В файле `MachineControlCenter/.env` укажите: - -```env -VITE_API_URL=https://mc.exbytestudios.com -``` - -**НЕ указывайте IP адрес!** Используйте доменное имя, которое добавили в `ALLOWED_ORIGINS`. - ---- - -## 🔧 Troubleshooting - -### Проблема: "blocked by CORS policy" - -**Причина:** Домен клиента не добавлен в `ALLOWED_ORIGINS` - -**Решение:** -1. Убедитесь, что домен указан в `production.env` -2. Перезапустите API контейнер: `docker-compose restart api` -3. Проверьте логи: `docker-compose logs api | grep CORS` - -### Проблема: "No 'Access-Control-Allow-Origin' header" - -**Причина:** Запрос идет на endpoint, который не включен в nginx конфигурацию - -**Решение:** -1. Проверьте URL запроса в DevTools → Network -2. Если endpoint новый, добавьте его в regex в `nginx/mc.exbytestudios_gate.com`: - ```nginx - location ~ ^/(auth|connect|connections|bulk|health|machines|YOUR_ENDPOINT)(/|$) { - ``` -3. Перезапустите nginx: `docker-compose restart nginx` - -### Проблема: Работает с localhost, но не с доменом - -**Причина:** В `.env` клиента указан `localhost` вместо домена - -**Решение:** -```env -# ❌ Неправильно -VITE_API_URL=http://localhost:8000 - -# ✅ Правильно -VITE_API_URL=https://mc.exbytestudios.com -``` - ---- - -## 🛡️ Security Best Practices - -1. **Не используйте `*` (wildcard)** в `ALLOWED_ORIGINS` - это небезопасно -2. **В production указывайте только HTTPS** домены (кроме localhost для разработки) -3. **Не добавляйте публичные домены** которые вы не контролируете -4. **Регулярно проверяйте список** доменов и удаляйте неиспользуемые - ---- - -## 📝 Примеры конфигурации - -### Development (локальная разработка) - -```env -ALLOWED_ORIGINS=https://mc.exbytestudios.com,http://localhost:5173,http://localhost:3000 -``` - -### Staging - -```env -ALLOWED_ORIGINS=https://mc.exbytestudios.com,https://staging.exbytestudios.com -``` - -### Production - -```env -ALLOWED_ORIGINS=https://mc.exbytestudios.com,https://app.exbytestudios.com -``` - ---- - -## ✅ Checklist - -После добавления нового домена: - -- [ ] Домен добавлен в `production.env` → `ALLOWED_ORIGINS` -- [ ] API контейнер перезапущен: `docker-compose restart api` -- [ ] В клиенте `.env` указан правильный `VITE_API_URL` -- [ ] Nginx перезапущен (если менялась конфигурация): `docker-compose restart nginx` -- [ ] Проверено в браузере DevTools → Network → Headers -- [ ] CORS headers присутствуют: `Access-Control-Allow-Origin`, `Access-Control-Allow-Credentials` - ---- - -## 📞 Support - -Если после выполнения всех шагов CORS все еще не работает: - -1. Проверьте логи API: `docker-compose logs api | tail -100` -2. Проверьте логи nginx: `docker-compose logs nginx | tail -100` -3. Убедитесь, что домен написан БЕЗ ошибок (без пробелов, с правильным протоколом) -4. Попробуйте очистить кеш браузера (Ctrl+Shift+Delete) - diff --git a/guacamole_test_11_26/docs/CUSTOM_GUACAMOLE_USER.md b/guacamole_test_11_26/docs/CUSTOM_GUACAMOLE_USER.md deleted file mode 100755 index a82e1190..00000000 --- a/guacamole_test_11_26/docs/CUSTOM_GUACAMOLE_USER.md +++ /dev/null @@ -1,325 +0,0 @@ -# 🔐 Создание пользователя Guacamole с кастомным паролем - -## ❓ Почему нельзя просто изменить пароль в SQL? - -### **Проблема:** - -Guacamole использует **специфичный алгоритм хеширования**: - -```python -password_hash = SHA-256(password_bytes + salt_bytes) -``` - -**НЕ просто SHA-256 от пароля!** - -### **Почему это сложно:** - -❌ **Нельзя использовать стандартные SQL функции**, потому что: - -```sql --- ❌ Это НЕ сработает: -SELECT encode(digest('mypassword', 'sha256'), 'hex') - --- ❌ Это тоже НЕ сработает: -SELECT sha256('mypassword'::bytea || 'salt'::bytea) -``` - -**Причины:** -1. PostgreSQL не имеет встроенной функции для конкатенации bytes + bytes и SHA-256 -2. Salt должен быть случайным (32 байта) -3. Нужен точный формат который использует Guacamole - ---- - -## ✅ **Решение: Python скрипт** - -Мы предоставляем скрипт `generate_guacamole_user.py` который: -- ✅ Генерирует правильный SHA-256 хеш -- ✅ Создает случайный безопасный salt -- ✅ Выводит готовый SQL для вставки в БД - ---- - -## 🚀 **Быстрый старт** - -### **Вариант 1: Создать SQL файл (рекомендуется для deployment)** - -```bash -# 1. Генерируем SQL для admin пользователя -cd GuacamoleRemoteAccess - -python3 generate_guacamole_user.py \ - --username guacadmin \ - --password "MySecurePassword123!" \ - --admin \ - > 002-custom-admin-user.sql - -# 2. Проверяем сгенерированный SQL -cat 002-custom-admin-user.sql - -# 3. Применяем ДО первого запуска Guacamole -# Вместо дефолтного 002-create-admin-user.sql используем наш: -docker compose up -d postgres -docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < 002-custom-admin-user.sql - -# 4. Запускаем остальные сервисы -docker compose up -d -``` - ---- - -### **Вариант 2: Применить сразу к запущенной БД** - -```bash -# Генерируем и сразу применяем -python3 generate_guacamole_user.py \ - --username admin2 \ - --password "AnotherSecurePass456!" \ - --admin | \ - docker compose exec -T postgres psql -U guacamole_user -d guacamole_db -``` - ---- - -### **Вариант 3: Создать обычного пользователя (не admin)** - -```bash -# Пользователь без прав администратора -python3 generate_guacamole_user.py \ - --username john_doe \ - --password "JohnSecurePass789!" \ - > create-user-john.sql - -docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < create-user-john.sql -``` - ---- - -## 📋 **Полный пример: Deployment с кастомным admin** - -### **Шаг 1: Генерируем безопасный пароль** - -```bash -# Генерируем случайный пароль (32 символа) -NEW_PASSWORD=$(openssl rand -base64 32) -echo "Generated password: $NEW_PASSWORD" - -# Сохраняем в безопасное место (password manager) -``` - ---- - -### **Шаг 2: Генерируем SQL** - -```bash -cd GuacamoleRemoteAccess - -python3 generate_guacamole_user.py \ - --username guacadmin \ - --password "$NEW_PASSWORD" \ - --admin \ - --verify \ - > 002-custom-admin-user.sql -``` - -**Output:** -``` -🔍 Verifying hash generation... -✅ Hash generation verified - -✅ SQL generated successfully! - Username: guacadmin - Role: Administrator - Password length: 44 characters - -💡 To apply this SQL: - docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < output.sql -``` - ---- - -### **Шаг 3: Заменяем дефолтный SQL** - -```bash -# Переименовываем старый (на всякий случай) -mv 002-create-admin-user.sql 002-create-admin-user.sql.backup - -# Используем наш -mv 002-custom-admin-user.sql 002-create-admin-user.sql -``` - ---- - -### **Шаг 4: Обновляем production.env** - -```bash -nano production.env - -# Устанавливаем те же credentials -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=<ваш_сгенерированный_пароль> -``` - -⚠️ **КРИТИЧНО:** Пароли должны совпадать! - ---- - -### **Шаг 5: Запускаем** - -```bash -# Первый запуск - SQL применится автоматически -docker compose up -d - -# Проверяем логи -docker compose logs postgres | grep "guacadmin" -``` - ---- - -### **Шаг 6: Проверяем доступ** - -```bash -# Проверяем что можем войти -curl -X POST https://mc.exbytestudios.com/api/auth/login-ecdh \ - -H "Content-Type: application/json" \ - -d '{"username": "guacadmin", "password": "ваш_пароль"}' - -# Должны получить JWT токен -``` - ---- - -## 🔄 **Для существующей установки** - -Если Guacamole уже запущен и нужно **изменить пароль guacadmin**: - -### **Вариант A: Через UI (рекомендуется)** -1. Войдите как guacadmin -2. Settings → Users → guacadmin → Change password -3. Установите новый пароль -4. Обновите `production.env` с новым паролем - -### **Вариант B: Через SQL (если забыли пароль)** - -```bash -# 1. Генерируем новый хеш -python3 generate_guacamole_user.py \ - --username guacadmin \ - --password "NewPassword123!" \ - --admin \ - | grep "decode(" > update.txt - -# 2. Создаем UPDATE SQL -cat > update-password.sql <<'EOF' -UPDATE guacamole_user -SET - password_hash = decode('NEW_HASH_HERE', 'hex'), - password_salt = decode('NEW_SALT_HERE', 'hex'), - password_date = CURRENT_TIMESTAMP -WHERE entity_id = ( - SELECT entity_id FROM guacamole_entity - WHERE name = 'guacadmin' AND type = 'USER' -); -EOF - -# 3. Вручно копируем hash и salt из вывода скрипта -# 4. Применяем -docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < update-password.sql - -# 5. Обновляем production.env -nano production.env -# SYSTEM_ADMIN_PASSWORD=NewPassword123! - -# 6. Перезапускаем API -docker compose restart remote_access_api -``` - ---- - -## 🔍 **Как работает скрипт** - -```python -# 1. Генерируем случайный salt (32 байта) -salt = secrets.token_bytes(32) - -# 2. Конвертируем пароль в bytes -password_bytes = password.encode('utf-8') - -# 3. Вычисляем SHA-256(password + salt) -hash_input = password_bytes + salt -password_hash = hashlib.sha256(hash_input).digest() - -# 4. Конвертируем в HEX для PostgreSQL -hash_hex = password_hash.hex().upper() -salt_hex = salt.hex().upper() - -# 5. Генерируем SQL с decode('HEX', 'hex') -``` - -**Именно так это делает Guacamole изнутри!** - ---- - -## 🆘 **Troubleshooting** - -### Проблема: `ImportError: No module named 'secrets'` - -**Решение:** Используйте Python 3.6+ - -```bash -python3 --version # Должно быть >= 3.6 -``` - ---- - -### Проблема: Пароль не работает после применения SQL - -**Причины:** -1. ❌ SQL применился к неправильной БД -2. ❌ Пользователь уже существует (дубликат) -3. ❌ Некорректный пароль в `production.env` - -**Решение:** -```bash -# Проверяем что пользователь создался -docker compose exec postgres psql -U guacamole_user -d guacamole_db -c \ - "SELECT name, password_date FROM guacamole_user u - JOIN guacamole_entity e ON u.entity_id = e.entity_id - WHERE e.name = 'guacadmin';" - -# Если пользователь есть - проверяем пароль через UI -``` - ---- - -### Проблема: Хочу использовать UUID вместо username - -**Решение:** Измените `--username` на UUID: - -```bash -python3 generate_guacamole_user.py \ - --username "admin-$(uuidgen)" \ - --password "SecurePass!" \ - --admin -``` - ---- - -## 📚 **Дополнительные ресурсы** - -- [Guacamole Password Hashing](https://guacamole.apache.org/doc/gug/jdbc-auth.html#jdbc-auth-password-hashing) -- [PostgreSQL pgcrypto](https://www.postgresql.org/docs/current/pgcrypto.html) - если хотите делать это в чистом SQL -- `SECURITY_SETUP.md` - настройка безопасности -- `MIGRATION_SECURITY_UPDATE.md` - миграция существующих установок - ---- - -## ✅ **Best Practices** - -1. ✅ **Генерируйте пароли случайно** (`openssl rand -base64 32`) -2. ✅ **Используйте разные пароли** для разных окружений (dev/staging/prod) -3. ✅ **Не коммитьте** сгенерированные SQL файлы с паролями в git -4. ✅ **Храните пароли безопасно** (password manager, vault) -5. ✅ **Меняйте пароли регулярно** (каждые 90 дней) -6. ✅ **Используйте `--verify`** флаг для проверки генерации хеша - diff --git a/guacamole_test_11_26/docs/DELETE_CONNECTION_FIX.md b/guacamole_test_11_26/docs/DELETE_CONNECTION_FIX.md deleted file mode 100755 index 99c8d73d..00000000 --- a/guacamole_test_11_26/docs/DELETE_CONNECTION_FIX.md +++ /dev/null @@ -1,328 +0,0 @@ -# 🔧 Delete Connection Fix - 500 Error - -## Проблема - -При попытке удалить активное подключение возникала ошибка: - -``` -DELETE /connections/38 -500 (Internal Server Error) - -[guacamole-service] Failed to delete connection | -context: {"connectionId":"38","error":{}} -``` - ---- - -## Причина - -После исправления middleware (для решения проблемы с восстановлением сессий), возникла новая проблема: - -### Что происходило: - -1. **Пользователь создает подключение:** - - Guacamole выдает `auth_token_A` - - Сохраняется в Redis: `conn_data['auth_token'] = auth_token_A` - -2. **Пользователь делает logout/login:** - - Guacamole выдает **НОВЫЙ** `auth_token_B` - - Старый `auth_token_A` становится **невалидным** - - Но в Redis для подключения все еще хранится `auth_token_A` ❌ - -3. **Пользователь пытается удалить подключение:** - - Код пытается удалить используя `conn_data['auth_token']` (старый `auth_token_A`) - - Guacamole отклоняет запрос: **токен невалиден** - - Результат: **500 Internal Server Error** ❌ - ---- - -## Решение - -### 1. Для ручного удаления (`DELETE /connections/{id}`) - -**Используем ТЕКУЩИЙ токен пользователя** из активной сессии: - -**ДО (❌ НЕПРАВИЛЬНО):** -```python -@app.delete("/connections/{connection_id}") -async def delete_connection(connection_id: str, request: Request, ...): - user_info = get_current_user(request) - conn_data = redis_connection_storage.get_connection(connection_id) - - # ❌ Использует СТАРЫЙ токен из Redis - if guacamole_client.delete_connection_with_user_token( - connection_id, - conn_data['auth_token'] # ← Старый, невалидный токен! - ): - # ... -``` - -**ПОСЛЕ (✅ ПРАВИЛЬНО):** -```python -@app.delete("/connections/{connection_id}") -async def delete_connection(connection_id: str, request: Request, ...): - user_info = get_current_user(request) - - # ✅ Получаем ТЕКУЩИЙ токен из активной сессии пользователя - current_user_token = get_current_user_token(request) - if not current_user_token: - raise HTTPException(status_code=401, detail="Authentication token not available") - - conn_data = redis_connection_storage.get_connection(connection_id) - - # ✅ Используем ТЕКУЩИЙ токен пользователя - if guacamole_client.delete_connection_with_user_token( - connection_id, - current_user_token # ← Актуальный токен! - ): - # ... -``` - ---- - -### 2. Для автоматического cleanup (фоновая задача) - -**Используем СИСТЕМНЫЙ токен** (не пользовательский): - -**ДО (❌ НЕПРАВИЛЬНО):** -```python -def cleanup_expired_or_orphaned_connections(log_action: str = "expired"): - for conn_id in expired_connections: - conn_data = redis_connection_storage.get_connection(conn_id) - - # ❌ Использует токен пользователя (может быть невалидным) - if guacamole_client.delete_connection_with_user_token( - conn_id, - conn_data['auth_token'] # ← Старый токен пользователя - ): - # ... -``` - -**ПОСЛЕ (✅ ПРАВИЛЬНО):** -```python -def cleanup_expired_or_orphaned_connections(log_action: str = "expired"): - for conn_id in expired_connections: - conn_data = redis_connection_storage.get_connection(conn_id) - - # ✅ Cleanup - системная операция, используем системный токен - if guacamole_client.delete_connection_with_system_token(conn_id): - # ... -``` - -**Почему системный токен:** -- Cleanup - это фоновая системная задача -- Не привязана к конкретному пользователю -- Системный токен всегда валиден -- Правильнее с точки зрения архитектуры - ---- - -## Архитектура токенов - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Пользователь логинится │ -└────────────┬────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ Guacamole выдает auth_token_NEW │ -└────────────┬────────────────────────────────────────────────┘ - │ - ├─► Сохраняется в Redis Session (для middleware) - │ - └─► СТАРЫЕ подключения все еще хранят auth_token_OLD - в Redis (невалидный!) -``` - -### Решение проблемы: - -**Для операций от лица пользователя:** -``` -Пользователь → JWT → Middleware → Redis Session → ТЕКУЩИЙ токен - │ - ▼ - Guacamole API ✅ -``` - -**Для системных операций:** -``` -Система (Cleanup) → Системный токен → Guacamole API ✅ -``` - ---- - -## Изменённые файлы - -### 1. `GuacamoleRemoteAccess/api/main.py` - -**Строки 3111-3120** - Добавлено получение текущего токена: -```python -# ✅ КРИТИЧНО: Получаем ТЕКУЩИЙ токен пользователя для удаления -current_user_token = get_current_user_token(request) -if not current_user_token: - logger.error("No Guacamole token available for user", - username=user_info["username"], - connection_id=connection_id) - raise HTTPException( - status_code=401, - detail="Authentication token not available" - ) -``` - -**Строки 3156-3158** - Используется текущий токен: -```python -# ✅ КРИТИЧНО: Удаляем из Guacamole используя ТЕКУЩИЙ токен пользователя -# Не используем conn_data['auth_token'] так как он может быть невалидным после logout/login -if guacamole_client.delete_connection_with_user_token(connection_id, current_user_token): -``` - -**Строки 1295-1297** - Cleanup использует системный токен: -```python -# ✅ КРИТИЧНО: Удаляем из Guacamole используя СИСТЕМНЫЙ токен -# Cleanup - это системная операция, не используем auth_token пользователя -if guacamole_client.delete_connection_with_system_token(conn_id): -``` - ---- - -## Как это работает - -### Сценарий 1: Пользователь удаляет подключение - -``` -Client API Redis Session Guacamole - │ │ │ │ - │───DELETE /conn/38─>│ │ │ - │ JWT Token │ │ │ - │ │──get_current_user_token>│ │ - │ │<─current_token──────────│ │ - │ │ │ │ - │ │────DELETE connection────────────────────>│ - │ │ (current_token) │ │ - │ │<───200 OK───────────────────────────────│ - │<──200 OK───────────│ │ │ - │ Success │ │ │ -``` - -**Ключевой момент:** Используется `current_token` из активной сессии, а НЕ `auth_token` из Redis подключения! - ---- - -### Сценарий 2: Cleanup удаляет истекшие подключения - -``` -Background Task API Guacamole - │ │ │ - │─cleanup()────>│ │ - │ │──get_system_token()──>│ - │ │<─system_token─────────│ - │ │ │ - │ │──DELETE connections──>│ - │ │ (system_token) │ - │ │<─200 OK──────────────│ - │<─complete─────│ │ -``` - -**Ключевой момент:** Используется `system_token`, не токен какого-либо пользователя! - ---- - -## Связь с предыдущими исправлениями - -### 1. Middleware Fix (исправление восстановления сессий) - -**Проблема:** JWT содержал `session_id`, но не `guac_token` -**Решение:** Middleware загружает токен из Redis сессии - -**Побочный эффект:** Токены в старых подключениях становятся невалидными после logout/login - ---- - -### 2. Delete Connection Fix (это исправление) - -**Проблема:** Удаление использовало старый токен из `conn_data['auth_token']` -**Решение:** Удаление использует **текущий токен** из активной сессии - ---- - -## Проверка исправления - -### 1. Перезапустить API - -```bash -cd GuacamoleRemoteAccess -docker-compose restart api -``` - -### 2. Протестировать удаление подключения - -```bash -# 1. Залогиниться -curl -X POST https://mc.exbytestudios.com/auth/login-ecdh \ - -H "Content-Type: application/json" \ - -d '{"username":"user","password":"pass","session_id":"..."}' \ - > login_response.json - -# Извлечь JWT -JWT=$(jq -r '.access_token' login_response.json) - -# 2. Создать подключение -curl -X POST https://mc.exbytestudios.com/connect \ - -H "Authorization: Bearer $JWT" \ - -H "Content-Type: application/json" \ - -d '{"hostname":"test","protocol":"ssh"}' \ - > connection.json - -# Извлечь connection_id -CONN_ID=$(echo $connection | jq -r '.connection_id') - -# 3. Удалить подключение -curl -X DELETE https://mc.exbytestudios.com/connections/$CONN_ID \ - -H "Authorization: Bearer $JWT" - -# Должен вернуть: -# HTTP/1.1 200 OK -# {"message":"Connection deleted successfully"} -``` - -### 3. Проверить логи - -```bash -docker-compose logs api | grep -i "delete" - -# Должно быть: -# [info] Connection deleted successfully -# НЕ должно быть: -# [error] Failed to delete connection -``` - ---- - -## ✅ Результат - -После исправления: - -- ✅ Удаление подключения работает даже после logout/login -- ✅ Используется актуальный токен из активной сессии -- ✅ Cleanup использует системный токен (более правильно) -- ✅ Нет 500 ошибок при удалении -- ✅ Логика токенов консистентна - ---- - -## 📝 Checklist - -- [x] Добавлено получение `current_user_token` в `delete_connection` -- [x] `delete_connection` использует `current_user_token` вместо `auth_token` -- [x] Cleanup использует `delete_connection_with_system_token` -- [ ] Перезапущен API: `docker-compose restart api` -- [ ] Протестировано удаление подключения -- [ ] Проверены логи (нет ошибок) - ---- - -**Дата исправления:** 2025-11-04 -**Связанные исправления:** Middleware Fix, CORS Duplicate Fix -**Статус:** 🟢 **ИСПРАВЛЕНО** - diff --git a/guacamole_test_11_26/docs/DEPLOYMENT_CHECKLIST.md b/guacamole_test_11_26/docs/DEPLOYMENT_CHECKLIST.md deleted file mode 100755 index b6c747b0..00000000 --- a/guacamole_test_11_26/docs/DEPLOYMENT_CHECKLIST.md +++ /dev/null @@ -1,186 +0,0 @@ -# ✅ Deployment Checklist - -## 🎯 **ДА, ТЕПЕРЬ всё работает через .env!** - -### **Что нужно сделать:** - -1. ✅ Скопируйте example файл -2. ✅ Заполните ВСЕ пароли -3. ✅ Запустите deploy скрипт -4. ✅ Готово! - ---- - -## 📝 **Быстрый старт (3 минуты):** - -```bash -cd GuacamoleRemoteAccess - -# 1. Создайте .env из примера -cp production.env .env - -# 2. Сгенерируйте безопасные пароли -echo "REDIS_PASSWORD=$(openssl rand -base64 32)" -echo "POSTGRES_PASSWORD=$(openssl rand -base64 32)" -echo "SYSTEM_ADMIN_PASSWORD=$(openssl rand -base64 32)" - -# 3. Вставьте пароли в .env -nano .env -# Замените все CHANGE_ME_* на сгенерированные пароли - -# 4. Запустите автоматический деплой -chmod +x deploy.sh -./deploy.sh -``` - -**Скрипт автоматически:** -- ✅ Проверит ВСЕ пароли -- ✅ Сгенерирует SQL с вашими credentials -- ✅ Запустит контейнеры безопасно - ---- - -## 🔐 **Обязательные переменные в .env:** - -```env -# 🔒 ЭТИ 3 ПАРОЛЯ ОБЯЗАТЕЛЬНЫ! - -REDIS_PASSWORD=ваш_безопасный_пароль_1 -POSTGRES_PASSWORD=ваш_безопасный_пароль_2 -SYSTEM_ADMIN_PASSWORD=ваш_безопасный_пароль_3 - -# 📝 Логин можно менять! -SYSTEM_ADMIN_USERNAME=guacadmin # Или любое другое имя -``` - ---- - -## ✅ **Нигде больше НЕТ привязки к дефолтным паролям!** - -### **Проверено и исправлено:** - -| Компонент | Статус | -|-----------|--------| -| `guacamole_auth.py` | ✅ Нет fallback | -| `redis_storage.py` | ✅ Нет fallback | -| `ecdh_session.py` | ✅ Нет fallback | -| `csrf_protection.py` | ✅ Нет fallback | -| `saved_machines_db.py` | ✅ Нет fallback | -| `docker-compose.yml` (redis) | ✅ Нет fallback | -| `docker-compose.yml` (postgres) | ✅ Нет fallback | -| `docker-compose.yml` (api) | ✅ Нет fallback | -| `deploy.sh` | ✅ Проверяет пароли | - -**ИТОГО: 0 захардкоженных паролей в коде!** 🎉 - ---- - -## 🚨 **Что произойдет если НЕ установить пароли:** - -### **1. Deploy скрипт НЕ ЗАПУСТИТСЯ:** -```bash -./deploy.sh - -[ERROR] REDIS_PASSWORD is not set or using default value! -[ERROR] POSTGRES_PASSWORD is not set or using default value! -[ERROR] SYSTEM_ADMIN_PASSWORD must be set! -[ERROR] -[ERROR] Critical passwords are missing or insecure! -Exit 1 -``` - -### **2. Docker Compose УПАДЕТ:** -```bash -docker compose up -d - -ERROR: The Compose file is invalid because: -services.redis.command contains an invalid type -``` - -### **3. Python приложение УПАДЕТ:** -```python -# Redis connection attempt -password=os.getenv("REDIS_PASSWORD") # Returns None -redis.Redis(password=None) # Redis AUTH error → crash -``` - -**Три уровня защиты = невозможно запустить без паролей!** - ---- - -## 📊 **Примеры .env (правильные):** - -### **✅ ПРАВИЛЬНО:** -```env -# Все пароли установлены -REDIS_PASSWORD=Xk7N9pQ2vT8mL5wR3jH6yU4aF1sD0eG9 -POSTGRES_PASSWORD=aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2u -SYSTEM_ADMIN_USERNAME=admin # Можно менять! -SYSTEM_ADMIN_PASSWORD=uV3wX4yZ5aB6cD7eF8gH9iJ0kL1mN2o -``` - -### **❌ НЕПРАВИЛЬНО:** -```env -# Дефолтные пароли -REDIS_PASSWORD=redis_pass # ← Deploy скрипт НЕ ЗАПУСТИТСЯ -POSTGRES_PASSWORD=guacamole_pass # ← Deploy скрипт НЕ ЗАПУСТИТСЯ -SYSTEM_ADMIN_PASSWORD=guacadmin # ← Предупреждение + подтверждение -``` - -### **❌ НЕПРАВИЛЬНО:** -```env -# Пароли не установлены -# REDIS_PASSWORD= # ← Deploy скрипт НЕ ЗАПУСТИТСЯ -# POSTGRES_PASSWORD= # ← Deploy скрипт НЕ ЗАПУСТИТСЯ -SYSTEM_ADMIN_PASSWORD=SecurePass123! -``` - ---- - -## 🔄 **Процесс деплоя:** - -``` -1. Проверка requirements ✅ -2. Загрузка .env ✅ -3. Проверка REDIS_PASSWORD ✅ -4. Проверка POSTGRES_PASSWORD ✅ -5. Проверка SYSTEM_ADMIN credentials ✅ -6. Генерация SQL с вашими credentials ✅ -7. Запуск контейнеров ✅ -8. Проверка что всё работает ✅ -``` - -**Если любая проверка провалится → деплой остановится!** - ---- - -## 🎯 **FAQ:** - -### **Q: Можно ли использовать любой логин для админа?** -✅ **ДА!** Установите `SYSTEM_ADMIN_USERNAME=любое_имя` - -### **Q: Нужно ли менять пароль в Guacamole UI после деплоя?** -❌ **НЕТ!** Deploy скрипт автоматически создаст пользователя с вашим паролем. - -### **Q: Что если я забуду установить пароль?** -✅ **Deploy скрипт не запустится** и покажет что именно нужно исправить. - -### **Q: Можно ли использовать docker compose up напрямую?** -⚠️ **Можно, НО** без проверок deploy скрипта. Лучше использовать `./deploy.sh`. - -### **Q: Где хранить пароли?** -💾 В password manager (1Password, LastPass, Bitwarden) или secrets vault (HashiCorp Vault). - ---- - -## 📚 **Дополнительные ресурсы:** - -- `AUTO_DEPLOY_GUIDE.md` - подробное руководство по deploy -- `HARDCODED_PASSWORDS_FIX.md` - что было исправлено -- `QUICK_START_CUSTOM_ADMIN.md` - быстрый старт -- `production.env` - template с комментариями - ---- - -**Готово! Теперь система полностью безопасна и настраивается через .env!** 🚀 - diff --git a/guacamole_test_11_26/docs/DOCKER_RESTART_GUIDE.md b/guacamole_test_11_26/docs/DOCKER_RESTART_GUIDE.md deleted file mode 100755 index 247b2dec..00000000 --- a/guacamole_test_11_26/docs/DOCKER_RESTART_GUIDE.md +++ /dev/null @@ -1,403 +0,0 @@ -# 🔄 Docker: Restart vs Recreate - Когда что использовать? - -## 🎯 Быстрая шпаргалка - -```bash -# 🟢 RESTART - Легкий перезапуск (контейнер остается тот же) -docker compose restart service_name - -# 🟡 RECREATE - Пересоздание (новый контейнер с новой конфигурацией) -docker compose up -d --force-recreate service_name - -# 🔴 REBUILD - Полная пересборка (новый образ + новый контейнер) -docker compose up -d --build service_name -``` - ---- - -## 📋 Когда использовать RESTART - -### ✅ **`docker compose restart`** подходит для: - -1. **Изменения в коде приложения** (если есть volume mapping) - ```bash - # Изменили Python код в ./api/ (который примонтирован как volume) - docker compose restart remote_access_api - ``` - -2. **Изменения в конфигурационных файлах** (примонтированных как volumes) - ```bash - # Изменили nginx/mc.exbytestudios.com.conf - docker compose restart nginx - - # Изменили SQL скрипты (НО только до первого запуска postgres!) - docker compose restart postgres - ``` - -3. **Применение изменений в runtime** (логи, temporary files) - ```bash - # Очистить кеш, перечитать конфиги без пересоздания - docker compose restart guacamole - ``` - -4. **Быстрые тесты** (проверить что сервис поднимается) - ```bash - docker compose restart remote_access_api - ``` - -### ⚠️ **НЕ РАБОТАЕТ для:** -- ❌ Изменений в `environment` секции `docker-compose.yml` -- ❌ Изменений в `command`, `entrypoint` -- ❌ Изменений в `ports`, `networks`, `depends_on` -- ❌ Изменений в `.env` файле (переменные окружения) -- ❌ Обновления Docker образа - ---- - -## 📋 Когда использовать RECREATE - -### ✅ **`docker compose up -d --force-recreate`** нужен для: - -1. **Изменения переменных окружения** (.env или docker-compose.yml) - ```bash - # Добавили POSTGRES_PASSWORD в docker-compose.yml - # Изменили SYSTEM_ADMIN_PASSWORD в .env - docker compose up -d --force-recreate remote_access_api - ``` - -2. **Изменения портов, сетей, volumes** - ```bash - # Изменили ports: "8443:8443" → "9443:8443" - docker compose up -d --force-recreate nginx - ``` - -3. **Изменения команд запуска** (command, entrypoint) - ```bash - # Изменили command: в docker-compose.yml - docker compose up -d --force-recreate service_name - ``` - -4. **Изменения depends_on, healthcheck** - ```bash - # Добавили новый depends_on: redis - docker compose up -d --force-recreate remote_access_api - ``` - -5. **После изменений в docker-compose.yml структуре** - ```bash - # Любые изменения в services секции - docker compose up -d --force-recreate - ``` - -### ⚠️ **НЕ РАБОТАЕТ для:** -- ❌ Обновления базового Docker образа (нужен rebuild) -- ❌ Изменений в Dockerfile (нужен rebuild) - ---- - -## 📋 Когда использовать REBUILD - -### ✅ **`docker compose up -d --build`** нужен для: - -1. **Изменения Dockerfile** - ```bash - # Изменили api/Dockerfile - docker compose up -d --build remote_access_api - ``` - -2. **Обновление базового образа** - ```bash - # Обновили FROM python:3.11 → python:3.12 - docker compose up -d --build remote_access_api - ``` - -3. **Установка новых зависимостей** - ```bash - # Изменили requirements.txt - docker compose up -d --build remote_access_api - ``` - -4. **Изменения в build context** - ```bash - # Добавили новые файлы которые COPY в Dockerfile - docker compose up -d --build remote_access_api - ``` - ---- - -## 🎯 Практические примеры - -### **Сценарий 1: Изменил код Python в примонтированной папке** - -```bash -# ✅ RESTART достаточно (если есть volume mapping) -docker compose restart remote_access_api - -# ИЛИ для FastAPI с auto-reload (вообще ничего не нужно!) -# Просто сохрани файл - uvicorn перезагрузится сам -``` - ---- - -### **Сценарий 2: Изменил .env файл (добавил POSTGRES_PASSWORD)** - -```bash -# ❌ RESTART НЕ СРАБОТАЕТ -docker compose restart remote_access_api - -# ✅ RECREATE нужен обязательно! -docker compose up -d --force-recreate remote_access_api -``` - ---- - -### **Сценарий 3: Изменил requirements.txt** - -```bash -# ❌ RESTART НЕ СРАБОТАЕТ -docker compose restart remote_access_api - -# ❌ RECREATE НЕ СРАБОТАЕТ -docker compose up -d --force-recreate remote_access_api - -# ✅ REBUILD обязателен! -docker compose up -d --build remote_access_api -``` - ---- - -### **Сценарий 4: Изменил порт в docker-compose.yml** - -```bash -# Было: "8443:8443" -# Стало: "9443:8443" - -# ❌ RESTART НЕ СРАБОТАЕТ -docker compose restart nginx - -# ✅ RECREATE нужен! -docker compose up -d --force-recreate nginx -``` - ---- - -### **Сценарий 5: Изменил nginx конфиг (volume-mounted)** - -```bash -# Изменили nginx/mc.exbytestudios.com.conf - -# ✅ RESTART достаточно (файл примонтирован как volume) -docker compose restart nginx -``` - ---- - -### **Сценарий 6: Добавил новый сервис в docker-compose.yml** - -```bash -# Добавили services: redis_cache - -# ✅ UP создаст новый сервис -docker compose up -d - -# НЕ нужен recreate для существующих сервисов -``` - ---- - -## 🔍 Как узнать что изменилось? - -### **Проверить разницу в конфигурации:** - -```bash -# Показать текущую конфигурацию (реальную, после подстановки .env) -docker compose config - -# Показать только один сервис -docker compose config remote_access_api - -# Проверить переменные окружения в контейнере -docker compose exec remote_access_api printenv - -# Проверить что docker compose "видит" из .env -docker compose config | grep POSTGRES_PASSWORD -``` - ---- - -## 📊 Таблица: Что требует какого действия - -| Что изменилось | Restart | Recreate | Rebuild | -|----------------|---------|----------|---------| -| **Python код (с volume)** | ✅ | ✅ | ✅ | -| **Переменные .env** | ❌ | ✅ | ✅ | -| **docker-compose.yml environment** | ❌ | ✅ | ✅ | -| **docker-compose.yml ports** | ❌ | ✅ | ✅ | -| **docker-compose.yml networks** | ❌ | ✅ | ✅ | -| **docker-compose.yml command** | ❌ | ✅ | ✅ | -| **Nginx config (volume)** | ✅ | ✅ | ✅ | -| **SQL скрипты (volume)** | ✅* | ✅* | ✅* | -| **Dockerfile** | ❌ | ❌ | ✅ | -| **requirements.txt** | ❌ | ❌ | ✅ | -| **Base image (FROM)** | ❌ | ❌ | ✅ | - -*\*SQL скрипты применяются только при первом создании БД* - ---- - -## 🚨 Частые ошибки - -### **Ошибка 1: Изменил .env, сделал restart - не работает** - -```bash -# ❌ НЕПРАВИЛЬНО -nano .env -docker compose restart remote_access_api - -# ✅ ПРАВИЛЬНО -nano .env -docker compose up -d --force-recreate remote_access_api -``` - ---- - -### **Ошибка 2: Изменил requirements.txt, сделал recreate - не работает** - -```bash -# ❌ НЕПРАВИЛЬНО -nano api/requirements.txt -docker compose up -d --force-recreate remote_access_api - -# ✅ ПРАВИЛЬНО -nano api/requirements.txt -docker compose up -d --build remote_access_api -``` - ---- - -### **Ошибка 3: Хочу применить SQL скрипт к существующей БД** - -```bash -# ❌ НЕПРАВИЛЬНО - SQL скрипты выполняются только при ПЕРВОМ создании БД -docker compose restart postgres - -# ✅ ПРАВИЛЬНО - Применить вручную -docker compose exec -T postgres psql -U mc_db_user -d mc_db < 004-add-os-field.sql - -# ИЛИ удалить volume и пересоздать БД (⚠️ ПОТЕРЯ ДАННЫХ!) -docker compose down -v postgres -docker compose up -d postgres -``` - ---- - -## 💡 Лучшие практики - -### **1. После изменения .env - всегда recreate:** -```bash -nano .env -docker compose up -d --force-recreate -``` - -### **2. После git pull - проверь что изменилось:** -```bash -git pull -git diff HEAD~1 docker-compose.yml -git diff HEAD~1 .env - -# Если изменился docker-compose.yml или .env: -docker compose up -d --force-recreate - -# Если изменился Dockerfile или requirements.txt: -docker compose up -d --build -``` - -### **3. Проверь что переменные загрузились:** -```bash -docker compose up -d --force-recreate remote_access_api -docker compose exec remote_access_api printenv | grep POSTGRES -``` - -### **4. Используй docker compose logs для отладки:** -```bash -docker compose logs -f remote_access_api -``` - ---- - -## 🎯 Золотое правило - -> **Если сомневаешься - используй `up -d --force-recreate`** -> -> Это безопасно и гарантирует применение всех изменений в конфигурации. -> -> ```bash -> docker compose up -d --force-recreate service_name -> ``` - ---- - -## 📚 Команды для копирования - -```bash -# Самые частые случаи: - -# Изменил .env -docker compose up -d --force-recreate - -# Изменил код (с volume) - FastAPI с auto-reload -# Ничего не делай - перезагрузится сам - -# Изменил Dockerfile или requirements.txt -docker compose up -d --build - -# Изменил nginx config -docker compose restart nginx - -# Изменил docker-compose.yml структуру -docker compose up -d --force-recreate - -# Проверить переменные в контейнере -docker compose exec service_name printenv - -# Проверить что docker compose "видит" -docker compose config | grep VARIABLE_NAME - -# Посмотреть логи -docker compose logs -f service_name -``` - ---- - -## 🆘 Troubleshooting - -### Проблема: Изменения не применяются даже после recreate - -**Причина:** Docker кеширует образы. - -**Решение:** -```bash -# Принудительно пересобрать без кеша -docker compose build --no-cache service_name -docker compose up -d --force-recreate service_name -``` - ---- - -### Проблема: Не уверен что контейнер использует новую конфигурацию - -**Решение:** -```bash -# Удалить и создать заново -docker compose down service_name -docker compose up -d service_name -``` - ---- - -## 📖 Связанные документы - -- `docker-compose.yml` - основная конфигурация -- `.env` / `production.env` - переменные окружения -- `Действительноважно.md` - критичные настройки - diff --git a/guacamole_test_11_26/docs/DOCUMENTATION_INDEX.md b/guacamole_test_11_26/docs/DOCUMENTATION_INDEX.md deleted file mode 100755 index 2efa5a1d..00000000 --- a/guacamole_test_11_26/docs/DOCUMENTATION_INDEX.md +++ /dev/null @@ -1,327 +0,0 @@ -# 📚 Documentation Index - -## 🎯 Quick Navigation - -**Выберите документ в зависимости от вашей задачи:** - ---- - -## 🚀 Для быстрого старта - -### 📖 [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) -**3 минуты** -✅ Быстрый checklist для деплоя -✅ Обязательные переменные в .env -✅ Что произойдет если не установить пароли - -**Используйте когда:** -- 🎯 Нужно быстро задеплоить проект -- 🎯 Проверить что всё настроено правильно -- 🎯 Убедиться что нет дефолтных паролей - ---- - -### 📖 [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) -**2 минуты** -✅ Краткая сводка совместимости -✅ Key metrics (35 endpoints, 0 issues) -✅ Quick FAQ - -**Используйте когда:** -- 🎯 Нужен быстрый ответ "всё ли совместимо?" -- 🎯 Проверить безопасность перед деплоем -- 🎯 Показать summary менеджеру - ---- - -## 🔐 Для аудита безопасности - -### 📖 [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) -**15 минут** -✅ Полный audit report -✅ Все 35 endpoints проанализированы -✅ Security findings и recommendations -✅ Test scenarios - -**Используйте когда:** -- 🎯 Нужен полный audit report для security team -- 🎯 Проверить все endpoints на совместимость -- 🎯 Документировать security improvements -- 🎯 Подготовить production deployment approval - ---- - -### 📖 [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) -**30 минут** -✅ Детальный анализ каждого endpoint -✅ Code snippets для каждого случая -✅ Security analysis -✅ Compatibility matrix - -**Используйте когда:** -- 🎯 Нужна детальная информация по конкретному endpoint -- 🎯 Code review -- 🎯 Debugging authentication issues -- 🎯 Понять как работает каждый endpoint - ---- - -### 📖 [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) -**10 минут** -✅ Что было исправлено -✅ Где были hardcoded passwords -✅ Как теперь хранятся credentials -✅ Before/After comparison - -**Используйте когда:** -- 🎯 Понять какие security issues были -- 🎯 Документировать исправления -- 🎯 Показать security improvements -- 🎯 Audit trail для compliance - ---- - -## 🔄 Для понимания архитектуры - -### 📖 [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) -**20 минут** -✅ Визуальные диаграммы потоков -✅ Startup sequence -✅ User login flow -✅ Connection creation flow -✅ Cleanup operations -✅ Token types comparison - -**Используйте когда:** -- 🎯 Нужно понять как работает authentication -- 🎯 Debugging auth issues -- 🎯 Onboarding нового разработчика -- 🎯 Объяснить архитектуру stakeholder'ам - ---- - -## 🛠️ Для деплоя и настройки - -### 📖 [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) -**5 минут** -✅ Как использовать deploy.sh / deploy.ps1 -✅ Что проверяется автоматически -✅ Troubleshooting - -**Используйте когда:** -- 🎯 Первый раз запускаете deploy script -- 🎯 Автоматизация деплоя -- 🎯 CI/CD pipeline setup - ---- - -### 📖 [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) -**10 минут** -✅ Как создать кастомного Guacamole admin -✅ Password hashing механизм -✅ Использование generate_guacamole_user.py -✅ Manual vs automated process - -**Используйте когда:** -- 🎯 Нужно создать кастомного admin пользователя -- 🎯 Изменить username/password админа -- 🎯 Понять как работает Guacamole authentication -- 🎯 Troubleshooting login issues - ---- - -### 📖 [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) -**3 минуты** -✅ Краткие шаги для создания custom admin -✅ One-liner commands - -**Используйте когда:** -- 🎯 Быстро создать custom admin -- 🎯 Нужен quick reference -- 🎯 Copy-paste команды - ---- - -## 📊 По типу задачи - -### 🎯 **Я первый раз деплою проект** -1. Читайте: [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) ⭐ -2. Затем: [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) -3. И: [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) - -### 🎯 **Мне нужен security audit** -1. Читайте: [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) ⭐ -2. Затем: [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) -3. И: [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) - -### 🎯 **Мне нужно понять архитектуру** -1. Читайте: [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) ⭐ -2. Затем: [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - -### 🎯 **У меня проблема с authentication** -1. Читайте: [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) -2. Затем: [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) -3. И: [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - -### 🎯 **Мне нужно создать custom admin** -1. Читайте: [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) ⭐ -2. Или детально: [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) - -### 🎯 **Я хочу проверить совместимость** -1. Читайте: [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) ⭐ -2. Или детально: [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - ---- - -## 📂 Полный список документов - -| Документ | Размер | Сложность | Время чтения | -|----------|--------|-----------|--------------| -| [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) | Средний | 🟢 Легко | 3 мин | -| [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) | Малый | 🟢 Легко | 2 мин | -| [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) | Большой | 🟡 Средне | 15 мин | -| [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) | Очень большой | 🔴 Детально | 30 мин | -| [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) | Большой | 🟡 Средне | 20 мин | -| [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) | Средний | 🟢 Легко | 10 мин | -| [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) | Малый | 🟢 Легко | 5 мин | -| [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) | Средний | 🟡 Средне | 10 мин | -| [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) | Малый | 🟢 Легко | 3 мин | - ---- - -## 🗂️ Категории документов - -### **📘 Security & Audit** -- ✅ [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) - Полный audit report -- ✅ [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - Детальный endpoint анализ -- ✅ [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) - Security improvements -- ✅ [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) - Совместимость - -### **📗 Architecture & Design** -- ✅ [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) - Auth flows и диаграммы - -### **📙 Deployment & Setup** -- ✅ [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) - Quick checklist -- ✅ [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) - Automated deployment -- ✅ [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) - Custom users -- ✅ [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) - Quick start - ---- - -## 🔍 Поиск по ключевым словам - -### **Если ищете информацию про:** - -**"Hardcoded passwords"** → [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) - -**"Custom admin username"** → [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) - -**"Deploy script"** → [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) - -**"Endpoint compatibility"** → [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - -**"Environment variables"** → [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) - -**"Authentication flow"** → [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) - -**"Security audit"** → [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) - -**"Quick start"** → [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) - -**"Token types"** → [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) - -**"Cleanup operations"** → [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - -**"RBAC"** → [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - -**"Password hashing"** → [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) - ---- - -## 📊 Статус документации - -| Категория | Документов | Статус | -|-----------|-----------|--------| -| Security & Audit | 4 | ✅ Complete | -| Architecture | 1 | ✅ Complete | -| Deployment | 4 | ✅ Complete | -| **TOTAL** | **9** | ✅ **100% Complete** | - ---- - -## 🎓 Рекомендованный порядок чтения - -### **Для новичков:** -1. [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) - Базовое понимание -2. [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) - Что работает -3. [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) - Как всё работает -4. [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) - Запуск проекта - -### **Для разработчиков:** -1. [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) - Архитектура -2. [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - Детали endpoints -3. [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) - User management -4. [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) - Security history - -### **Для security team:** -1. [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) - Audit report -2. [ENDPOINT_AUDIT_REPORT.md](./ENDPOINT_AUDIT_REPORT.md) - Детальный анализ -3. [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) - Исправления -4. [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) - Summary - -### **Для DevOps:** -1. [AUTO_DEPLOY_GUIDE.md](./AUTO_DEPLOY_GUIDE.md) - Deployment automation -2. [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) - Checklist -3. [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) - Quick commands -4. [CUSTOM_GUACAMOLE_USER.md](./CUSTOM_GUACAMOLE_USER.md) - User creation - ---- - -## ✅ Quick Answers - -### **Q: Все ли эндпоинты совместимы с custom credentials?** -A: ✅ ДА, 100%. См. [COMPATIBILITY_SUMMARY.md](./COMPATIBILITY_SUMMARY.md) - -### **Q: Есть ли hardcoded пароли?** -A: ❌ НЕТ, все убраны. См. [HARDCODED_PASSWORDS_FIX.md](./HARDCODED_PASSWORDS_FIX.md) - -### **Q: Как быстро задеплоить?** -A: См. [DEPLOYMENT_CHECKLIST.md](./DEPLOYMENT_CHECKLIST.md) (3 минуты) - -### **Q: Как создать custom admin?** -A: См. [QUICK_START_CUSTOM_ADMIN.md](./QUICK_START_CUSTOM_ADMIN.md) (3 минуты) - -### **Q: Как работает authentication?** -A: См. [AUTHENTICATION_FLOW.md](./AUTHENTICATION_FLOW.md) (визуальные диаграммы) - -### **Q: Где полный audit report?** -A: См. [FINAL_AUDIT_SUMMARY.md](./FINAL_AUDIT_SUMMARY.md) - ---- - -## 📞 Support - -**Если после прочтения документации у вас остались вопросы:** - -1. 🔍 Используйте Ctrl+F для поиска по документу -2. 📚 Проверьте индекс выше -3. 🎯 Выберите документ по категории -4. 📖 Прочитайте рекомендованные документы для вашей роли - ---- - -## 🔄 Обновления - -**Last Updated:** 2025-10-29 -**Version:** 1.0 -**Status:** ✅ Complete - -**Changelog:** -- 2025-10-29: Создана вся документация (9 документов) -- 2025-10-29: Audit completed (35 endpoints) -- 2025-10-29: Security improvements documented - ---- - -**Happy Reading! 📚✨** - diff --git a/guacamole_test_11_26/docs/ENDPOINT_AUDIT_REPORT.md b/guacamole_test_11_26/docs/ENDPOINT_AUDIT_REPORT.md deleted file mode 100755 index 357afd0f..00000000 --- a/guacamole_test_11_26/docs/ENDPOINT_AUDIT_REPORT.md +++ /dev/null @@ -1,510 +0,0 @@ -# 🔍 Audit Report: Endpoint Compatibility with New Authentication Logic - -**Date:** 2025-10-29 -**Scope:** All API endpoints compatibility with custom username/password authentication -**Status:** ✅ **FULLY COMPATIBLE** - ---- - -## 📊 Executive Summary - -**Total Endpoints Audited:** 35 -**Critical Issues Found:** 0 -**Security Improvements:** ✅ All hardcoded credentials removed -**Compatibility Status:** ✅ 100% compatible with custom SYSTEM_ADMIN_USERNAME/PASSWORD - ---- - -## 🎯 Key Findings - -### ✅ **1. No Hardcoded Credentials** - -**Checked Files:** -- ✅ `api/main.py` - **0 hardcoded credentials** -- ✅ `api/auth/guacamole_auth.py` - **Strict environment variable enforcement** -- ✅ `api/auth/redis_storage.py` - **No fallback passwords** -- ✅ `api/auth/ecdh_session.py` - **No fallback passwords** -- ✅ `api/auth/csrf_protection.py` - **No fallback passwords** -- ✅ `api/auth/saved_machines_db.py` - **No fallback passwords** -- ✅ `api/auth/session_storage.py` - **No fallback passwords** -- ✅ `api/auth/token_blacklist.py` - **No fallback passwords** -- ✅ `api/auth/rate_limiter.py` - **No fallback passwords** - -**Grep Results:** -```bash -# Search for hardcoded credentials -grep -r "guacadmin" api/main.py -# Result: No matches found ✅ - -# Search for SYSTEM_ADMIN references -grep -r "SYSTEM_ADMIN" api/main.py -# Result: No matches found ✅ -``` - -**Conclusion:** ✅ All credentials are loaded from environment variables without fallback values. - ---- - -### ✅ **2. System Token Management** - -**Location:** `api/auth/guacamole_auth.py:42-60` - -```python -def get_system_token(self) -> str: - """ - Получение токена системного пользователя для служебных операций - - ✅ КРИТИЧНО: Использует self._system_username и self._system_password - которые берутся ТОЛЬКО из environment variables - - Raises: - Exception: Если не удалось аутентифицировать системного пользователя - """ - # Проверяем, нужно ли обновить токен - if (self._system_token is None or - self._system_token_expires is None or - self._system_token_expires <= datetime.now()): - - # ✅ Аутентификация через ENVIRONMENT VARIABLES - self._system_token = self._authenticate_guacamole_user( - self._system_username, # ← From os.getenv("SYSTEM_ADMIN_USERNAME") - self._system_password # ← From os.getenv("SYSTEM_ADMIN_PASSWORD") - ) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Works with any custom username (not just "guacadmin") -- Requires environment variables to be set -- Raises `ValueError` if credentials missing - ---- - -### ✅ **3. Cleanup Operations** - -#### **3.1. Cleanup Expired Connections** - -**Location:** `api/main.py:1246-1300` - -```python -async def cleanup_expired_connections_once(log_action: str = "expired"): - """ - ✅ БЕЗОПАСНО: Использует user token из Redis для удаления - НЕ использует системные credentials напрямую - """ - for conn_id in expired_connections: - conn_data = redis_connection_storage.get_connection(conn_id) - if conn_data: - # ✅ Использует auth_token пользователя (из Redis) - guacamole_client.delete_connection_with_user_token( - conn_id, - conn_data['auth_token'] # ← User's Guacamole token - ) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Uses user tokens (not system token) -- No dependency on system credentials - ---- - -#### **3.2. Cleanup Orphaned Connections** - -**Location:** `api/main.py:1187-1244` - -```python -async def cleanup_orphaned_guacamole_connections(): - """ - ✅ БЕЗОПАСНО: Использует системный токен для cleanup - Системный токен получается через guacamole_authenticator - который использует environment variables - """ - # ✅ Получает системный токен (из environment variables) - guac_connections = guacamole_client.get_all_connections_with_system_token() - - for conn in guac_connections: - # ✅ Удаляет через системный токен (из environment variables) - guacamole_client.delete_connection_with_system_token(conn_id) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Uses system token from environment variables -- Works with custom SYSTEM_ADMIN_USERNAME - ---- - -## 📋 Endpoint-by-Endpoint Analysis - -### **Public Endpoints (No Auth)** - -| Endpoint | Method | Credentials Used | Compatible | -|----------|--------|------------------|------------| -| `/` | GET | None | ✅ Yes | -| `/docs` | GET | None | ✅ Yes | -| `/health` | GET | None | ✅ Yes | -| `/health/detailed` | GET | None | ✅ Yes | -| `/health/ready` | GET | None | ✅ Yes | -| `/health/routing` | GET | None | ✅ Yes | -| `/metrics` | GET | None | ✅ Yes | -| `/stats` | GET | None | ✅ Yes | - ---- - -### **Authentication Endpoints** - -| Endpoint | Method | Auth Type | Credentials Used | Compatible | -|----------|--------|-----------|------------------|------------| -| `/auth/login` | POST | None (Login) | **User provided** | ✅ Yes | -| `/auth/login-ecdh` | POST | None (Login) | **User provided** | ✅ Yes | -| `/auth/profile` | GET | JWT | **From JWT** | ✅ Yes | -| `/auth/permissions` | GET | JWT | **From JWT** | ✅ Yes | -| `/auth/logout` | POST | JWT | **From JWT** | ✅ Yes | -| `/auth/limits` | GET | JWT | **From JWT** | ✅ Yes | -| `/auth/public-key` | GET | None | None | ✅ Yes | -| `/auth/signing-public-key` | GET | None | None | ✅ Yes | -| `/auth/key-exchange` | POST | None | None | ✅ Yes | -| `/auth/refresh-ecdh` | POST | JWT | **From JWT** | ✅ Yes | -| `/auth/csrf-token` | GET | None | None | ✅ Yes | -| `/auth/revoke` | POST | JWT | **From JWT** | ✅ Yes | - -**Details:** - -#### `/auth/login` (Line 1792) -```python -@app.post("/auth/login", response_model=LoginResponse) -async def login(login_request: LoginRequest, request: Request): - # ✅ Использует credentials из login_request (user provided) - user_info = guacamole_authenticator.authenticate_user( - login_request.username, # ← User provided - login_request.password # ← User provided - ) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Uses user-provided credentials -- No dependency on system credentials -- Works with any Guacamole user (including custom admin username) - ---- - -### **Connection Management Endpoints** - -| Endpoint | Method | Auth Type | Credentials Used | Compatible | -|----------|--------|-----------|------------------|------------| -| `/connect` | POST | JWT | **User's Guacamole token** | ✅ Yes | -| `/connections` | GET | JWT | **User's Guacamole token** | ✅ Yes | -| `/connections/{id}` | DELETE | JWT | **User's Guacamole token** | ✅ Yes | -| `/machines/check-availability` | POST | JWT | **System credentials** | ✅ Yes | - -**Details:** - -#### `/connect` (Line 2593) -```python -@app.post("/connect", response_model=ConnectionResponse) -async def create_remote_connection( - connection_request: ConnectionRequest, - request: Request, - credentials: HTTPAuthorizationCredentials = Depends(security) -): - # ✅ Использует user info из JWT middleware - user_info = get_current_user(request) - guacamole_token = get_current_user_token(request) - - # ✅ Создает подключение с user's Guacamole token - connection = guacamole_client.create_connection_with_user_token( - connection_request, - guacamole_token # ← User's token from ECDH session - ) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Uses user's Guacamole token (from ECDH session) -- No dependency on system credentials - ---- - -#### `/connections/{id}` DELETE (Line 2983) -```python -@app.delete("/connections/{connection_id}") -async def delete_connection( - connection_id: str, - request: Request, - credentials: HTTPAuthorizationCredentials = Depends(security) -): - # ✅ Получает connection data из Redis - conn_data = redis_connection_storage.get_connection(connection_id) - - # ✅ Удаляет с user token из Redis - guacamole_client.delete_connection_with_user_token( - connection_id, - conn_data['auth_token'] # ← User's Guacamole token from Redis - ) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Uses user token stored in Redis -- Checks ownership via `PermissionChecker.check_connection_ownership` - ---- - -#### `/machines/check-availability` (Line 2515) -```python -@app.post("/machines/check-availability") -async def check_machine_availability( - request: MachineAvailabilityRequest, - auth_request: Request, - credentials: HTTPAuthorizationCredentials = Depends(security) -): - # ✅ Использует только user info для authorization - user_info = get_current_user(auth_request) - - # ✅ НЕ использует credentials для ping - # Просто делает TCP connect на hostname:port - sock = socket.create_connection((hostname, port), timeout=timeout) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Only uses JWT for authorization -- No Guacamole credentials used - ---- - -### **Saved Machines Endpoints** - -| Endpoint | Method | Auth Type | Credentials Used | Compatible | -|----------|--------|-----------|------------------|------------| -| `/api/machines/saved` | GET | JWT | **User from JWT** | ✅ Yes | -| `/api/machines/saved` | POST | JWT | **User from JWT** | ✅ Yes | -| `/api/machines/saved/{id}` | GET | JWT | **User from JWT** | ✅ Yes | -| `/api/machines/saved/{id}` | PUT | JWT | **User from JWT** | ✅ Yes | -| `/api/machines/saved/{id}` | DELETE | JWT | **User from JWT** | ✅ Yes | -| `/api/machines/saved/{id}/connect` | POST | JWT | **User's Guacamole token** | ✅ Yes | - -**Details:** - -#### `/api/machines/saved` GET (Line 3084) -```python -@app.get("/api/machines/saved", response_model=SavedMachineList) -async def get_saved_machines( - request: Request, - include_stats: bool = False, - credentials: HTTPAuthorizationCredentials = Depends(security) -): - # ✅ Использует user info из JWT - user_info = get_current_user(request) - user_id = user_info["username"] # ← User from JWT, NOT system admin - - # ✅ Получает машины для конкретного пользователя - machines = saved_machines_db.get_user_machines(user_id, include_stats) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Uses username from JWT -- No dependency on system credentials - ---- - -#### `/api/machines/saved` POST (Line 3142) -```python -@app.post("/api/machines/saved", response_model=SavedMachineResponse) -async def create_saved_machine( - machine: SavedMachineCreate, - request: Request, - credentials: HTTPAuthorizationCredentials = Depends(security) -): - # ✅ Использует user info из JWT - user_info = get_current_user(request) - user_id = user_info["username"] # ← User from JWT - - # ✅ Создает машину для конкретного пользователя - created_machine = saved_machines_db.create_machine( - user_id=user_id, # ← User-specific, NOT system admin - name=machine.name, - # ... - ) -``` - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- Creates machine for specific user -- No dependency on system credentials - ---- - -### **Configuration & Management Endpoints** - -| Endpoint | Method | Auth Type | Credentials Used | Compatible | -|----------|--------|-----------|------------------|------------| -| `/logs/config` | GET | JWT | **User from JWT** | ✅ Yes | -| `/logs/config` | POST | JWT | **User from JWT** | ✅ Yes | -| `/stats/reset` | GET | JWT | **User from JWT** | ✅ Yes | -| `/rate-limit/status` | GET | JWT | **User from JWT** | ✅ Yes | -| `/security/certificate-pins` | GET | None | None | ✅ Yes | - -**Compatibility:** ✅ **ALL COMPATIBLE** -- All use JWT for authorization -- No system credentials required - ---- - -## 🔐 Security Analysis - -### **1. Credential Storage Audit** - -**Checked:** All files that access credentials - -| File | Credential Type | Storage Method | Fallback? | Secure? | -|------|----------------|----------------|-----------|---------| -| `guacamole_auth.py` | System Admin | `os.getenv()` | ❌ No | ✅ Yes | -| `redis_storage.py` | Redis Password | `os.getenv()` | ❌ No | ✅ Yes | -| `saved_machines_db.py` | Postgres Password | `os.getenv()` | ❌ No | ✅ Yes | -| `csrf_protection.py` | Redis Password | `os.getenv()` | ❌ No | ✅ Yes | -| `ecdh_session.py` | Redis Password | `os.getenv()` | ❌ No | ✅ Yes | -| `token_blacklist.py` | Redis Password | `os.getenv()` | ❌ No | ✅ Yes | -| `session_storage.py` | Redis Password | `os.getenv()` | ❌ No | ✅ Yes | -| `rate_limiter.py` | Redis Password | `os.getenv()` | ❌ No | ✅ Yes | -| `encryption.py` | Encryption Key | `os.getenv()` | ❌ No | ✅ Yes | - -**Result:** ✅ **NO FALLBACK VALUES** - All credentials MUST be provided via environment variables - ---- - -### **2. System Admin Usage Analysis** - -**Where is SYSTEM_ADMIN_USERNAME/PASSWORD used?** - -1. ✅ **Startup Cleanup** (`api/main.py:1187-1244`) - - Purpose: Delete orphaned Guacamole connections - - Method: `get_all_connections_with_system_token()` - - Usage: Read-only (listing connections) + Delete (cleanup) - - Impact: **Low** - Only runs at startup - -2. ✅ **Periodic Cleanup** (Background task, disabled by default) - - Purpose: Delete expired connections - - Method: Uses **user tokens from Redis** (NOT system token) - - Impact: **None** - Doesn't use system credentials - -3. ✅ **Connection Deletion** (`api/main.py:2983-3077`) - - Purpose: User-initiated connection deletion - - Method: Uses **user token from Redis** (NOT system token) - - Impact: **None** - Doesn't use system credentials - -**Conclusion:** ✅ System admin credentials are ONLY used for: -- Startup cleanup (low-privilege operations) -- Never used for user-facing operations -- Never hardcoded or exposed - ---- - -### **3. Role-Based Access Control (RBAC)** - -**Tested Roles:** -- ✅ **GUEST** - View-only, cannot create connections -- ✅ **USER** - Can create and manage own connections -- ✅ **ADMIN** - Can manage all connections -- ✅ **System Admin** - Internal service account (from environment variables) - -**Permission Checks:** - -| Endpoint | GUEST | USER | ADMIN | System Admin | -|----------|-------|------|-------|--------------| -| `/auth/login` | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | -| `/connect` | ❌ No | ✅ Yes | ✅ Yes | N/A | -| `/connections` (GET) | ✅ Yes (own) | ✅ Yes (own) | ✅ Yes (all) | N/A | -| `/connections/{id}` (DELETE) | ❌ No | ✅ Yes (own) | ✅ Yes (all) | N/A | -| `/api/machines/saved` (GET) | ✅ Yes (own) | ✅ Yes (own) | ✅ Yes (own) | N/A | -| `/api/machines/saved` (POST) | ❌ No | ✅ Yes | ✅ Yes | N/A | - -**Compatibility:** ✅ **FULLY COMPATIBLE** -- All roles work correctly with custom admin username -- System admin is separate from user-facing roles - ---- - -## 🧪 Testing Recommendations - -### **1. Integration Tests** - -```python -# Test with custom SYSTEM_ADMIN_USERNAME -def test_cleanup_with_custom_admin(): - os.environ["SYSTEM_ADMIN_USERNAME"] = "custom_admin" - os.environ["SYSTEM_ADMIN_PASSWORD"] = "SecurePass123!" - - # Start API - # Verify cleanup works - # Verify connections are deleted -``` - -### **2. Environment Variable Tests** - -```python -# Test missing credentials -def test_missing_system_admin_credentials(): - # Remove SYSTEM_ADMIN_PASSWORD - del os.environ["SYSTEM_ADMIN_PASSWORD"] - - # Try to start API - # Should raise ValueError - with pytest.raises(ValueError, match="SYSTEM_ADMIN_PASSWORD.*required"): - GuacamoleAuthenticator() -``` - -### **3. Username Change Tests** - -```bash -# Test changing admin username after deployment -1. Update .env: SYSTEM_ADMIN_USERNAME=new_admin -2. Generate new SQL: python generate_guacamole_user.py --username new_admin --password SecurePass123! --admin -3. Apply SQL to Guacamole database -4. Restart API -5. Verify cleanup still works -``` - ---- - -## 📊 Compatibility Matrix - -| Component | Hardcoded Credentials | Custom Username Support | Environment Variable Required | Status | -|-----------|----------------------|------------------------|-------------------------------|--------| -| `main.py` | ❌ None | ✅ Yes | ✅ Yes | ✅ Compatible | -| `guacamole_auth.py` | ❌ None | ✅ Yes | ✅ Yes | ✅ Compatible | -| `redis_storage.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `saved_machines_db.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `ecdh_session.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `csrf_protection.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `session_storage.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `token_blacklist.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `rate_limiter.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | -| `encryption.py` | ❌ None | N/A | ✅ Yes | ✅ Compatible | - ---- - -## ✅ Final Verdict - -### **Overall Compatibility: 100% ✅** - -**Summary:** -1. ✅ **No hardcoded credentials** - All removed -2. ✅ **Custom username support** - Works with any admin username -3. ✅ **Environment variable enforcement** - All credentials MUST be in .env -4. ✅ **All endpoints compatible** - 35/35 endpoints work correctly -5. ✅ **RBAC fully functional** - All roles work with custom credentials -6. ✅ **Security enhanced** - No fallback passwords - -**Ready for Production:** ✅ **YES** - ---- - -## 📚 Related Documentation - -- `DEPLOYMENT_CHECKLIST.md` - Quick deployment guide -- `HARDCODED_PASSWORDS_FIX.md` - Security improvements -- `AUTO_DEPLOY_GUIDE.md` - Automated deployment -- `CUSTOM_GUACAMOLE_USER.md` - Creating custom Guacamole users - ---- - -**Audited by:** AI Assistant -**Date:** 2025-10-29 -**Version:** 1.0 -**Status:** ✅ APPROVED FOR PRODUCTION - diff --git a/guacamole_test_11_26/docs/FINAL_AUDIT_SUMMARY.md b/guacamole_test_11_26/docs/FINAL_AUDIT_SUMMARY.md deleted file mode 100755 index a54759e0..00000000 --- a/guacamole_test_11_26/docs/FINAL_AUDIT_SUMMARY.md +++ /dev/null @@ -1,548 +0,0 @@ -# ✅ Final Audit Summary: Custom Authentication Compatibility - -**Date:** 2025-10-29 -**Auditor:** AI Assistant -**Scope:** Complete system audit for custom SYSTEM_ADMIN_USERNAME/PASSWORD compatibility -**Status:** ✅ **APPROVED FOR PRODUCTION** - ---- - -## 🎯 Executive Summary - -### **Вопрос:** -> "Все ли эндпоинты и их функционал совместимы с новой логикой по учетным записям (УЗ)?" - -### **Ответ:** -> ✅ **ДА, 100% совместимы!** Все 35 эндпоинтов работают корректно с кастомными учетными записями. - ---- - -## 📊 Audit Results - -| Category | Checked | Issues Found | Status | -|----------|---------|--------------|--------| -| **Endpoints** | 35 | 0 | ✅ Pass | -| **Python Files** | 10 | 0 | ✅ Pass | -| **Hardcoded Credentials** | All | 0 | ✅ Pass | -| **Fallback Passwords** | All | 0 | ✅ Pass | -| **Environment Variables** | 9 critical | All enforced | ✅ Pass | -| **Security Tests** | 15 scenarios | All passed | ✅ Pass | - ---- - -## 🔍 What Was Audited - -### **1. Code Analysis** - -#### **Checked Files:** -``` -✅ api/main.py - 35 endpoints, 3556 lines -✅ api/auth/guacamole_auth.py - System authentication -✅ api/auth/redis_storage.py - Redis connections -✅ api/auth/ecdh_session.py - ECDH sessions -✅ api/auth/csrf_protection.py - CSRF tokens -✅ api/auth/saved_machines_db.py - Database connections -✅ api/auth/session_storage.py - Session storage -✅ api/auth/token_blacklist.py - Token management -✅ api/auth/rate_limiter.py - Rate limiting -✅ api/auth/encryption.py - Password encryption -``` - -#### **Search Queries:** -```bash -# 1. Hardcoded usernames -grep -r "guacadmin" api/ -Result: 0 matches ✅ - -# 2. Hardcoded passwords -grep -r "redis_pass\|guacamole_pass" api/ -Result: 0 matches ✅ - -# 3. System admin references in main.py -grep "SYSTEM_ADMIN\|guacadmin" api/main.py -Result: 0 matches ✅ - -# 4. Environment variable usage -grep -r "os.getenv.*PASSWORD" api/ -Result: All without fallback values ✅ -``` - ---- - -### **2. Endpoint Analysis** - -#### **Public Endpoints (8):** -| Endpoint | Auth | System Creds | Compatible | -|----------|------|--------------|------------| -| `/` | None | ❌ No | ✅ Yes | -| `/docs` | None | ❌ No | ✅ Yes | -| `/health` | None | ❌ No | ✅ Yes | -| `/health/detailed` | None | ❌ No | ✅ Yes | -| `/health/ready` | None | ❌ No | ✅ Yes | -| `/health/routing` | None | ❌ No | ✅ Yes | -| `/metrics` | None | ❌ No | ✅ Yes | -| `/stats` | None | ❌ No | ✅ Yes | - -**Result:** ✅ No system credentials used - ---- - -#### **Authentication Endpoints (11):** -| Endpoint | Auth Type | Credentials Source | Compatible | -|----------|-----------|-------------------|------------| -| `/auth/login` | User creds | Request body | ✅ Yes | -| `/auth/login-ecdh` | User creds | Request body | ✅ Yes | -| `/auth/profile` | JWT | From JWT | ✅ Yes | -| `/auth/permissions` | JWT | From JWT | ✅ Yes | -| `/auth/logout` | JWT | From JWT | ✅ Yes | -| `/auth/limits` | JWT | From JWT | ✅ Yes | -| `/auth/public-key` | None | N/A | ✅ Yes | -| `/auth/signing-public-key` | None | N/A | ✅ Yes | -| `/auth/key-exchange` | None | N/A | ✅ Yes | -| `/auth/refresh-ecdh` | JWT | From JWT | ✅ Yes | -| `/auth/csrf-token` | None | N/A | ✅ Yes | - -**Key Finding:** -```python -# /auth/login (line 1792) -user_info = guacamole_authenticator.authenticate_user( - login_request.username, # ← User provided ✅ - login_request.password # ← User provided ✅ -) -# ❌ NOT using system credentials -``` - -**Result:** ✅ All use user-provided or JWT credentials - ---- - -#### **Connection Endpoints (4):** -| Endpoint | Auth | Token Type | System Creds | Compatible | -|----------|------|------------|--------------|------------| -| `/connect` | JWT | User's Guacamole | ❌ No | ✅ Yes | -| `/connections` | JWT | User's Guacamole | ❌ No | ✅ Yes | -| `/connections/{id}` | JWT | User's Guacamole | ❌ No | ✅ Yes | -| `/machines/check-availability` | JWT | N/A | ❌ No | ✅ Yes | - -**Key Finding:** -```python -# /connect (line 2593) -user_info = get_current_user(request) -guacamole_token = get_current_user_token(request) -# ↑ User's token from ECDH session (NOT system token) ✅ - -connection = guacamole_client.create_connection_with_user_token( - connection_request, - guacamole_token # ← User's token ✅ -) -``` - -**Result:** ✅ All use user's Guacamole token from ECDH session - ---- - -#### **Saved Machines Endpoints (6):** -| Endpoint | Auth | User Isolation | System Creds | Compatible | -|----------|------|----------------|--------------|------------| -| `GET /api/machines/saved` | JWT | By user_id | ❌ No | ✅ Yes | -| `POST /api/machines/saved` | JWT | By user_id | ❌ No | ✅ Yes | -| `GET /api/machines/saved/{id}` | JWT | By user_id | ❌ No | ✅ Yes | -| `PUT /api/machines/saved/{id}` | JWT | By user_id | ❌ No | ✅ Yes | -| `DELETE /api/machines/saved/{id}` | JWT | By user_id | ❌ No | ✅ Yes | -| `POST /api/machines/saved/{id}/connect` | JWT | By user_id | ❌ No | ✅ Yes | - -**Key Finding:** -```python -# /api/machines/saved GET (line 3084) -user_info = get_current_user(request) -user_id = user_info["username"] # ← From JWT ✅ - -machines = saved_machines_db.get_user_machines( - user_id, # ← User-specific ✅ - include_stats=include_stats -) -# ❌ NOT using system credentials -``` - -**Result:** ✅ All use user ID from JWT for data isolation - ---- - -#### **Config/Management Endpoints (6):** -| Endpoint | Auth | Purpose | System Creds | Compatible | -|----------|------|---------|--------------|------------| -| `/logs/config` | JWT | Log settings | ❌ No | ✅ Yes | -| `POST /logs/config` | JWT | Update logs | ❌ No | ✅ Yes | -| `/stats/reset` | JWT | Reset stats | ❌ No | ✅ Yes | -| `/rate-limit/status` | JWT | Rate limits | ❌ No | ✅ Yes | -| `/security/certificate-pins` | None | SSL pins | ❌ No | ✅ Yes | -| `/auth/revoke` | JWT | Revoke token | ❌ No | ✅ Yes | - -**Result:** ✅ All use JWT for authorization, no system credentials - ---- - -### **3. Background Operations** - -#### **Startup Cleanup:** -```python -# api/main.py:1187 (cleanup_orphaned_guacamole_connections) -async def cleanup_orphaned_guacamole_connections(): - """ - ✅ ЕДИНСТВЕННОЕ место где используется system token - """ - # Get system token from environment variables - guac_connections = guacamole_client.get_all_connections_with_system_token() - - # Delete orphaned connections - for conn in guac_connections: - guacamole_client.delete_connection_with_system_token(conn_id) -``` - -**System Token Usage:** -```python -# api/auth/guacamole_auth.py:42 -def get_system_token(self) -> str: - # Uses credentials from environment variables - self._system_token = self._authenticate_guacamole_user( - self._system_username, # ← os.getenv("SYSTEM_ADMIN_USERNAME") ✅ - self._system_password # ← os.getenv("SYSTEM_ADMIN_PASSWORD") ✅ - ) -``` - -**Security Check:** -```python -# api/auth/guacamole_auth.py:35 -if not self._system_username or not self._system_password: - raise ValueError( - "SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD " - "environment variables are required." - ) - # ✅ API will NOT START without credentials -``` - -**Result:** ✅ System token only used for startup cleanup, uses environment variables - ---- - -#### **Expired Connections Cleanup:** -```python -# api/main.py:1246 (cleanup_expired_connections_once) -async def cleanup_expired_connections_once(log_action: str = "expired"): - """ - ✅ Использует user tokens (NOT system token) - """ - for conn_id in expired_connections: - conn_data = redis_connection_storage.get_connection(conn_id) - - # Delete using USER's token from Redis - guacamole_client.delete_connection_with_user_token( - conn_id, - conn_data['auth_token'] # ← User's token ✅ - ) -``` - -**Result:** ✅ Uses user tokens stored in Redis, NOT system credentials - ---- - -## 🔐 Security Audit - -### **1. Credential Storage:** - -| File | Credential | Method | Fallback | Secure | -|------|------------|--------|----------|--------| -| `guacamole_auth.py` | SYSTEM_ADMIN | `os.getenv()` | ❌ None | ✅ Yes | -| `redis_storage.py` | REDIS_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `saved_machines_db.py` | POSTGRES_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `ecdh_session.py` | REDIS_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `csrf_protection.py` | REDIS_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `session_storage.py` | REDIS_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `token_blacklist.py` | REDIS_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `rate_limiter.py` | REDIS_PASSWORD | `os.getenv()` | ❌ None | ✅ Yes | -| `encryption.py` | ENCRYPTION_KEY | `os.getenv()` | ❌ None | ✅ Yes | - -**Conclusion:** ✅ **ZERO FALLBACK VALUES** - All credentials MUST be in .env - ---- - -### **2. Deployment Protection:** - -```bash -# deploy.sh (line 87) -check_critical_passwords() { - # Check REDIS_PASSWORD - if [[ -z "$REDIS_PASSWORD" ]] || [[ "$REDIS_PASSWORD" == "redis_pass" ]]; then - echo "[ERROR] REDIS_PASSWORD is not set or using default value!" - exit 1 - fi - - # Check POSTGRES_PASSWORD - if [[ -z "$POSTGRES_PASSWORD" ]] || [[ "$POSTGRES_PASSWORD" == "guacamole_pass" ]]; then - echo "[ERROR] POSTGRES_PASSWORD is not set or using default value!" - exit 1 - fi - - # Check SYSTEM_ADMIN_PASSWORD - if [[ -z "$SYSTEM_ADMIN_PASSWORD" ]]; then - echo "[ERROR] SYSTEM_ADMIN_PASSWORD must be set!" - exit 1 - fi -} -``` - -**Result:** ✅ Deploy script blocks insecure deployments - ---- - -### **3. Runtime Protection:** - -```python -# Startup Check (guacamole_auth.py:35) -if not self._system_username or not self._system_password: - raise ValueError( - "SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD " - "environment variables are required." - ) - # ✅ Python will crash → Container will not start -``` - -**Result:** ✅ API fails to start without credentials - ---- - -## 📋 Test Scenarios - -### **✅ Tested Scenarios:** - -1. ✅ **Custom Admin Login** - ```env - SYSTEM_ADMIN_USERNAME=my_custom_admin - SYSTEM_ADMIN_PASSWORD=SecurePass123! - ``` - - Result: API starts successfully - - Cleanup works correctly - -2. ✅ **Regular User Login** - ```json - { "username": "alice", "password": "user_pass" } - ``` - - Result: Authenticated successfully - - JWT token issued - - Can create connections - -3. ✅ **GUEST Role Access** - ```json - { "username": "guest_user", "password": "guest_pass" } - ``` - - Result: Can view connections - - Cannot create connections (403 Forbidden) - - UI disabled appropriately - -4. ✅ **Connection Creation (USER role)** - - POST `/connect` with JWT - - Result: Connection created using user's Guacamole token - - NOT using system credentials - -5. ✅ **Connection Deletion (USER role)** - - DELETE `/connections/{id}` with JWT - - Result: Connection deleted using user's token - - Ownership checked correctly - -6. ✅ **Saved Machines CRUD** - - All operations use user_id from JWT - - Data isolation works correctly - - No system credentials used - -7. ✅ **Startup Cleanup** - - Uses system token from environment variables - - Deletes orphaned connections - - Does not affect user operations - -8. ✅ **Expired Cleanup** - - Uses user tokens from Redis - - Does NOT use system token - - Works correctly for all users - -9. ✅ **Missing Credentials** - ```bash - # Remove SYSTEM_ADMIN_PASSWORD - unset SYSTEM_ADMIN_PASSWORD - docker compose up -d - ``` - - Result: API fails to start ✅ - - Error: "SYSTEM_ADMIN_PASSWORD required" - -10. ✅ **Default Password Prevention** - ```bash - ./deploy.sh - # With REDIS_PASSWORD=redis_pass - ``` - - Result: Deploy blocked ✅ - - Error: "Default password detected" - ---- - -## 🎯 Key Findings - -### **✅ POSITIVE:** - -1. ✅ **No Hardcoded Credentials** - - Zero hardcoded usernames - - Zero hardcoded passwords - - All credentials from environment variables - -2. ✅ **No Fallback Values** - - API will crash without .env - - Docker Compose will fail - - Deploy script blocks insecure configs - -3. ✅ **Custom Username Support** - - Works with ANY username - - Not limited to "guacadmin" - - System token uses custom credentials - -4. ✅ **User Token Isolation** - - Each user has their own Guacamole token - - Stored in Redis with session - - Never mixed with system token - -5. ✅ **RBAC Functional** - - GUEST, USER, ADMIN roles work correctly - - Permissions enforced properly - - System admin separate from user roles - -6. ✅ **Security Enhanced** - - Three layers of protection: - 1. Deploy script checks - 2. Docker Compose validation - 3. Python runtime checks - ---- - -### **⚠️ RECOMMENDATIONS:** - -1. **Password Rotation:** - ```bash - # Periodically update credentials - # 1. Update .env - # 2. Regenerate Guacamole SQL - # 3. Apply SQL - # 4. Restart containers - ``` - -2. **Monitoring:** - ```bash - # Monitor system token usage - grep "get_system_token" logs/api.log - # Should only see at startup - ``` - -3. **Audit Logs:** - ```bash - # Review who accessed system admin endpoints - # (Should be NONE - system only) - ``` - -4. **Secrets Management:** - ```bash - # Consider using: - # - HashiCorp Vault - # - AWS Secrets Manager - # - Azure Key Vault - # Instead of .env file - ``` - ---- - -## 📊 Compatibility Matrix - -| Feature | Custom Username | Custom Password | Environment Variables | Status | -|---------|----------------|-----------------|----------------------|--------| -| **User Login** | ✅ Any username | ✅ Any password | ✅ Not required | ✅ Compatible | -| **System Cleanup** | ✅ Custom admin | ✅ Custom password | ✅ Required | ✅ Compatible | -| **Connection Management** | ✅ User's token | ✅ User's token | ✅ Not required | ✅ Compatible | -| **Saved Machines** | ✅ User's ID | ✅ User's password | ✅ Not required | ✅ Compatible | -| **RBAC** | ✅ All roles | ✅ All roles | ✅ Required | ✅ Compatible | -| **Deploy Script** | ✅ Validates | ✅ Validates | ✅ Required | ✅ Compatible | - ---- - -## ✅ Final Verdict - -### **Overall Assessment:** - -| Category | Score | Grade | -|----------|-------|-------| -| **Endpoint Compatibility** | 35/35 | A+ | -| **Security** | 100% | A+ | -| **Custom Username Support** | 100% | A+ | -| **Environment Variables** | 100% | A+ | -| **Documentation** | Complete | A+ | - -### **Production Readiness:** - -✅ **APPROVED FOR PRODUCTION** - -**Justification:** -1. ✅ All 35 endpoints fully compatible -2. ✅ Zero hardcoded credentials -3. ✅ Zero fallback passwords -4. ✅ Custom username support verified -5. ✅ Security enhanced with multiple layers -6. ✅ Deploy script validates configuration -7. ✅ Runtime checks prevent insecure startup -8. ✅ Complete documentation provided - ---- - -## 📚 Documentation Created - -| Document | Purpose | Status | -|----------|---------|--------| -| `ENDPOINT_AUDIT_REPORT.md` | Detailed endpoint analysis | ✅ Complete | -| `COMPATIBILITY_SUMMARY.md` | Quick compatibility check | ✅ Complete | -| `AUTHENTICATION_FLOW.md` | Auth flow diagrams | ✅ Complete | -| `DEPLOYMENT_CHECKLIST.md` | Deployment guide | ✅ Complete | -| `HARDCODED_PASSWORDS_FIX.md` | Security improvements | ✅ Complete | -| `AUTO_DEPLOY_GUIDE.md` | Automated deployment | ✅ Complete | -| `CUSTOM_GUACAMOLE_USER.md` | Custom user creation | ✅ Complete | -| `FINAL_AUDIT_SUMMARY.md` | This document | ✅ Complete | - ---- - -## 🚀 Deployment Recommendation - -**Status:** ✅ **READY FOR PRODUCTION DEPLOYMENT** - -**Next Steps:** -1. ✅ Review all documentation -2. ✅ Set environment variables in `.env` -3. ✅ Run `./deploy.sh` (validates configuration) -4. ✅ Verify startup logs -5. ✅ Test with custom admin credentials -6. ✅ Test with regular user credentials -7. ✅ Monitor system for 24-48 hours - -**Confidence Level:** 🟢 **HIGH** (95%+) - ---- - -## 🔗 Quick Links - -- [Endpoint Audit Report](./ENDPOINT_AUDIT_REPORT.md) - Detailed analysis -- [Compatibility Summary](./COMPATIBILITY_SUMMARY.md) - Quick reference -- [Authentication Flow](./AUTHENTICATION_FLOW.md) - Visual diagrams -- [Deployment Checklist](./DEPLOYMENT_CHECKLIST.md) - Deploy guide - ---- - -**Audit Date:** 2025-10-29 -**Auditor:** AI Assistant -**Status:** ✅ **APPROVED** -**Signature:** `[AI Assistant v1.0]` - ---- - -**END OF AUDIT REPORT** - diff --git a/guacamole_test_11_26/docs/HARDCODED_PASSWORDS_FIX.md b/guacamole_test_11_26/docs/HARDCODED_PASSWORDS_FIX.md deleted file mode 100755 index 8b2a71bf..00000000 --- a/guacamole_test_11_26/docs/HARDCODED_PASSWORDS_FIX.md +++ /dev/null @@ -1,298 +0,0 @@ -# 🔒 Исправление захардкоженных паролей - -## ✅ **Что исправлено:** - -### **1. Убраны fallback пароли из кода** - -#### **До (НЕБЕЗОПАСНО):** -```python -# ❌ Если не установлен - использует "redis_pass" -password=os.getenv("REDIS_PASSWORD", "redis_pass") - -# ❌ Если не установлен - использует "guacamole_pass" -'password': os.getenv('POSTGRES_PASSWORD', 'guacamole_pass') -``` - -#### **После (БЕЗОПАСНО):** -```python -# ✅ Если не установлен - приложение упадет (fail-safe) -password=os.getenv("REDIS_PASSWORD") - -# ✅ Если не установлен - приложение упадет (fail-safe) -'password': os.getenv('POSTGRES_PASSWORD') -``` - -**Измененные файлы:** -- `api/auth/redis_storage.py` -- `api/auth/ecdh_session.py` -- `api/auth/csrf_protection.py` -- `api/auth/saved_machines_db.py` - ---- - -### **2. Добавлена проверка в deploy.sh** - -Deploy скрипт **автоматически проверяет** все критичные пароли: - -```bash -[INFO] Checking critical passwords... -[ERROR] REDIS_PASSWORD is not set or using default value! -[ERROR] POSTGRES_PASSWORD is not set or using default value! -[ERROR] -[ERROR] Critical passwords are missing or insecure! -[ERROR] Update the following in production.env: -[ERROR] - REDIS_PASSWORD= -[ERROR] - POSTGRES_PASSWORD= -[ERROR] - SYSTEM_ADMIN_PASSWORD= -``` - -**Деплой НЕ ЗАПУСТИТСЯ** без установленных паролей! - ---- - -### **3. Обновлен production.env** - -```env -# 🔒 КРИТИЧНЫЕ ПАРОЛИ - ОБЯЗАТЕЛЬНО измените перед деплоем! - -# Redis -REDIS_PASSWORD=CHANGE_ME_$(openssl rand -base64 32) - -# PostgreSQL -POSTGRES_PASSWORD=CHANGE_ME_$(openssl rand -base64 32) - -# Guacamole Admin -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=CHANGE_ME_$(openssl rand -base64 32) -``` - ---- - -## 🎯 **Ответы на вопросы:** - -### **Q1: Можно ли менять логин (username) при первом запуске?** - -✅ **ДА!** Полностью поддерживается: - -```env -# production.env -SYSTEM_ADMIN_USERNAME=admin # ⬅️ Любое имя! -SYSTEM_ADMIN_PASSWORD=SecurePass! -``` - -**Deploy скрипт автоматически:** -- Генерирует SQL с вашим username -- Проверяет создание в БД -- API использует эти credentials - ---- - -### **Q2: Есть ли еще захардкоженные пароли?** - -**Были найдены и ИСПРАВЛЕНЫ:** - -1. ✅ `REDIS_PASSWORD` - fallback "redis_pass" удален -2. ✅ `POSTGRES_PASSWORD` - fallback "guacamole_pass" удален -3. ✅ `SYSTEM_ADMIN_PASSWORD` - проверяется при деплое - -**Теперь ВСЕ пароли обязательны!** - ---- - -### **Q3: Отразятся ли изменения на эти участки?** - -✅ **ДА! Полностью отражаются:** - -#### **При деплое:** -```bash -./deploy.sh - -[INFO] Loading environment variables... -[INFO] Checking critical passwords... -[OK] All critical passwords are set -[INFO] Checking admin credentials... -[OK] Custom password detected - generating secure admin SQL -``` - -#### **При запуске контейнеров:** -- Redis использует `$REDIS_PASSWORD` из .env -- PostgreSQL использует `$POSTGRES_PASSWORD` из .env -- API использует все эти пароли из environment - -**Никаких дефолтов не осталось!** - ---- - -## 🚀 **Как использовать:** - -### **Шаг 1: Генерируем пароли** - -```bash -# Генерируем 3 безопасных пароля -echo "REDIS_PASSWORD=$(openssl rand -base64 32)" -echo "POSTGRES_PASSWORD=$(openssl rand -base64 32)" -echo "SYSTEM_ADMIN_PASSWORD=$(openssl rand -base64 32)" -``` - ---- - -### **Шаг 2: Обновляем production.env** - -```bash -cd GuacamoleRemoteAccess -nano production.env -``` - -**Вставляем сгенерированные пароли:** -```env -REDIS_PASSWORD=Xk7N9pQ2vT8mL5wR3jH6yU4aF1sD0eG9 -POSTGRES_PASSWORD=aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2u -SYSTEM_ADMIN_USERNAME=admin # ⬅️ Можно менять! -SYSTEM_ADMIN_PASSWORD=uV3wX4yZ5aB6cD7eF8gH9iJ0kL1mN2o -``` - ---- - -### **Шаг 3: Запускаем deploy** - -```bash -chmod +x deploy.sh -./deploy.sh -``` - -**Скрипт автоматически:** -- ✅ Проверит что все пароли установлены -- ✅ Проверит что пароли не дефолтные -- ✅ Сгенерирует SQL с вашими credentials -- ✅ Запустит контейнеры с безопасными паролями - ---- - -## 🛡️ **Уровни защиты:** - -### **1. Deploy скрипт (предотвращение)** -```bash -# Не даст запустить с небезопасными паролями -[ERROR] REDIS_PASSWORD is not set or using default value! -``` - -### **2. Docker Compose (конфигурация)** -```yaml -# Использует ТОЛЬКО переменные окружения (без fallback) -REDIS_PASSWORD: ${REDIS_PASSWORD} -POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} -``` - -### **3. Python код (runtime)** -```python -# Если пароль не установлен - приложение упадет -password=os.getenv("REDIS_PASSWORD") -# None → Redis connection error → crash -``` - -**Три уровня защиты = невозможно запустить с небезопасными паролями!** - ---- - -## 📊 **Сравнение ДО и ПОСЛЕ:** - -### **❌ ДО (Небезопасно):** -```bash -# Можно запустить вообще без паролей -docker compose up -d -# → Redis: redis_pass -# → PostgreSQL: guacamole_pass -# → Guacamole Admin: guacadmin:guacadmin -# ⚠️ КРИТИЧЕСКАЯ УЯЗВИМОСТЬ! -``` - -### **✅ ПОСЛЕ (Безопасно):** -```bash -# БЕЗ паролей в .env -./deploy.sh -# [ERROR] REDIS_PASSWORD is not set! -# [ERROR] POSTGRES_PASSWORD is not set! -# [ERROR] SYSTEM_ADMIN_PASSWORD must be set! -# Exit 1 - деплой НЕ ЗАПУСТИТСЯ - -# С паролями в .env -./deploy.sh -# [OK] All critical passwords are set -# [OK] Custom password detected -# [OK] Containers started successfully -# ✅ ВСЁ БЕЗОПАСНО! -``` - ---- - -## 🆘 **Troubleshooting:** - -### Проблема: "REDIS_PASSWORD is not set!" - -**Решение:** -```bash -# Добавьте в production.env: -REDIS_PASSWORD=$(openssl rand -base64 32) -``` - ---- - -### Проблема: "Redis connection error" - -**Причина:** Пароль в .env не совпадает с паролем Redis. - -**Решение:** -```bash -# Проверьте что docker-compose.yml использует переменную -grep REDIS_PASSWORD docker-compose.yml - -# Должно быть: -# REDIS_PASSWORD: ${REDIS_PASSWORD} -# БЕЗ :-default_value -``` - ---- - -### Проблема: "PostgreSQL authentication failed" - -**Причина:** Пароль в .env не совпадает с паролем PostgreSQL. - -**Решение:** -```bash -# Если БД уже создана с другим паролем - нужно пересоздать volume -docker compose down -v -# ⚠️ ВНИМАНИЕ: Это удалит все данные! - -# Обновите POSTGRES_PASSWORD в .env -nano production.env - -# Запустите заново -./deploy.sh -``` - ---- - -## ✅ **Checklist:** - -- [ ] Сгенерированы 3 безопасных пароля (minimum 20 символов) -- [ ] `REDIS_PASSWORD` установлен в production.env -- [ ] `POSTGRES_PASSWORD` установлен в production.env -- [ ] `SYSTEM_ADMIN_USERNAME` установлен (можно менять!) -- [ ] `SYSTEM_ADMIN_PASSWORD` установлен в production.env -- [ ] Deploy скрипт запущен и прошел все проверки -- [ ] Контейнеры запустились успешно -- [ ] Логи подтверждают использование паролей из .env -- [ ] Дефолтные пароли НИГДЕ не используются - ---- - -## 📚 **Связанные документы:** - -- `AUTO_DEPLOY_GUIDE.md` - автоматический деплой -- `QUICK_START_CUSTOM_ADMIN.md` - быстрый старт -- `MIGRATION_SECURITY_UPDATE.md` - миграция существующих установок - ---- - -**Теперь система полностью защищена от захардкоженных паролей!** 🔒 - diff --git a/guacamole_test_11_26/docs/MIGRATION_SECURITY_UPDATE.md b/guacamole_test_11_26/docs/MIGRATION_SECURITY_UPDATE.md deleted file mode 100755 index 4bdf7ed5..00000000 --- a/guacamole_test_11_26/docs/MIGRATION_SECURITY_UPDATE.md +++ /dev/null @@ -1,195 +0,0 @@ -# 🔒 Миграция: Обязательные системные credentials - -## ⚠️ Критическое обновление безопасности - -**Начиная с этой версии, API ТРЕБУЕТ явной установки системных credentials.** - -Это изменение **устраняет критическую уязвимость** - захардкоженные дефолтные пароли в коде. - ---- - -## 📋 Что изменилось? - -### **До:** -```python -# ❌ НЕБЕЗОПАСНО: Дефолтные значения в коде -self._system_username = os.getenv("SYSTEM_ADMIN_USERNAME", "guacadmin") -self._system_password = os.getenv("SYSTEM_ADMIN_PASSWORD", "guacadmin") -``` - -### **После:** -```python -# ✅ БЕЗОПАСНО: Обязательные переменные окружения -self._system_username = os.getenv("SYSTEM_ADMIN_USERNAME") -self._system_password = os.getenv("SYSTEM_ADMIN_PASSWORD") - -if not self._system_username or not self._system_password: - raise ValueError("Credentials required!") -``` - ---- - -## 🚀 Быстрая миграция (2 минуты) - -### **Шаг 1: Генерируем безопасный пароль** - -```bash -openssl rand -base64 32 -``` - -**Пример вывода:** `Xk7N9pQ2vT8mL5wR3jH6yU4aF1sD0eG9` - ---- - -### **Шаг 2: Меняем пароль в Guacamole** - -1. Войдите в Guacamole: `https://mc.exbytestudios.com` -2. **Settings** → **Users** → **guacadmin** -3. **Change password** → вставьте сгенерированный пароль -4. Сохраните - ---- - -### **Шаг 3: Обновляем production.env** - -```bash -cd /usr/local/guacomole_project -nano GuacamoleRemoteAccess/production.env -``` - -**Найдите и обновите:** -```bash -# 🔒 System Admin Account -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=Xk7N9pQ2vT8mL5wR3jH6yU4aF1sD0eG9 # ⬅️ Ваш новый пароль! -``` - -⚠️ **Пароли ДОЛЖНЫ совпадать!** - ---- - -### **Шаг 4: Перезапускаем API** - -```bash -cd GuacamoleRemoteAccess -docker compose restart remote_access_api -``` - ---- - -### **Шаг 5: Проверяем работу** - -```bash -# Проверяем запуск API -docker compose logs remote_access_api | tail -20 - -# ✅ Должно быть: -# "System token refreshed successfully" -# "Application startup complete" - -# ❌ Если ошибка: -# "SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD environment variables are required" -# → Вернитесь к Шагу 3 -``` - ---- - -## 🔄 Для существующих установок с дефолтным паролем - -Если вы **ранее использовали дефолтный пароль `guacadmin`**, ваша установка **продолжит работать**, но: - -### ⚠️ **Рекомендуем немедленно обновить!** - -```bash -# 1. Сгенерируйте новый пароль -NEW_PASSWORD=$(openssl rand -base64 32) -echo "Новый пароль: $NEW_PASSWORD" - -# 2. Обновите в Guacamole UI (см. выше) - -# 3. Обновите production.env -echo "SYSTEM_ADMIN_PASSWORD=$NEW_PASSWORD" >> GuacamoleRemoteAccess/production.env - -# 4. Перезапустите -cd GuacamoleRemoteAccess && docker compose restart remote_access_api -``` - ---- - -## 🆘 Troubleshooting - -### Проблема: API не запускается после обновления - -**Логи:** -``` -ValueError: SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD environment -variables are required -``` - -**Решение:** -```bash -# Проверьте наличие переменных в production.env -grep SYSTEM_ADMIN GuacamoleRemoteAccess/production.env - -# Должно быть: -# SYSTEM_ADMIN_USERNAME=guacadmin -# SYSTEM_ADMIN_PASSWORD=какой-то_пароль - -# Если пусто - добавьте: -echo "SYSTEM_ADMIN_USERNAME=guacadmin" >> GuacamoleRemoteAccess/production.env -echo "SYSTEM_ADMIN_PASSWORD=ваш_пароль_из_guacamole" >> GuacamoleRemoteAccess/production.env -``` - ---- - -### Проблема: `Failed to authenticate system user` - -**Причина:** Пароль в `production.env` не совпадает с паролем в Guacamole. - -**Решение:** -1. Войдите в Guacamole UI -2. Убедитесь какой пароль установлен для guacadmin -3. Обновите `SYSTEM_ADMIN_PASSWORD` в `production.env` -4. Перезапустите API - ---- - -### Проблема: Хочу продолжить использовать `guacadmin:guacadmin` - -**⚠️ НЕ РЕКОМЕНДУЕТСЯ для production!** - -Но если очень нужно (только для dev/test): - -```bash -# production.env -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=guacadmin -``` - -⚠️ **КРИТИЧНО:** Эта конфигурация небезопасна и может быть скомпрометирована! - ---- - -## ✅ Checklist миграции - -- [ ] Сгенерирован новый пароль -- [ ] Пароль guacadmin изменен в Guacamole UI -- [ ] `production.env` обновлен -- [ ] API успешно перезапущен -- [ ] Логи подтверждают успешную аутентификацию -- [ ] Дефолтный пароль больше **НЕ используется** - ---- - -## 📚 Дополнительная информация - -- `SECURITY_SETUP.md` - полная инструкция по безопасной настройке -- `DEPLOYMENT_API_GUIDE.md` - руководство по деплою -- `production.env` - файл с переменными окружения - ---- - -**Время миграции:** ~2-5 минут -**Downtime:** ~10 секунд (только перезапуск API) -**Риски:** Минимальные (откат = вернуть старый пароль) - diff --git a/guacamole_test_11_26/docs/QUICK_CORS_SETUP.md b/guacamole_test_11_26/docs/QUICK_CORS_SETUP.md deleted file mode 100755 index 0a207071..00000000 --- a/guacamole_test_11_26/docs/QUICK_CORS_SETUP.md +++ /dev/null @@ -1,39 +0,0 @@ -# 🚀 Quick CORS Setup - -## Добавить новый домен клиента (3 шага) - -### 1️⃣ Откройте `production.env` - -```bash -nano production.env -``` - -### 2️⃣ Добавьте ваш домен в ALLOWED_ORIGINS - -```env -ALLOWED_ORIGINS=https://mc.exbytestudios.com,https://test.exbytestudios.com,https://YOUR_DOMAIN.com -``` - -**⚠️ Важно:** -- Домены через запятую БЕЗ пробелов -- С протоколом: `https://` или `http://` -- Без `/` в конце - -### 3️⃣ Перезапустите API - -```bash -docker-compose restart api -``` - ---- - -## ✅ Готово! - -Теперь ваш домен может делать запросы к API без CORS ошибок. - ---- - -## 📖 Полная документация - -См. [CORS_CONFIGURATION.md](./CORS_CONFIGURATION.md) для детального руководства и troubleshooting. - diff --git a/guacamole_test_11_26/docs/QUICK_START_CUSTOM_ADMIN.md b/guacamole_test_11_26/docs/QUICK_START_CUSTOM_ADMIN.md deleted file mode 100755 index ecf6d920..00000000 --- a/guacamole_test_11_26/docs/QUICK_START_CUSTOM_ADMIN.md +++ /dev/null @@ -1,262 +0,0 @@ -# ⚡ Быстрый старт: Кастомный администратор Guacamole - -## 🎯 Цель - -Развернуть проект с **безопасным паролем администратора** с самого начала. - -**Время выполнения:** 5 минут - ---- - -## 📋 Шаг 1: Генерируем безопасный пароль - -```bash -# Windows PowerShell -$password = -join ((65..90) + (97..122) + (48..57) + (33,35,36,37,38,42,43,45,61) | Get-Random -Count 20 | ForEach-Object {[char]$_}) -echo "Generated password: $password" - -# Linux/Mac -openssl rand -base64 32 -``` - -**Сохраните пароль в безопасное место** (password manager)! - ---- - -## 📋 Шаг 2: Генерируем SQL для администратора - -```bash -cd GuacamoleRemoteAccess - -# Замените YOUR_SECURE_PASSWORD на сгенерированный пароль -python generate_guacamole_user.py \ - --username guacadmin \ - --password "YOUR_SECURE_PASSWORD" \ - --admin \ - --verify \ - > 002-create-admin-user-custom.sql -``` - -**Пример вывода:** -``` -[VERIFY] Verifying hash generation... -[OK] Hash generation verified -[OK] SQL generated successfully! - Username: guacadmin - Role: Administrator - Password length: 20 characters -``` - ---- - -## 📋 Шаг 3: Заменяем дефолтный SQL - -```bash -# Делаем backup оригинала -mv 002-create-admin-user.sql 002-create-admin-user-DEFAULT-BACKUP.sql - -# Используем наш кастомный -mv 002-create-admin-user-custom.sql 002-create-admin-user.sql -``` - -**Теперь при первом запуске будет использован ВАШ пароль!** - ---- - -## 📋 Шаг 4: Обновляем production.env - -```bash -nano production.env -``` - -**Установите те же credentials:** -```bash -# System Admin Account -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=YOUR_SECURE_PASSWORD # ⬅️ Тот же пароль! -``` - -⚠️ **КРИТИЧНО:** Пароли ДОЛЖНЫ совпадать! - ---- - -## 📋 Шаг 5: Первый запуск - -```bash -# Запускаем проект -docker compose up -d - -# Проверяем логи -docker compose logs postgres | grep "guacadmin" -docker compose logs remote_access_api | grep "System token" -``` - -**Ожидаемый результат:** -``` -[OK] System token refreshed successfully -[OK] Application startup complete -``` - ---- - -## 📋 Шаг 6: Проверяем доступ - -```bash -# Проверяем вход в Guacamole UI -# Откройте: https://mc.exbytestudios.com -# Войдите: guacadmin / YOUR_SECURE_PASSWORD - -# Проверяем API -curl -X POST https://mc.exbytestudios.com/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"username": "guacadmin", "password": "YOUR_SECURE_PASSWORD"}' -``` - -**Должны получить JWT токен!** - ---- - -## ✅ Checklist - -- [ ] Сгенерирован безопасный пароль (минимум 16 символов) -- [ ] SQL создан через `generate_guacamole_user.py` -- [ ] Оригинальный `002-create-admin-user.sql` заменен -- [ ] `production.env` обновлен с теми же credentials -- [ ] Проект запущен (`docker compose up -d`) -- [ ] Логи подтверждают успешный старт -- [ ] Можно войти в Guacamole UI с новым паролем -- [ ] API возвращает JWT токен -- [ ] Backup оригинального SQL сохранен (опционально) - ---- - -## 🔄 Альтернативный вариант: Для существующей установки - -Если проект уже запущен и нужно **изменить** пароль guacadmin: - -```bash -# 1. Генерируем новый хеш -python generate_guacamole_user.py \ - --username guacadmin \ - --password "NEW_SECURE_PASSWORD" \ - --admin \ - > update-admin-password.sql - -# 2. Редактируем SQL для UPDATE вместо INSERT -# Меняем INSERT на UPDATE (см. CUSTOM_GUACAMOLE_USER.md) - -# 3. Применяем к существующей БД -docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < update-admin-password.sql - -# 4. Обновляем production.env -nano production.env -# SYSTEM_ADMIN_PASSWORD=NEW_SECURE_PASSWORD - -# 5. Перезапускаем API -docker compose restart remote_access_api -``` - ---- - -## 🆘 Troubleshooting - -### Проблема: "Failed to authenticate system user" - -**Решение:** -```bash -# Проверяем что пароли совпадают -docker compose exec postgres psql -U guacamole_user -d guacamole_db -c \ - "SELECT name FROM guacamole_user u - JOIN guacamole_entity e ON u.entity_id = e.entity_id - WHERE e.name = 'guacadmin';" - -# Если пользователь существует - проверьте пароль в production.env -grep SYSTEM_ADMIN_PASSWORD production.env -``` - ---- - -### Проблема: Скрипт выдает ошибку кодировки - -**Решение:** Используйте PowerShell с UTF-8: -```powershell -[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -python generate_guacamole_user.py --username admin --password "Pass123!" -``` - ---- - -### Проблема: SQL не применяется автоматически - -**Причина:** SQL скрипты в `docker-entrypoint-initdb.d` выполняются **только если БД пустая**. - -**Решение для существующей БД:** -```bash -# Применить вручную -docker compose exec -T postgres psql -U guacamole_user -d guacamole_db < 002-create-admin-user.sql -``` - -**Решение для чистой установки:** -```bash -# Удалить volume и пересоздать -docker compose down -v -docker compose up -d -``` - ---- - -## 📊 Проверка корректности хеша - -Скрипт имеет встроенную проверку с флагом `--verify`: - -```bash -python generate_guacamole_user.py \ - --username test \ - --password "TestPass123" \ - --verify -``` - -**Вывод:** -``` -[VERIFY] Verifying hash generation... -[OK] Hash generation verified -``` - -Это гарантирует что: -- ✅ Salt генерируется случайно (каждый раз разный) -- ✅ Hash вычисляется корректно (SHA-256) -- ✅ Формат совместим с Guacamole - ---- - -## 🔐 Безопасность - -**Рекомендации:** - -1. ✅ **Генерируйте пароли случайно** (минимум 20 символов) -2. ✅ **Не используйте дефолтные пароли** (`guacadmin:guacadmin`) -3. ✅ **Не коммитьте** `.env` файлы и SQL с паролями в git -4. ✅ **Храните пароли безопасно** (password manager, vault) -5. ✅ **Меняйте пароли регулярно** (каждые 90 дней) -6. ✅ **Используйте `--verify`** для проверки корректности - -**Что НЕ делать:** - -- ❌ Не используйте простые пароли (`admin123`, `password`) -- ❌ Не храните пароли в plain text в git -- ❌ Не используйте один и тот же пароль для разных окружений -- ❌ Не давайте системные credentials обычным пользователям - ---- - -## 📚 Дополнительные материалы - -- `CUSTOM_GUACAMOLE_USER.md` - полное руководство -- `MIGRATION_SECURITY_UPDATE.md` - миграция для существующих установок -- `DEPLOYMENT_API_GUIDE.md` - деплой проекта -- `production.env` - переменные окружения - ---- - -**Готово!** Теперь ваш проект защищен с самого начала! 🎉 - diff --git a/guacamole_test_11_26/docs/TOKEN_FIX_SUMMARY.md b/guacamole_test_11_26/docs/TOKEN_FIX_SUMMARY.md deleted file mode 100755 index 2ccad092..00000000 --- a/guacamole_test_11_26/docs/TOKEN_FIX_SUMMARY.md +++ /dev/null @@ -1,230 +0,0 @@ -# 🔧 Token Issue Fix - Восстановление подключений - -## Проблема - -При восстановлении подключений после logout/login возникала ошибка 403 Forbidden при переключении между подключениями. - -### Причина - -Middleware получал Guacamole токен **напрямую из JWT payload**, а не из активной сессии в Redis. - -**ДО исправления:** -```python -# middleware.py (строка 77) -user_token = jwt_payload.get("guac_token") # ❌ guac_token нет в JWT! -``` - -**Проблема:** -- JWT содержит только `session_id`, а не `guac_token` -- При логине создается новая сессия в Redis с новым Guacamole токеном -- Но middleware не загружал сессию из Redis, поэтому `user_token` был `None` или старый - ---- - -## Решение - -### ✅ Исправление в `middleware.py` - -Теперь middleware: -1. Извлекает `session_id` из JWT -2. Загружает актуальную сессию из Redis -3. Получает текущий Guacamole токен из сессии - -**ПОСЛЕ исправления:** -```python -# middleware.py (строки 77-112) -session_id = jwt_payload.get("session_id") -if session_id: - # Загружаем сессию из Redis - from auth.session_storage import session_storage - session_data = session_storage.get_session(session_id) - - if session_data: - # ✅ Получаем актуальный Guacamole token из сессии - user_token = session_data.get("guac_token") - else: - # Сессия истекла или удалена - user_token = None -else: - # Backwards compatibility - user_token = jwt_payload.get("guac_token") -``` - ---- - -## Как это работает - -### Схема аутентификации - -``` -┌─────────────────┐ -│ 1. Пользователь │ -│ логинится │ -└────────┬────────┘ - │ - ▼ -┌────────────────────────────────────────────┐ -│ 2. Guacamole возвращает auth_token │ -└────────┬───────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────┐ -│ 3. API создает Redis сессию: │ -│ - session_id: "abc123" │ -│ - guac_token: "guac_token_xyz" │ -│ - user_info: {...} │ -└────────┬───────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────┐ -│ 4. API создает JWT token: │ -│ { │ -│ "username": "user", │ -│ "role": "USER", │ -│ "session_id": "abc123", ← ТОЛЬКО ID! │ -│ "exp": ... │ -│ } │ -└────────┬───────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────┐ -│ 5. Клиент отправляет запросы с JWT │ -└────────┬───────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────┐ -│ 6. Middleware: │ -│ - Извлекает session_id из JWT │ -│ - Загружает сессию из Redis ✅ │ -│ - Получает актуальный guac_token ✅ │ -└────────────────────────────────────────────┘ -``` - -### Восстановление подключений - -``` -User API Redis Guacamole - │ │ │ │ - │─────LOGIN──────>│ │ │ - │ │───AUTH───────────────────────────────>│ - │ │<──guac_token_A────────────────────────│ - │ │ │ │ - │ │──CREATE SESSION──>│ │ - │ │ (guac_token_A) │ │ - │<─JWT(session_id)│ │ │ - │ │ │ │ - │──CREATE CONN───>│ │ │ - │ │──GET TOKEN───────>│ │ - │ │<─guac_token_A─────│ │ - │ │────CREATE CONNECTION─────────────────>│ - │<─connection_url─│ │ │ - │ (token_A) │ │ │ - │ │ │ │ - │────LOGOUT──────>│ │ │ - │ │──DELETE SESSION──>│ │ - │ │ │ │ - │─────LOGIN──────>│ │ │ - │ │───AUTH───────────────────────────────>│ - │ │<──guac_token_B────────────────────────│ ← NEW TOKEN! - │ │ │ │ - │ │──CREATE SESSION──>│ │ - │ │ (guac_token_B) │ │ - │<─JWT(session_id)│ │ │ - │ │ │ │ - │──GET CONNECTIONS│ │ │ - │ │──GET TOKEN───────>│ │ - │ │<─guac_token_B─────│ ✅ CURRENT TOKEN │ - │<─URLs (token_B) │ │ │ - │ ✅ РАБОТАЕТ! │ │ │ -``` - ---- - -## Применение исправления - -```bash -cd GuacamoleRemoteAccess -docker-compose restart api -``` - ---- - -## Проверка - -После применения исправления: - -1. ✅ Логинитесь в клиент -2. ✅ Создайте подключение к любой машине -3. ✅ Сделайте logout -4. ✅ Залогиньтесь снова -5. ✅ Восстановите подключение -6. ✅ Создайте новое подключение к другой машине -7. ✅ Переключайтесь между подключениями → **403 ошибки больше нет!** 🎉 - ---- - -## Технические детали - -### JWT Payload (после логина) - -```json -{ - "username": "user", - "role": "USER", - "permissions": [], - "session_id": "4edb****************************8c45", - "token_type": "access", - "exp": 1730721881, - "iat": 1730718281, - "iss": "remote-access-api" -} -``` - -**Замечание:** `guac_token` НЕ хранится в JWT по соображениям безопасности. - -### Redis Session (при логине) - -```json -{ - "user_info": { - "username": "user", - "role": "USER", - "permissions": [] - }, - "guac_token": "589f****************************6edc", - "ecdh_session_id": "abc123...", - "created_at": "2025-11-04T14:24:41.123456Z", - "expires_at": "2025-11-04T15:24:41.123456Z" -} -``` - ---- - -## Backwards Compatibility - -Исправление поддерживает старые JWT токены (если они содержат `guac_token` напрямую): - -```python -else: - # Старый формат JWT с guac_token напрямую (backwards compatibility) - user_token = jwt_payload.get("guac_token") -``` - -Это позволяет избежать проблем при rolling deployment. - ---- - -## Связанные файлы - -- `GuacamoleRemoteAccess/api/auth/middleware.py` - middleware для извлечения токена -- `GuacamoleRemoteAccess/api/auth/utils.py` - создание JWT с `session_id` -- `GuacamoleRemoteAccess/api/auth/guacamole_auth.py` - создание сессий в Redis -- `GuacamoleRemoteAccess/api/auth/session_storage.py` - хранилище сессий -- `GuacamoleRemoteAccess/api/main.py` - endpoint `/connections` для восстановления - ---- - -## Дата исправления - -2025-11-04 - diff --git a/guacamole_test_11_26/docs/Действительноважно.md b/guacamole_test_11_26/docs/Действительноважно.md deleted file mode 100755 index e400990c..00000000 --- a/guacamole_test_11_26/docs/Действительноважно.md +++ /dev/null @@ -1,342 +0,0 @@ -# 🔒 Инструкция по безопасной настройке системных credentials - -## ⚠️ Критически важно! - -**Система ТРЕБУЕТ установки credentials для системного администратора Guacamole.** -API **НЕ ЗАПУСТИТСЯ** без этих переменных окружения. А клиент не запустится без установки ключа, инструкция есть в API - ---- - -## 📋 Что нужно настроить - -### 1. **Создайте безопасный пароль для системного администратора** - -```bash -# Генерируем случайный пароль (32 символа) -openssl rand -base64 32 -``` - -**Пример вывода:** -``` -Xk7N9pQ2vT8mL5wR3jH6yU4aF1sD0eG9 -``` - ---- - -## 🔧 Настройка для Production - -### **Шаг 1: Измените пароль guacadmin в Guacamole** - -1. Войдите в Guacamole UI как `guacadmin` (дефолтный пароль: `guacadmin`) -2. **Settings** → **Users** → **guacadmin** → **Change password** -3. Установите **безопасный пароль**, сгенерированный выше -4. Сохраните изменения - -### **Шаг 2: Обновите `production.env`** - -```bash -# Откройте production.env -nano GuacamoleRemoteAccess/production.env - -# Найдите и обновите: -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=Xk7N9pQ2vT8mL5wR3jH6yU4aF1sD0eG9 # ⬅️ Ваш пароль из Guacamole! -``` - -⚠️ **Пароль ДОЛЖЕН совпадать с паролем guacadmin в Guacamole!** - -### **Шаг 3: Перезапустите API** - -```bash -cd GuacamoleRemoteAccess -docker compose restart remote_access_api -``` - -### **Шаг 4: Проверьте логи** - -```bash -docker compose logs remote_access_api | grep "System token" -``` - -✅ **Успех:** `System token refreshed successfully` -❌ **Ошибка:** `Failed to authenticate system user` → проверьте совпадение паролей - ---- - -## 🛠️ Настройка для Development - -Для локальной разработки можно использовать дефолтные credentials, **НО:** - -### **Вариант 1: Дефолтные credentials (только для local dev)** - -```bash -# .env или encryption.env -SYSTEM_ADMIN_USERNAME=guacadmin -SYSTEM_ADMIN_PASSWORD=guacadmin -``` - -⚠️ **НИКОГДА не используйте дефолтные credentials на серверах доступных из интернета!** - -### **Вариант 2: Безопасные credentials (рекомендуется)** - -То же самое что для Production (см. выше). - ---- - -## 🔍 Зачем нужны системные credentials? - -API использует системный токен для: - -1. ✅ **Cleanup orphaned connections** - удаление "мертвых" подключений после краша Redis -2. ✅ **Startup cleanup** - очистка истекших подключений при старте -3. ✅ **System operations** - служебные операции требующие прав администратора - -**Без системного токена:** -- ❌ Orphaned connections будут накапливаться -- ❌ Cleanup при старте не будет работать -- ❌ API не запустится (security check) - ---- - -## 🚨 Что происходит при отсутствии credentials? - -```python -# API выбросит ошибку при старте: -ValueError: SYSTEM_ADMIN_USERNAME and SYSTEM_ADMIN_PASSWORD environment -variables are required. Set these in your .env or production.env file for -security. Never use default credentials in production! -``` - -**Контейнер упадет с ошибкой →** необходимо установить переменные. - ---- - -## 📝 Checklist перед деплоем - -- [ ] Сгенерирован безопасный пароль (`openssl rand -base64 32`) -- [ ] Пароль guacadmin изменен в Guacamole UI -- [ ] `production.env` обновлен с новым паролем -- [ ] Пароли в Guacamole UI и `production.env` **совпадают** -- [ ] API успешно запустился (`docker compose up -d`) -- [ ] Логи подтверждают успешную аутентификацию -- [ ] Дефолтные пароли **НИГДЕ не используются** - ---- - -## 🔐 Дополнительные рекомендации безопасности - -1. **Используйте secrets management** (Docker Secrets, Vault, etc.) для production -2. **Ротируйте пароли регулярно** (каждые 90 дней) -3. **Ограничьте доступ к `.env` файлам** (`chmod 600`) -4. **Никогда не коммитьте** `.env` файлы в git (`.gitignore`) -5. **Используйте SSL/TLS** для Guacamole Admin UI - ---- - -## 🆘 Troubleshooting - -### Проблема: `Failed to authenticate system user` - -**Причина:** Пароль в `production.env` не совпадает с паролем guacadmin в Guacamole. - -**Решение:** -```bash -# Проверьте пароль в Guacamole UI -# Убедитесь что SYSTEM_ADMIN_PASSWORD точно совпадает -docker compose restart remote_access_api -``` - -### Проблема: `SYSTEM_ADMIN_PASSWORD environment variables are required` - -**Причина:** Переменные окружения не установлены. - -**Решение:** -```bash -# Убедитесь что .env или production.env загружен -docker compose config | grep SYSTEM_ADMIN -# Должны быть значения (не пустые) -``` - -### Проблема: API запускается, но cleanup не работает - -**Причина:** Системный токен не может быть получен (неверные credentials). - -**Решение:** Проверьте логи и сверьте пароли. - ---- - -## 🔑 КРИТИЧНО: Ed25519 Signing Key для ECDH - -### ⚠️ Проблема: "Invalid server key signature - possible MITM attack!" - -Если клиент не может войти и показывает ошибку подписи: - -``` -[key-exchange] Invalid server key signature - rejecting for security -[key-exchange] Failed to set server public key | "Invalid server key signature - possible MITM attack!" -[auth-service] Login failed -``` - -**Причина:** Клиент использует **старый/неправильный TRUSTED_SIGNING_KEY**! - ---- - -### 📋 Как исправить: - -#### **Шаг 1: Получите текущий signing public key с сервера** - -```bash -# На сервере - извлекаем публичный ключ подписи -cd /usr/local/guacamole_project - -docker compose exec remote_access_api python3 -c " -from api.auth.key_exchange import ecdh_key_exchange -from cryptography.hazmat.primitives import serialization -import base64 - -signing_pub = ecdh_key_exchange.signing_public_key.public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo -) -print('Signing Public Key (base64):') -print(base64.b64encode(signing_pub).decode()) -" -``` - -**Пример вывода:** -``` -Signing Public Key (base64): -LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQVlXSytycFozN0VldklYVG8yYzlYSGUrKzZyWG82WlI1UENxNkxDdE40Zm89Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo= -``` - ---- - -#### **Шаг 2: Обновите клиент** - -Откройте файл клиента: -``` -MachineControlCenter/src/renderer/services/SignatureVerificationService.ts -``` - -Найдите (строка ~10-13): -```typescript -private static readonly TRUSTED_SIGNING_KEYS = { - production: "LS0tLS1CRUdJTi...", // ← ЗАМЕНИТЕ этот ключ! - staging: "LS0tLS1CRUdJTi...", -}; -``` - -Замените `production` ключ на ключ из **Шага 1**. - ---- - -#### **Шаг 3: Пересоберите клиент** - -```bash -cd MachineControlCenter -npm run build -npm run electron:build:win -``` - ---- - -### 🔍 Почему это происходит? - -1. **Сервер генерирует Ed25519 ключ** при первом запуске -2. **Ключ сохраняется** в `/app/secrets/ed25519_signing_key.pem` -3. **Клиент должен знать публичную часть** для проверки подписи -4. **Если ключи не совпадают** → MITM защита блокирует вход - ---- - -### 🛡️ Безопасность: - -**Это КРИТИЧНАЯ защита от MITM атак!** - -- ✅ Сервер подписывает каждый ephemeral ECDH ключ -- ✅ Клиент проверяет подпись перед key exchange -- ✅ Без правильной подписи → вход ЗАПРЕЩЕН - -**НЕ отключайте эту проверку!** Вместо этого синхронизируйте ключи. - ---- - -### 📝 Автоматизация (опционально): - -Создайте скрипт для обновления клиента: - -```bash -#!/bin/bash -# sync-signing-key.sh - -# Получаем ключ с сервера -KEY=$(docker compose exec -T remote_access_api python3 -c " -from api.auth.key_exchange import ecdh_key_exchange -from cryptography.hazmat.primitives import serialization -import base64 -signing_pub = ecdh_key_exchange.signing_public_key.public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo -) -print(base64.b64encode(signing_pub).decode()) -") - -# Обновляем клиент (sed команда) -sed -i "s/production: \".*\"/production: \"$KEY\"/" \ - ../MachineControlCenter/src/renderer/services/SignatureVerificationService.ts - -echo "✅ Signing key synced!" -echo "🔨 Rebuild client: cd ../MachineControlCenter && npm run build" -``` - ---- - -### 🆘 Troubleshooting: - -#### Проблема: Ключ не извлекается с сервера - -**Причина:** Файл `/app/secrets/ed25519_signing_key.pem` не существует. - -**Решение:** -```bash -# Перезапустите API для генерации нового ключа -docker compose restart remote_access_api - -# Проверьте логи -docker compose logs remote_access_api | grep "signing" -# Должно быть: "Server signing keypair generated successfully" -``` - ---- - -#### Проблема: После обновления ключа старые клиенты не могут войти - -**Причина:** У них старый TRUSTED_SIGNING_KEY. - -**Решение:** Пересоберите и распространите новую версию клиента. - ---- - -#### Проблема: Хочу использовать один ключ для prod/staging/dev - -**Решение:** Скопируйте `ed25519_signing_key.pem` между окружениями: - -```bash -# С production сервера -docker compose exec remote_access_api cat /app/secrets/ed25519_signing_key.pem > signing_key.pem - -# На staging/dev сервер -docker compose cp signing_key.pem remote_access_api:/app/secrets/ed25519_signing_key.pem -docker compose restart remote_access_api -``` - ---- - -## 📚 Связанные документы - -- `DEPLOYMENT_API_GUIDE.md` - полная инструкция по деплою -- `production.env` - файл с переменными окружения -- `JWT-SECURITY-GUIDE.md` - настройка JWT аутентификации -- `SignatureVerificationService.ts` - код проверки подписи на клиенте -- `key_exchange.py` - код генерации и подписи ключей на сервере - diff --git a/mc_test/.gitignore b/mc_test/.gitignore new file mode 100755 index 00000000..a9b8c9af --- /dev/null +++ b/mc_test/.gitignore @@ -0,0 +1,48 @@ +# Docker +.env +docker-compose.override.yml + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.pyc +venv/ +env/ +.venv/ + +# Logs +*.log +logs/ + +# Database +*.db +*.sqlite + +# Generated SQL files with passwords (SECURITY) +*custom*.sql +*-admin-user.sql +!002-create-admin-user.sql # Except default template +*-GENERATED.sql +*-DEFAULT-BACKUP.sql +update-*.sql +create-user-*.sql + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Temporary files +*.tmp +*.temp + +# PostgreSQL data (if running locally) +data/ +dist/ +node_modules/ diff --git a/mc_test/ENV_SETUP.md b/mc_test/ENV_SETUP.md deleted file mode 100755 index 4a1f9b42..00000000 --- a/mc_test/ENV_SETUP.md +++ /dev/null @@ -1,131 +0,0 @@ -# Environment Configuration Guide - -## Overview - -All hardcoded IP addresses and domains have been moved to environment variables for easier configuration across different environments. - -## Quick Start - -1. **Copy the example file:** - ```bash - cp env.example .env - ``` - -2. **Edit `.env` with your values:** - ```bash - # For local development - VITE_API_URL=http://localhost:8000 - VITE_DEV_HOST=192.168.200.10 - - # For production - VITE_API_URL=https://mc.exbytestudios.com - VITE_PROD_DOMAIN=mc.exbytestudios.com - ``` - -3. **Start development server:** - ```bash - npm run dev - ``` - -## Environment Variables - -### API Configuration -- `VITE_API_URL` - Base URL for API endpoints (default: `https://mc.exbytestudios.com`) - - Development: `http://localhost:8000` - - Production: `https://mc.exbytestudios.com` - -### Domain Configuration -- `VITE_PROD_DOMAIN` - Production domain (default: `mc.exbytestudios.com`) -- `VITE_BACKUP_DOMAIN` - Backup domain (default: `backup.mc.exbytestudios.com`) -- `VITE_TEST_DOMAIN` - Test domain (default: `test.exbytestudios.com`) - -### Development Server Configuration -- `VITE_DEV_HOST` - Vite dev server host (default: `192.168.200.10`) -- `VITE_DEV_PORT` - Vite dev server port (default: `5173`) -- `VITE_DEV_ALLOWED_HOST` - Allowed host for HMR (default: `test.exbytestudios.com`) - -### Security Settings -- `VITE_ENABLE_CERTIFICATE_PINNING` - Enable/disable certificate pinning (default: `true`) - - Set to `false` in development - - Set to `true` in production -- `VITE_CERTIFICATE_PINNING_FALLBACK` - Enable fallback for certificate pinning (default: `true`) - -### Development Settings -- `VITE_DEBUG_MODE` - Enable debug mode (default: `false`) -- `VITE_LOG_LEVEL` - Logging level: `debug`, `info`, `warn`, `error` (default: `info`) - -## Files Using Environment Variables - -### Configuration Files -- `vite.config.ts` - Uses `VITE_DEV_HOST`, `VITE_DEV_PORT`, `VITE_DEV_ALLOWED_HOST` -- `src/renderer/config/api.ts` - Uses `VITE_API_URL` - -### Service Files -- `src/renderer/services/CertificatePinning.ts` - Uses `VITE_PROD_DOMAIN`, `VITE_BACKUP_DOMAIN` -- `src/renderer/utils/csp.ts` - Uses `VITE_PROD_DOMAIN` -- `src/renderer/mocks/mockMachines.ts` - Uses `VITE_DEV_HOST` - -### Static Configuration Files (Manual Update Required) -- `csp-config.json` - Update production domains manually to match `.env` -- `index.html` - CSP meta tag uses hardcoded values (acceptable for development) - -## Development vs Production - -### Development (.env.development) -```env -VITE_API_URL=http://localhost:8000 -VITE_DEV_HOST=192.168.200.10 -VITE_ENABLE_CERTIFICATE_PINNING=false -VITE_DEBUG_MODE=true -VITE_LOG_LEVEL=debug -``` - -### Production (.env.production) -```env -VITE_API_URL=https://mc.exbytestudios.com -VITE_PROD_DOMAIN=mc.exbytestudios.com -VITE_ENABLE_CERTIFICATE_PINNING=true -VITE_DEBUG_MODE=false -VITE_LOG_LEVEL=info -``` - -## Migration from Hardcoded Values - -All instances of hardcoded IP (`192.168.200.10`) and domains (`*.exbytestudios.com`) have been replaced with environment variables: - -### Before -```typescript -const API_URL = 'https://mc.exbytestudios.com'; -host: '192.168.200.10' -``` - -### After -```typescript -const API_URL = import.meta.env.VITE_API_URL || 'https://mc.exbytestudios.com'; -host: import.meta.env.VITE_DEV_HOST || '192.168.200.10' -``` - -## Security Notes - -1. **Never commit `.env` files to git** - They are in `.gitignore` by default -2. **Use different values for each environment** - Development, Testing, Production -3. **Enable certificate pinning in production** - Set `VITE_ENABLE_CERTIFICATE_PINNING=true` -4. **Update `csp-config.json`** - When changing production domains, update CSP config manually - -## Troubleshooting - -### API connection fails -- Check `VITE_API_URL` matches your API server -- Verify API server is running -- Check network connectivity - -### HMR (Hot Module Replacement) not working -- Verify `VITE_DEV_HOST` is accessible -- Check `VITE_DEV_ALLOWED_HOST` matches your access domain -- Ensure WebSocket connections are allowed - -### Certificate pinning errors -- Disable in development: `VITE_ENABLE_CERTIFICATE_PINNING=false` -- Verify certificate fingerprints in production -- Check `VITE_PROD_DOMAIN` matches actual certificate domain -