From e7d81ea2a98f76341a99e5e0decef2ac31cf31e5 Mon Sep 17 00:00:00 2001 From: zuevav Date: Tue, 6 Oct 2026 18:35:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BB=D1=8E=D1=87:=20=D0=B4=D0=B2=D0=B0?= =?UTF-8?q?=20=D0=BF=D1=83=D1=82=D0=B8=20=E2=80=94=20=C2=AB=D0=9F=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B8=D1=82=D1=8C=20=D1=84=D0=BB?= =?UTF-8?q?=D0=B5=D1=88=D0=BA=D1=83=20=D1=81=20=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=BE=D0=BC=C2=BB=20=D0=B8=D0=BB=D0=B8=20=C2=AB=D0=A1=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=20=D0=BD=D0=B0=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=20=D1=84=D0=BB=D0=B5=D1=88=D0=BA=D0=B5=C2=BB;=20?= =?UTF-8?q?=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BE=D0=B4=D0=BD=D0=B8=D0=BC=20=D0=B7=D0=B0=D1=85=D0=BE=D0=B4?= =?UTF-8?q?=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Шаг «Ключ подписи» начинается с вопроса «Где ваш ключ?»: подключить подготовленную флешку (bj находит на ней ключ и подключает как есть) или сформировать ключ на новой флешке (архив НРД и пароль → распаковка → bj ждёт чистую флешку; без флешки записи нет — «вставьте и обновите страницу»). Этапы показываются, когда путь выбран, — свои у каждого пути. - Обновление больше не делится на два захода, когда вместе с bj обновляется и установщик обновлений: откладывание bj-installer нужно только установщикам старше 25.09.2026, которые его не знают. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi --- internal/lkgateway/keywizard.go | 6 +- internal/lkgateway/onboarding_test.go | 9 ++- internal/lkgateway/updater.go | 11 ++- .../lkgateway/web/templates/part_keywiz.html | 77 +++++++++++++------ 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/internal/lkgateway/keywizard.go b/internal/lkgateway/keywizard.go index 08c27f1..b491f96 100644 --- a/internal/lkgateway/keywizard.go +++ b/internal/lkgateway/keywizard.go @@ -74,7 +74,7 @@ func defaultKeySteps() []keyWizardStep { } return []keyWizardStep{ {Title: "Загрузка архива и распаковка", Status: "pending"}, - {Title: "Запись ключа на выбранную флешку (с бэкапом)", Status: "pending"}, + {Title: "Запись ключа на новую флешку (копия прежнего содержимого — на сервере)", Status: "pending"}, {Title: "Формирование справочника сертификатов (CRL)", Status: "pending"}, {Title: "Перезапуск и проверка ИШ", Status: "pending"}, {Title: last, Status: "pending"}, @@ -377,8 +377,8 @@ func (h *setupHandlers) keyWizardFromMedia(w http.ResponseWriter, r *http.Reques h.keyWiz.StagingID, h.keyWiz.VDK = id, vdk h.keyWiz.MediaDevice, h.keyWiz.MediaProfile = drive.Device, prof // флешка уже подготовлена: используется как есть — этапы называются по-другому, записи на флешку нет - h.keyWiz.Steps[0].Title = "Ключ найден на подготовленной флешке" - h.keyWiz.Steps[1].Title = "Флешка подключается как есть — на неё ничего не записывается" + h.keyWiz.Steps[0].Title = "Поиск ключа на флешке" + h.keyWiz.Steps[1].Title = "Подключение флешки к шлюзу как есть — на неё ничего не записывается" h.keyWiz.Steps[2].Title = "Справочник сертификатов для ИШ — на диске сервера" h.keyWiz.set(0, "ok", fmt.Sprintf("Ключ найден на флешке %s: %s, справочник %s%s", fallback(drive.Model, drive.Device), vdk, spr, prefixed(", профиль ", prof))) h.keyWiz.set(1, "active", "") diff --git a/internal/lkgateway/onboarding_test.go b/internal/lkgateway/onboarding_test.go index a2f4f5f..d6481c7 100644 --- a/internal/lkgateway/onboarding_test.go +++ b/internal/lkgateway/onboarding_test.go @@ -466,11 +466,18 @@ func TestDumpOnboardingPages(t *testing.T) { // шаг «Ключ подписи»: ключ найден на подготовленной флешке — используется как есть h.keyWiz = newKeyWizardState() h.keyWiz.StagingID, h.keyWiz.VDK, h.keyWiz.MediaDevice, h.keyWiz.MediaProfile = "media-test", "CKJCI7AYNIOSNLXK.vdk", "/dev/sdb1", "PrUser1046" - h.keyWiz.Steps[0].Title, h.keyWiz.Steps[1].Title = "Ключ найден на подготовленной флешке", "Флешка подключается как есть — на неё ничего не записывается" + h.keyWiz.Steps[0].Title, h.keyWiz.Steps[1].Title = "Поиск ключа на флешке", "Подключение флешки к шлюзу как есть — на неё ничего не записывается" h.keyWiz.set(0, "ok", "Ключ найден на флешке USB2FlashStorage: CKJCI7AYNIOSNLXK.vdk, справочник spr1046, профиль PrUser1046") wk := httptest.NewRecorder() h.renderWizard(wk, httptest.NewRequest(http.MethodGet, "/admin/wizard?step=8", nil)) _ = os.WriteFile(filepath.Join(dir, "wizard-08-media.html"), wk.Body.Bytes(), 0o644) + // путь «новая флешка»: архив распакован, ждём флешку + h.keyWiz = newKeyWizardState() + h.keyWiz.StagingID, h.keyWiz.VDK = "test-archive", "CKJCI7AYNIOSNLXK.vdk" + h.keyWiz.set(0, "ok", "Ключ CKJCI7AYNIOSNLXK.vdk, справочник spr1046") + wn := httptest.NewRecorder() + h.renderWizard(wn, httptest.NewRequest(http.MethodGet, "/admin/wizard?step=8", nil)) + _ = os.WriteFile(filepath.Join(dir, "wizard-08-new.html"), wn.Body.Bytes(), 0o644) h.keyWiz = nil // шаг QUIK после проверки подключения — выбор «Как bj работает с QUIK» q := rc.Snapshot().Quik diff --git a/internal/lkgateway/updater.go b/internal/lkgateway/updater.go index 7aa6ccc..a7d23ef 100644 --- a/internal/lkgateway/updater.go +++ b/internal/lkgateway/updater.go @@ -42,6 +42,9 @@ const updateStagingDir = "/var/lib/bj/update-staging" // DefaultUpdateURL — сервер обновлений по умолчанию (встроен в сервер лицензий). const DefaultUpdateURL = "https://lic.zetit.ru/updates" +// installerKnowsAll — с этой версии root-установщик обновлений знает bj-installer и ставит выделенные модули. +const installerKnowsAll = "2026.09.25" + type Updater struct{ rc *RuntimeConfig } func NewUpdater(rc *RuntimeConfig) *Updater { return &Updater{rc: rc} } @@ -287,11 +290,13 @@ func (u *Updater) applyUpdate(ctx context.Context, names []string) (string, erro } return "", fmt.Errorf("нечего обновлять: все установленные компоненты актуальны (релиз %s)", m.Version) } - // Прежний root-установщик не умеет впервые ставить выделенные из ядра модули: пока он сам не - // обновлён, такие модули откладываются — их поставит ensureSplitModules после перезапуска. + // Очень старый root-установщик (до 25.09.2026) не знает bj-installer и не ставит впервые выделенные + // из ядра модули: пока он сам не обновлён, такие компоненты откладываются (второй заход). Установщик + // новее этого умеет всё — обновление одним заходом, даже если вместе с ним обновляется и он сам + // (раньше любое его обновление делило установку на два раза: «скачал 24 МБ — снова „Обновить“ — ещё 6»). installerOutdated := false for _, c := range plan { - if c.Name == "bj-component-install" && c.Update { + if c.Name == "bj-component-install" && c.Update && (c.Installed == "" || release.IsNewer(installerKnowsAll, c.Installed)) { installerOutdated = true } } diff --git a/internal/lkgateway/web/templates/part_keywiz.html b/internal/lkgateway/web/templates/part_keywiz.html index 06f71e7..775d5ac 100644 --- a/internal/lkgateway/web/templates/part_keywiz.html +++ b/internal/lkgateway/web/templates/part_keywiz.html @@ -5,7 +5,19 @@ {{define "keyWizBody"}} {{$s := .State}} -{{/* ===== Лента шагов ===== */}} + +{{/* ===== Лента шагов — когда путь выбран (флешка с ключом или новая флешка из архива) ===== */}} +{{if or $s.StagingID $s.Done}}
    {{range $i, $step := $s.Steps}} @@ -27,6 +39,7 @@
{{/* ===== Действие в зависимости от состояния ===== */}} +{{end}} {{if $s.Done}}

✓ Готово

@@ -68,10 +81,12 @@ {{else if $s.StagingID}} {{/* Архив загружен — выбор флешки + запись */}}
-

Шаг 2 — выбор флешки и запись

+

Шаг 2 — вставьте новую флешку и запишите ключ

Архив распакован. Ключ: {{fallbackTpl $s.VDK "—"}}. - Выберите носитель — запись сделает бэкап, запишет ключ и справочник - сертификатов, дотянет CRL и перезапустит ИШ.

+ Вставьте в сервер чистую флешку — на неё запишется ключ и справочник сертификатов, затем bj + подключит её к шлюзу и перезапустит ИШ. Копия прежнего содержимого флешки сохраняется на сервере. + Не используйте флешку с рабочим ключом другого сервера.

+ {{if not .Drives}}

Флешка не найдена — вставьте её в сервер и обновите страницу.

{{else}}
{{template "keyWizRet" .}} @@ -90,8 +105,6 @@ {{end}} - {{else}} -

Съёмные носители не обнаружены — будет использован текущий ключевой носитель ИШ по умолчанию.

{{end}}
@@ -111,40 +124,54 @@ Пусто = имя берётся из архива автоматически.
- - + + {{end}}
{{template "keyWizRet" .}} - +
{{else}} - {{/* Начало — форма загрузки */}} + {{/* Начало: где ключ — на подготовленной флешке или в архиве НРД (тогда — на новую флешку) */}}
-

Шаг 1 — откуда взять ключ

-

Архив от НРД: выберите .7z-архив с ключом и введите пароль архива.

-
- {{template "keyWizRet" .}} - - - -
-
-

У меня уже есть подготовленная флешка — использовать ключ с неё (например, флешка с другого сервера bj). Флешка используется как есть: bj её только читает, ничего на неё не записывает. Архив не нужен.

+

Где ваш ключ?

+
+ + +
+ +
{{if .Drives}}
{{template "keyWizRet" .}} +

Флешка с ключом:

{{range $i, $d := .Drives}} -
+ +
+ {{end}} {{end}}