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