feat(cli): включение 2FA инстанс-админа командой totp-setup

2FA обязательна для инстанс-администраторов, но до её включения вход закрыт —
получался замкнутый круг. Добавлены команды обслуживания:

- `glchat totp-setup --email <admin>`: создаёт секрет, подтверждает его кодом,
  печатает секрет, otpauth-ссылку и 8 резервных кодов (каждый одноразовый);
- `glchat totp-reset --email <admin>`: удаляет секрет при потере устройства;
- код `auth.2fa_enrollment_required` с подсказкой, какую команду выполнить;
- установщик: флаг `--admin-2fa` для автоматического включения (по умолчанию
  печатает подсказку, чтобы секреты не оседали в логах установки).

Проверено сквозным прогоном локально: bootstrap → 403 на входе без 2FA →
totp-setup → вход с TOTP-кодом → профиль, серверы, комнаты, роли, участники,
аудит, создание сервера админом, 429 на шестой попытке входа, секретов в логах
нет.
This commit is contained in:
2026-09-19 21:53:35 +03:00
parent c059cd9f51
commit bf0d130ee8
23 changed files with 1115 additions and 269 deletions
+15
View File
@@ -78,6 +78,7 @@ PROFILE="${PROFILE:-auto}"
INSTANCE_NAME="${INSTANCE_NAME:-glchat}"
MAIN_GUILD_NAME="${MAIN_GUILD_NAME:-Главный сервер}"
ADMIN_EMAIL="${ADMIN_EMAIL:-}"
ENABLE_ADMIN_2FA="${ENABLE_ADMIN_2FA:-0}"
ADMIN_PASSWORD="${ADMIN_PASSWORD:-}"
REGISTRATION_ENABLED="${REGISTRATION_ENABLED:-true}"
TURN_ENABLED="${TURN_ENABLED:-true}"
@@ -118,6 +119,9 @@ install.sh — установка glchat (AGENT.md 10).
--email <email> email для Let's Encrypt (обязателен, если TLS включён)
--admin <email> логин инстанс-администратора
--password <password> пароль инстанс-администратора (иначе — интерактивный ввод)
--admin-2fa включить 2FA инстанс-админу и напечатать секрет и
резервные коды (по умолчанию включается вручную:
glchat totp-setup --email <admin>)
--instance-name <name> название инстанса (по умолчанию glchat)
Сеть:
@@ -183,6 +187,7 @@ parse_args() {
--email) ACME_EMAIL="${2:?}"; shift 2 ;;
--admin) ADMIN_EMAIL="${2:?}"; shift 2 ;;
--password) ADMIN_PASSWORD="${2:?}"; shift 2 ;;
--admin-2fa) ENABLE_ADMIN_2FA=1; shift ;;
--instance-name) INSTANCE_NAME="${2:?}"; shift 2 ;;
--main-guild) MAIN_GUILD_NAME="${2:?}"; shift 2 ;;
--ssh-port) SSH_PORT="${2:?}"; shift 2 ;;
@@ -1463,6 +1468,16 @@ bootstrap_admin() {
else
warn "bootstrap-admin недоступен в этой версии образа (появится в фазе 1); данные сохранены в .env"
fi
# 2FA обязательна для инстанс-админов (AGENT.md 7.19): секрет и резервные
# коды печатает команда totp-setup. По умолчанию не выполняем её, чтобы
# секреты не оседали в логах установки.
if [ "${ENABLE_ADMIN_2FA:-0}" = "1" ]; then
info "включение 2FA для инстанс-админа"
docker exec glchat-app /usr/local/bin/glchat totp-setup --email "$ADMIN_EMAIL" \
|| warn "не удалось включить 2FA автоматически: выполните glchat totp-setup --email $ADMIN_EMAIL"
else
info "2FA инстанс-админа включается вручную: glchat totp-setup --email $ADMIN_EMAIL"
fi
}
run_smoke() {