# 🔐 Создание пользователя 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`** флаг для проверки генерации хеша