Files

182 lines
9.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# upgrade-ish-v107.sh — полное автоматическое обновление ИШ до версии 107 на
# Astra Linux (amd64) в headless-режиме (сервер без графической сессии).
#
# ИШ 107 принёс изменения, из-за которых он «из коробки» не стартует как
# systemd-служба без графики. Этот скрипт решает ВСЕ слои (проверено 19.08.2026,
# см. память ish-v107-upgrade):
# 1. Установка .deb (dpkg).
# 2. gnome-keyring для секретов (v107 хранит пароли в OS SecretStore/libsecret).
# 3. Виртуальный дисплей Xvfb (v107 igate-svc тянет GTK/GVFS).
# 4. Параметры канала WSL для v107 (короткий URL, TLS-отпечаток GOST, DN, chain,
# M2M) — через configure-ish-v107.sql.
# 5. Самоочистка stale-состояния (ExecStartPre) — иначе рестарты флакуют.
#
# Конфигурация ИШ живёт в PostgreSQL и ПЕРЕЖИВАЕТ обновление.
#
# Использование:
# sudo ./upgrade-ish-v107.sh /путь/к/igate-107-0-930-amd64.zip
# Опционально переменные окружения:
# SVC_USER (по умолчанию igate) — пользователь службы ИШ
# IGATE_DB (по умолчанию igate) — имя БД PostgreSQL
# CHAN_ID (по умолчанию auto) — id канала в channels (auto = найти WSL)
# KEYRING_PASS_FILE (/var/lib/igate/.keyring-pass) — файл пароля keyring
#
set -euo pipefail
ZIP="${1:?укажите путь к igate-107-*-amd64.zip}"
SVC_USER="${SVC_USER:-igate}"
IGATE_DB="${IGATE_DB:-igate}"
IGATE_DIR="/opt/nsd/igate"
WRAPPER="/usr/local/bin/igate-run.sh" # вне /opt — переживает переустановку .deb
DROPIN_DIR="/etc/systemd/system/igate.service.d"
SQL_DIR="$(cd "$(dirname "$0")" && pwd)"
STAMP="$(date +%Y%m%d-%H%M%S)"
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT
log(){ echo -e "\n=== $* ==="; }
[ "$(id -u)" = 0 ] || { echo "нужен root (sudo)"; exit 1; }
SVC_UID="$(id -u "$SVC_USER")"
KEYRING_PASS_FILE="${KEYRING_PASS_FILE:-/var/lib/$SVC_USER/.keyring-pass}"
HOME_DIR="$(getent passwd "$SVC_USER" | cut -d: -f6)"
log "0/9 Проверка зависимостей"
for bin in dpkg gnome-keyring-daemon dbus-run-session xvfb-run loginctl psql; do
command -v "$bin" >/dev/null || { echo "нет $bin — установите (gnome-keyring, dbus-x11, xvfb, libsecret-tools, postgresql-client)"; exit 1; }
done
echo "все зависимости на месте"
log "1/9 Распаковка дистрибутива"
unzip -o -q "$ZIP" -d "$WORK"
DEB="$(ls "$WORK"/*.deb 2>/dev/null | head -1)"
[ -n "$DEB" ] || { echo "в архиве нет .deb"; exit 1; }
echo "пакет: $(basename "$DEB") версия: $(dpkg-deb -f "$DEB" Version)"
log "2/9 Бэкап установки, конфига службы и БД"
mkdir -p "/var/backups/ish-pre107-$STAMP"
BK="/var/backups/ish-pre107-$STAMP"
[ -d "$IGATE_DIR" ] && tar czf "$BK/opt-nsd-igate.tar.gz" -C "$(dirname "$IGATE_DIR")" "$(basename "$IGATE_DIR")" 2>/dev/null || true
[ -d "$DROPIN_DIR" ] && cp -a "$DROPIN_DIR" "$BK/dropin" || true
( cd /tmp && sudo -u postgres pg_dump -d "$IGATE_DB" -Fc | cat > "$BK/igate-db.dump" ) 2>/dev/null || echo " (пропуск дампа БД)"
echo "$BK" > /var/backups/ish-last-backup.txt
echo "бэкап: $BK"
log "3/9 Остановка службы и очистка stale-состояния"
systemctl stop igate 2>/dev/null || true
pkill -9 -u "$SVC_USER" -f igate-svc 2>/dev/null || true
pkill -9 -u "$SVC_USER" -f Xvfb 2>/dev/null || true
rm -f /tmp/CoreFxPipe_NSD.IGate.* 2>/dev/null || true
log "4/9 Установка пакета (.deb)"
echo "igate igate/service boolean false" | debconf-set-selections
echo "igate igate/shortcut boolean false" | debconf-set-selections
DEBIAN_FRONTEND=noninteractive dpkg -i --force-confnew "$DEB" || apt-get -f install -y || true
echo "версия установлена: $(python3 -c "import json;print([k for k in json.load(open('$IGATE_DIR/igate/igate.deps.json'))['libraries'] if k.lower().startswith('igate/')][0])" 2>/dev/null)"
log "5/9 Подготовка keyring (пароль + linger для XDG_RUNTIME_DIR)"
loginctl enable-linger "$SVC_USER"
if [ ! -f "$KEYRING_PASS_FILE" ]; then
umask 077
# локальный пароль keyring (только для сервисного хранилища секретов ИШ)
head -c 18 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 20 > "$KEYRING_PASS_FILE"
chown "$SVC_USER":"$SVC_USER" "$KEYRING_PASS_FILE"; chmod 600 "$KEYRING_PASS_FILE"
echo "создан $KEYRING_PASS_FILE"
else
echo "используется существующий $KEYRING_PASS_FILE"
fi
# сбросить возможно несовместимый старый login.keyring — wrapper создаст заново
rm -f "$HOME_DIR/.local/share/keyrings/login.keyring" 2>/dev/null || true
log "6/9 Установка wrapper $WRAPPER"
cat > "$WRAPPER" <<EOF
#!/usr/bin/env bash
# headless-запуск igate-svc v107: gnome-keyring + виртуальный дисплей.
# Запускается из ExecStart через dbus-run-session (сессионная шина уже есть).
export HOME=$HOME_DIR
export XDG_DATA_HOME="\$HOME/.local/share"
export XDG_RUNTIME_DIR="/run/user/\$(id -u)"
export GIO_USE_VFS=local
eval "\$(printf '%s\n' "\$(cat $KEYRING_PASS_FILE)" | gnome-keyring-daemon --replace --unlock --components=secrets,pkcs11 2>/dev/null)"
export GNOME_KEYRING_CONTROL SSH_AUTH_SOCK
cd "\$HOME"
exec xvfb-run -a $IGATE_DIR/igate-svc/igate-svc
EOF
chmod +x "$WRAPPER"; echo "wrapper установлен"
log "7/9 Настройка systemd (drop-in с самоочисткой и авто-рестартом)"
mkdir -p "$DROPIN_DIR"
cat > "$DROPIN_DIR/override.conf" <<EOF
[Unit]
StartLimitIntervalSec=300
StartLimitBurst=8
[Service]
User=$SVC_USER
WorkingDirectory=$HOME_DIR
# САМООЧИСТКА stale-состояния перед стартом — иначе рестарты флакуют
# (осиротевшие CoreFxPipe-сокеты / login.keyring / X-локи).
ExecStartPre=-/bin/bash -c 'rm -f /tmp/CoreFxPipe_NSD.IGate.* $HOME_DIR/.local/share/keyrings/login.keyring; find /tmp -maxdepth 1 -name ".X9*-lock" -delete 2>/dev/null; true'
ExecStart=
ExecStart=/usr/bin/dbus-run-session -- $WRAPPER
Restart=on-failure
RestartSec=8
EOF
systemctl daemon-reload
log "8/9 Параметры канала v107 (SQL) + миграция паролей"
CHAN_ID="${CHAN_ID:-auto}"
if [ "$CHAN_ID" = auto ]; then
CHAN_ID="$(cd /tmp && sudo -u postgres psql -d "$IGATE_DB" -tAc "select id from channels where type='WSL' order by id limit 1" 2>/dev/null | tr -d '[:space:]')"
fi
[ -n "$CHAN_ID" ] || { echo "не найден WSL-канал в channels — укажите CHAN_ID вручную"; exit 1; }
echo "канал id=$CHAN_ID"
if [ -f "$SQL_DIR/configure-ish-v107.sql" ]; then
( cd /tmp && sudo -u postgres psql -d "$IGATE_DB" -v chan_id="$CHAN_ID" -f "$SQL_DIR/configure-ish-v107.sql" )
else
echo " ⚠️ configure-ish-v107.sql не найден рядом со скриптом — параметры канала НЕ применены"
fi
# Утилита миграции v107 (флаг миграции); финальный Console.ReadKey в headless
# безвреден — миграция сохраняется до него.
if [ -x "$IGATE_DIR/igate-mig/igate-mig" ]; then
sudo -u "$SVC_USER" bash -c '
export HOME='"$HOME_DIR"' XDG_DATA_HOME='"$HOME_DIR"'/.local/share XDG_RUNTIME_DIR=/run/user/'"$SVC_UID"'
dbus-run-session -- bash -c "
eval \$(printf %s\\\\n \"\$(cat '"$KEYRING_PASS_FILE"')\" | gnome-keyring-daemon --replace --unlock --components=secrets,pkcs11 2>/dev/null)
echo \"\" | timeout 30 '"$IGATE_DIR"'/igate-mig/igate-mig --data '"$HOME_DIR"' >/dev/null 2>&1 || true
"' 2>/dev/null || true
echo "igate-mig выполнен (флаг миграции)"
fi
log "9/9 Запуск и проверка"
systemctl start igate
OK=0
for i in $(seq 1 8); do
sleep 5
if ss -tlnp 2>/dev/null | grep -q ':8090'; then OK=1; break; fi
systemctl is-active --quiet igate || break
done
VER="$(python3 -c "import json;print([k for k in json.load(open('$IGATE_DIR/igate/igate.deps.json'))['libraries'] if k.lower().startswith('igate/')][0])" 2>/dev/null || true)"
STATE="$(curl -s http://localhost:8090/api/admin/engine/state 2>/dev/null || true)"
echo "версия: $VER"
echo "engine/state: ${STATE:-нет ответа}"
echo "8090: $(ss -tlnp 2>/dev/null | grep -c ':8090') слушатель"
if [ "$OK" = 1 ] && [ "$STATE" = '"Running"' ]; then
echo -e "\n✅ ИШ 107 запущен и работает."
else
cat <<MSG
⚠️ Web API 8090 не поднялся. Диагностика:
• лог движка: /var/lib/$SVC_USER/.local/share/NSD Integration Gateway/logs-svc/log.txt
(искать RefreshToken/Unable to start/fingerprint/HTTP)
• если 'CA fingerprint mismatch' — сервер покажет actual-отпечаток, вписать его
в wslTlsCACertFingerprint (не перепутать контур/крипту GOST↔RSA)
• если RefreshToken пустой — проверить wslEndpoint (должен быть КОРОТКИМ базовым)
Откат на предыдущую версию:
systemctl stop igate && rm -rf $IGATE_DIR &&
tar xzf $BK/opt-nsd-igate.tar.gz -C $(dirname "$IGATE_DIR") &&
printf '[Service]\nWorkingDirectory=$HOME_DIR\n' > $DROPIN_DIR/override.conf &&
systemctl daemon-reload && systemctl start igate
MSG
fi