fix(install): повторный запуск установщика больше не меняет секреты
Найдено на стенде: повторный `install.sh` без `--reconfigure` генерировал новые MASTER_KEY/SESSION_PEPPER/TOTP_ENCRYPTION_KEY, после чего email-индекс и TOTP-секреты существующих пользователей перестали расшифровываться (вход возвращал `auth.invalid_credentials`). - секреты переиспользуются при любом повторном запуске, а не только с `--reconfigure`; - добавлен явный флаг `--rotate-secrets` с предупреждением о последствиях; - age-ключ бэкапов сохраняется, старые бэкапы остаются читаемыми; - защита от потери `.env`: если база есть, а MASTER_KEY нет — установщик останавливается с объяснением вместо молчаливой генерации новых ключей; - `scripts/test-install.sh` сравнивает секреты до и после повторной установки и падает при их изменении.
This commit is contained in:
+26
-5
@@ -79,6 +79,8 @@ INSTANCE_NAME="${INSTANCE_NAME:-glchat}"
|
||||
MAIN_GUILD_NAME="${MAIN_GUILD_NAME:-Главный сервер}"
|
||||
ADMIN_EMAIL="${ADMIN_EMAIL:-}"
|
||||
ENABLE_ADMIN_2FA="${ENABLE_ADMIN_2FA:-0}"
|
||||
# Явная ротация секретов: по умолчанию секреты существующего .env сохраняются.
|
||||
ROTATE_SECRETS="${ROTATE_SECRETS:-0}"
|
||||
ADMIN_PASSWORD="${ADMIN_PASSWORD:-}"
|
||||
REGISTRATION_ENABLED="${REGISTRATION_ENABLED:-true}"
|
||||
TURN_ENABLED="${TURN_ENABLED:-true}"
|
||||
@@ -119,6 +121,8 @@ install.sh — установка glchat (AGENT.md 10).
|
||||
--email <email> email для Let's Encrypt (обязателен, если TLS включён)
|
||||
--admin <email> логин инстанс-администратора
|
||||
--password <password> пароль инстанс-администратора (иначе — интерактивный ввод)
|
||||
--rotate-secrets сменить секреты (MASTER_KEY, SESSION_PEPPER и др.):
|
||||
ломает существующие данные, нужен чистый инстанс
|
||||
--admin-2fa включить 2FA инстанс-админу и напечатать секрет и
|
||||
резервные коды (по умолчанию включается вручную:
|
||||
glchat totp-setup --email <admin>)
|
||||
@@ -188,6 +192,7 @@ parse_args() {
|
||||
--admin) ADMIN_EMAIL="${2:?}"; shift 2 ;;
|
||||
--password) ADMIN_PASSWORD="${2:?}"; shift 2 ;;
|
||||
--admin-2fa) ENABLE_ADMIN_2FA=1; shift ;;
|
||||
--rotate-secrets) ROTATE_SECRETS=1; shift ;;
|
||||
--instance-name) INSTANCE_NAME="${2:?}"; shift 2 ;;
|
||||
--main-guild) MAIN_GUILD_NAME="${2:?}"; shift 2 ;;
|
||||
--ssh-port) SSH_PORT="${2:?}"; shift 2 ;;
|
||||
@@ -569,10 +574,14 @@ generate_secrets() {
|
||||
local env_existing=0
|
||||
[ -f "$GLCHAT_ENV_FILE" ] && env_existing=1
|
||||
|
||||
# Секреты переиспользуются при любом повторном запуске: MASTER_KEY
|
||||
# расшифровывает email/PII и TOTP-секреты, SESSION_PEPPER — blind index,
|
||||
# LIVEKIT_API_SECRET подписывает токены. Их смена делает существующие
|
||||
# данные нечитаемыми, поэтому она возможна только явным --rotate-secrets.
|
||||
secret_or_new() {
|
||||
local key="$1" generator="${2:-rand_hex}"
|
||||
local current=""
|
||||
if [ "$env_existing" = "1" ] && [ "$RECONFIGURE" = "1" ]; then
|
||||
if [ "$env_existing" = "1" ] && [ "$ROTATE_SECRETS" != "1" ]; then
|
||||
current="$(env_get "$key" || true)"
|
||||
fi
|
||||
if [ -n "$current" ]; then
|
||||
@@ -582,6 +591,19 @@ generate_secrets() {
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$ROTATE_SECRETS" = "1" ] && [ "$env_existing" = "1" ]; then
|
||||
warn "ВНИМАНИЕ: --rotate-secrets меняет MASTER_KEY/SESSION_PEPPER."
|
||||
warn "Существующие email/PII, blind index и TOTP-секреты станут нечитаемыми:"
|
||||
warn "нужен чистый инстанс (сначала сделайте бэкап и удалите базу)."
|
||||
fi
|
||||
|
||||
# Существующая база без секретов в .env — почти всегда потерянный .env:
|
||||
# молча сгенерировать новые ключи значит сделать данные нечитаемыми.
|
||||
if [ "$ROTATE_SECRETS" != "1" ] && [ -f "${GLCHAT_DATA_DIR}/db/glchat.db" ] \
|
||||
&& [ -z "$(env_get MASTER_KEY || true)" ]; then
|
||||
die "найдена база ${GLCHAT_DATA_DIR}/db/glchat.db, но в ${GLCHAT_ENV_FILE} нет MASTER_KEY: восстановите .env из бэкапа (иначе данные не расшифровать) или запустите с --rotate-secrets на чистой базе"
|
||||
fi
|
||||
|
||||
SESSION_PEPPER="$(secret_or_new SESSION_PEPPER rand_hex)"
|
||||
MASTER_KEY="$(secret_or_new MASTER_KEY rand_hex)"
|
||||
TOTP_ENCRYPTION_KEY="$(secret_or_new TOTP_ENCRYPTION_KEY rand_hex)"
|
||||
@@ -601,10 +623,9 @@ generate_secrets() {
|
||||
# без смены владельца приложение не сможет создать базу (AGENT.md 4.3).
|
||||
set_data_ownership
|
||||
|
||||
if [ "$env_existing" = "1" ] && [ "$RECONFIGURE" = "1" ] && [ -f "${GLCHAT_DATA_DIR}/backups/age-key.txt" ]; then
|
||||
AGE_KEY_FILE="${GLCHAT_DATA_DIR}/backups/age-key.txt"
|
||||
else
|
||||
AGE_KEY_FILE="${GLCHAT_DATA_DIR}/backups/age-key.txt"
|
||||
# Ключ шифрования бэкапов тоже сохраняем: иначе старые бэкапы не прочитать.
|
||||
AGE_KEY_FILE="${GLCHAT_DATA_DIR}/backups/age-key.txt"
|
||||
if [ ! -f "$AGE_KEY_FILE" ]; then
|
||||
generate_age_key "$AGE_KEY_FILE"
|
||||
fi
|
||||
chmod 600 "$AGE_KEY_FILE"
|
||||
|
||||
Reference in New Issue
Block a user