ИШ ждёт флешку с ключом — bj это видит и перезапускает шлюз сам; итог установки ключа; список копий; скрытые блоки

- ИШ без флешки ждёт её в окне Валидаты («Вставьте ключевой носитель»): статус «ждёт флешку», без кнопки
  переустановки; сторож не тратит перезапуски, а когда флешка появилась — перезапускает ИШ сам; письмо
- шаг ключа: итог — карточка «Ключ подключён», «Заменить ключ» вместо «Установить ещё один», этапы свёрнуты
- копии: «Копии на хранилище» ищет там же, куда ложится копия (подпапка по умолчанию bj-backup, не из старых
  настроек); поля показываются разобранными
- [hidden] прячет всегда (пустая полоска под версией ИШ); «Шлюз НРД на другом сервере?» — что это за адрес

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-10-07 00:11:48 +03:00
parent 5abf71e3ed
commit c62225dd7d
10 changed files with 86 additions and 21 deletions
+40
View File
@@ -18,6 +18,8 @@ import (
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"sync"
"time"
@@ -45,6 +47,9 @@ type igwWatchState struct {
LastRestart time.Time
LastRemind time.Time
RestartMsg string
// KeyWait — ИШ ждёт флешку с ключом подписи (окно Валидаты «Вставьте ключевой носитель»): перезапуск не
// поможет, пока её нет, а когда она появится — bj перезапустит ИШ сам.
KeyWait bool
}
var igwWatch igwWatchState
@@ -155,6 +160,23 @@ func igwWatchTick(ctx context.Context, rc *RuntimeConfig) {
needAlert := !w.Alerted && down >= igwAlertAfter
canRestart := igwLocal(base) && down >= igwAlertAfter && w.Restarts < igwRestartMax &&
(w.LastRestart.IsZero() || now.Sub(w.LastRestart) >= igwRestartEvery)
keyAlert := false
if igwLocal(base) {
switch keymediaState() {
case "missing": // без флешки ИШ ждёт её в окне Валидаты — перезапуски бесполезны
canRestart = false
if !w.KeyWait {
w.KeyWait, keyAlert = true, true
needAlert = false
w.Alerted, w.LastRemind = true, now
}
case "ok":
if w.KeyWait { // флешку вернули — перезапустить ИШ сразу, попытки — заново
w.KeyWait, w.Restarts, w.LastRestart = false, 0, time.Time{}
canRestart = true
}
}
}
remind := w.Alerted && !canRestart && w.Restarts >= igwRestartMax && now.Sub(w.LastRemind) >= igwRemindEvery
if needAlert {
w.Alerted, w.LastRemind = true, now
@@ -169,6 +191,9 @@ func igwWatchTick(ctx context.Context, rc *RuntimeConfig) {
attempt, since, lastErr := w.Restarts, w.DownSince, w.LastErr
w.mu.Unlock()
if keyAlert {
raiseSystemAlert(rc, "ИШ НРД ждёт флешку с ключом подписи", fmt.Sprintf("Интеграционный шлюз НРД не запускается: флешки с ключом подписи в сервере нет (%s пуста) — Валидата ждёт ключевой носитель. Вставьте флешку с ключом в этот сервер: bj перезапустит шлюз сам. Переустанавливать ИШ не нужно.", keymediaDir))
}
if needAlert {
plan := "ИШ на другом сервере — перезапустите службу ИШ там."
if igwLocal(base) {
@@ -186,6 +211,21 @@ func igwWatchTick(ctx context.Context, rc *RuntimeConfig) {
}
}
// keymediaDir — куда подключается флешка с ключом для ИШ (bj-keymedia-install, строка fstab по UUID).
const keymediaDir = "/var/lib/igate/keymedia"
// keymediaState — флешка с ключом для ИШ: "" — не настроена (ключ не с флешки), "ok" — на месте, "missing" — нет.
func keymediaState() string {
b, err := os.ReadFile("/etc/fstab")
if err != nil || !strings.Contains(string(b), " "+keymediaDir+" ") {
return ""
}
if m, _ := filepath.Glob(keymediaDir + "/vdkeys/*.vdk"); len(m) > 0 {
return "ok"
}
return "missing"
}
// igwTryRestart — перезапуск службы ИШ и проверка, поднялся ли он.
func igwTryRestart(rc *RuntimeConfig, base string, attempt int) {
log.Printf("igw-watch: перезапуск службы %s (попытка %d из %d)", igwServiceUnit, attempt, igwRestartMax)