# 🔒 Инструкция по безопасной настройке системных 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` - код генерации и подписи ключей на сервере