Ключ: мастер не пишет «Готово» при ошибке; справочник подготовленной флешки — как есть; проверка подписи
- Мастер смотрел не на итог установщика, а ставил галочки подряд: при «ошибке пересборки» и несформированном профиле ИШ показывал «Готово». Теперь этап с ошибкой — красный, причина — в сообщении, «Готово» — только когда справочник собран, профиль ИШ создан и ключ подписывает (оба пути — флешка и архив). - Подготовленная флешка: справочник на ней уже совместимый (пересобран при первой установке) — если пересборка не удалась, берётся как есть (gdbm cf9a5713; архивный НРД ce9a5713 — только с пересборкой). - В конце установки — проверка под igate: ключ подписывает проверочный документ профилем ИШ; не подписывает — понятная ошибка («вставлена ли флешка?»). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
{{if $s.Done}}
|
||||
<div class="card" style="background:var(--ok-weak)">
|
||||
<h2>✓ Готово</h2>
|
||||
<p>Ключ установлен на флешку, справочник сертификатов сформирован, Валидата проверена.</p>
|
||||
<p>{{if $s.MediaDevice}}Ключ с флешки подключён к шлюзу НРД как есть и подписывает — флешка не менялась.{{else}}Ключ записан на флешку, справочник сертификатов сформирован, ключ подписывает.{{end}}</p>
|
||||
{{if $s.Backup}}<p class="muted">Бэкап прежнего носителя: <code>{{$s.Backup}}</code></p>{{end}}
|
||||
<div style="display:flex;gap:8px;margin-top:12px;flex-wrap:wrap">
|
||||
{{if devOn}}<form method="post" action="/admin/setup/test-nsd" style="margin:0">
|
||||
|
||||
Reference in New Issue
Block a user