From fb2fc155694c9a14ff4048e49bf978d94b5ae4f2 Mon Sep 17 00:00:00 2001 From: zuevav Date: Tue, 6 Oct 2026 18:41:10 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BB=D1=8E=D1=87:=20=D0=BC=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D0=B5=D1=80=20=D0=BD=D0=B5=20=D0=BF=D0=B8=D1=88=D0=B5?= =?UTF-8?q?=D1=82=20=C2=AB=D0=93=D0=BE=D1=82=D0=BE=D0=B2=D0=BE=C2=BB=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B5;=20?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=BE=D0=B9=20=D1=84=D0=BB=D0=B5=D1=88=D0=BA=D0=B8?= =?UTF-8?q?=20=E2=80=94=20=D0=BA=D0=B0=D0=BA=20=D0=B5=D1=81=D1=82=D1=8C;?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=BF=D0=B8=D1=81=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Мастер смотрел не на итог установщика, а ставил галочки подряд: при «ошибке пересборки» и несформированном профиле ИШ показывал «Готово». Теперь этап с ошибкой — красный, причина — в сообщении, «Готово» — только когда справочник собран, профиль ИШ создан и ключ подписывает (оба пути — флешка и архив). - Подготовленная флешка: справочник на ней уже совместимый (пересобран при первой установке) — если пересборка не удалась, берётся как есть (gdbm cf9a5713; архивный НРД ce9a5713 — только с пересборкой). - В конце установки — проверка под igate: ключ подписывает проверочный документ профилем ИШ; не подписывает — понятная ошибка («вставлена ли флешка?»). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi --- deploy/linux/sbin/bj-keymedia-install | 24 ++++++++++++-- internal/lkgateway/keywizard.go | 33 ++++++++++++++++++- internal/lkgateway/onboarding_test.go | 20 +++++++++++ .../lkgateway/web/templates/part_keywiz.html | 2 +- 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/deploy/linux/sbin/bj-keymedia-install b/deploy/linux/sbin/bj-keymedia-install index 96e4d71..667589c 100755 --- a/deploy/linux/sbin/bj-keymedia-install +++ b/deploy/linux/sbin/bj-keymedia-install @@ -224,9 +224,17 @@ if [ -n "$SPRNAME" ] && [ -x "$REBUILD" ] && [ -f "$FLASH_SPR/local.pse" ]; then sync fi +# флешка уже подготовлена (use-media): её справочник совместим — пересобран при первой установке; пересборка +# не удалась (ключ подписи справочника не загрузился) — взять его как есть. Совместимый gdbm начинается с cf9a5713, +# архивный НРД — с ce9a5713 (его без пересборки ИШ не читает). +if [ "$NOWRITE" = 1 ] && [ "$REBUILD_RES" != ok ] && [ -f "$FLASH_SPR/local.gdbm" ] && \ + [ "$(head -c4 "$FLASH_SPR/local.gdbm" | od -An -tx1 | tr -d ' \n')" = cf9a5713 ]; then + REBUILD_RES="as-is" +fi + # ---- сформировать профиль для ИШ (стораны на диске, ключ остаётся на флешке) ---- IGATE_RES="skip" -if [ "$REBUILD_RES" = "ok" ] && [ -d "$(dirname "$IGATE_PROFILES")" ]; then +if { [ "$REBUILD_RES" = "ok" ] || [ "$REBUILD_RES" = "as-is" ]; } && [ -d "$(dirname "$IGATE_PROFILES")" ]; then IGP="$IGATE_PROFILES/$PROFILE" rm -rf "$IGP"; mkdir -p "$IGP" cp -f "$FLASH_SPR/local.pse" "$FLASH_SPR/local.gdbm" "$IGP"/ 2>/dev/null @@ -293,6 +301,16 @@ PY fi fi +# ---- проверка: ключ подписывает под igate (как будет подписывать ИШ) — проверочный документ профилем ---- +KEYCHECK="skip" +if [ "$IGATE_RES" = connected ] || [ "$IGATE_RES" = pending-channel ]; then + KT=$(mktemp -d); echo "bj key check" > "$KT/in"; chown -R igate:igate "$KT" + KO=$(timeout -k 5 60 runuser -u igate -- env HOME=/var/lib/igate LD_LIBRARY_PATH="$VDLIB" "$ZPKI" -sign -profile "$PROFILE" -registry -in "$KT/in" -out "$KT/out.p7s" 2>&1) + if [ -s "$KT/out.p7s" ]; then KEYCHECK=ok + else KEYCHECK="fail: $(printf '%s' "$KO" | grep -iE 'ошибк|результат|error' | head -1 | tr -d '"\\' | head -c 200)"; fi + rm -rf "$KT" +fi + finish; trap - EXIT -printf '{"ok":true,"profile":"%s","spr":"%s","vdk":"%s","backup":"%s","target":"%s","rebuild":"%s","igate":"%s","igate_profile_dir":"%s","keymedia":"%s","nowrite":%s}\n' \ - "$PROFILE" "$SPRNAME" "$VDK_NAME" "$BACKUP" "$TARGET_MNT" "$REBUILD_RES" "$IGATE_RES" "$IGATE_PROFILES/$PROFILE" "$KEYMEDIA_UUID" "$([ "$NOWRITE" = 1 ] && echo true || echo false)" +printf '{"ok":true,"profile":"%s","spr":"%s","vdk":"%s","backup":"%s","target":"%s","rebuild":"%s","igate":"%s","igate_profile_dir":"%s","keymedia":"%s","nowrite":%s,"keycheck":"%s"}\n' \ + "$PROFILE" "$SPRNAME" "$VDK_NAME" "$BACKUP" "$TARGET_MNT" "$REBUILD_RES" "$IGATE_RES" "$IGATE_PROFILES/$PROFILE" "$KEYMEDIA_UUID" "$([ "$NOWRITE" = 1 ] && echo true || echo false)" "$KEYCHECK" diff --git a/internal/lkgateway/keywizard.go b/internal/lkgateway/keywizard.go index b491f96..9e9395a 100644 --- a/internal/lkgateway/keywizard.go +++ b/internal/lkgateway/keywizard.go @@ -312,7 +312,13 @@ func (h *setupHandlers) keyWizardUseMedia(w http.ResponseWriter, r *http.Request rebuild, _ := res["rebuild"].(string) igate, _ := res["igate"].(string) h.keyWiz.set(1, "ok", "Флешка "+dev+" подключена к ИШ только для чтения — на неё ничего не записано") - h.keyWiz.set(2, "ok", fmt.Sprintf("Справочник для ИШ собран на диске (%s); профиль «%s» %s", rebuildRu(rebuild), h.keyWiz.Profile, igateRu(igate))) + if bad := keyInstallProblem(res); bad != "" { + h.keyWiz.set(2, "error", bad) + h.keyWiz.mu.Unlock() + h.keyWizFlash(w, r, "Ключ с флешки не подключён: "+bad) + return + } + h.keyWiz.set(2, "ok", fmt.Sprintf("Справочник для ИШ (%s); профиль «%s» %s ключ подписывает", rebuildRu(rebuild), h.keyWiz.Profile, igateRu(igate))) h.keyWiz.set(3, "active", "") h.keyWiz.mu.Unlock() @@ -539,6 +545,12 @@ func (h *setupHandlers) keyWizardInstall(w http.ResponseWriter, r *http.Request) rebuild, _ := res["rebuild"].(string) igate, _ := res["igate"].(string) igp, _ := res["igate_profile_dir"].(string) + if bad := keyInstallProblem(res); bad != "" { + h.keyWiz.set(2, "error", bad) + h.keyWiz.mu.Unlock() + h.keyWizFlash(w, r, "Ключ записан на флешку, но не подключён: "+bad) + return + } h.keyWiz.set(2, "ok", fmt.Sprintf("Справочник «%s» пересобран (%s); профиль ИШ %s %s", fallback(spr, "—"), rebuildRu(rebuild), igateRu(igate), igp)) h.keyWiz.set(3, "active", "") @@ -639,10 +651,29 @@ func crlRu(s string) string { } // rebuildRu — статус пересборки справочника сертификатов на флешке. +// keyInstallProblem — что не так в итоге установщика ключа (пусто — ключ подключён и подписывает). +// Раньше мастер ставил галочки по порядку, даже если справочник не собрался и профиль ИШ не создан. +func keyInstallProblem(res map[string]any) string { + rebuild, _ := res["rebuild"].(string) + igate, _ := res["igate"].(string) + check, _ := res["keycheck"].(string) + switch { + case rebuild != "ok" && rebuild != "as-is": + return "справочник сертификатов не собран — " + rebuildRu(rebuild) + case igate != "connected" && igate != "pending-channel": + return "профиль ИШ не сформирован — " + strings.TrimSuffix(igateRu(igate), ":") + case strings.HasPrefix(check, "fail"): + return "ключ не подписывает: " + strings.TrimPrefix(check, "fail: ") + " — вставлена ли флешка с ключом?" + } + return "" +} + func rebuildRu(s string) string { switch { case s == "ok": return "совместимый формат, сертификаты извлечены из архива" + case s == "as-is": + return "справочник с флешки уже совместимый — взят как есть" case s == "skip": return "пропущено" case strings.HasPrefix(s, "fail"): diff --git a/internal/lkgateway/onboarding_test.go b/internal/lkgateway/onboarding_test.go index d6481c7..20eb9fe 100644 --- a/internal/lkgateway/onboarding_test.go +++ b/internal/lkgateway/onboarding_test.go @@ -790,3 +790,23 @@ func TestKeyWizBack(t *testing.T) { } } } + +// Итог установщика ключа: мастер не ставит галочки, если справочник не собран, профиль ИШ не создан +// или ключ не подписывает (раньше — «Готово» при ошибке пересборки). +func TestKeyInstallProblem(t *testing.T) { + for _, c := range []struct { + res map[string]any + want string + }{ + {map[string]any{"rebuild": "ok", "igate": "connected", "keycheck": "ok"}, ""}, + {map[string]any{"rebuild": "as-is", "igate": "pending-channel", "keycheck": "ok"}, ""}, + {map[string]any{"rebuild": "fail: crestor: Ошибка загрузки ключа ЭП", "igate": "skip"}, "справочник"}, + {map[string]any{"rebuild": "ok", "igate": "skip"}, "профиль ИШ"}, + {map[string]any{"rebuild": "ok", "igate": "connected", "keycheck": "fail: E0D5"}, "не подписывает"}, + } { + got := keyInstallProblem(c.res) + if (c.want == "") != (got == "") || !strings.Contains(got, c.want) { + t.Errorf("%v: %q, ожидалось %q", c.res, got, c.want) + } + } +} diff --git a/internal/lkgateway/web/templates/part_keywiz.html b/internal/lkgateway/web/templates/part_keywiz.html index 775d5ac..5dc71cd 100644 --- a/internal/lkgateway/web/templates/part_keywiz.html +++ b/internal/lkgateway/web/templates/part_keywiz.html @@ -43,7 +43,7 @@ {{if $s.Done}}

✓ Готово

-

Ключ установлен на флешку, справочник сертификатов сформирован, Валидата проверена.

+

{{if $s.MediaDevice}}Ключ с флешки подключён к шлюзу НРД как есть и подписывает — флешка не менялась.{{else}}Ключ записан на флешку, справочник сертификатов сформирован, ключ подписывает.{{end}}

{{if $s.Backup}}

Бэкап прежнего носителя: {{$s.Backup}}

{{end}}
{{if devOn}}