Первичная настройка, повторная проверка: копии без ключевых носителей СКЗИ (--one-file-system, без keymedia), без отпечатка железа и списка компонентов; восстановление на новый сервер — пароль базы bj из копии, база и пользователь ИШ; ключ для контура без канала запоминается и подключается при настройке канала; первый настроенный канал становится рабочим контуром; справочник сертификатов перечитывается после ключа и смены контура; шлюз НРД — шаг 7, ключ — шаг 8 (ключ ставится в профиль ИШ); подсказка контура ключа по сертификату; ИШ: параметры работающего шлюза не перезаписываются; без чужого кода отправителя и получателя по умолчанию; прокси для выхода в интернет; установка с образа без интернета; HTTPS — новый сертификат при смене адреса; bj-network — без cloud-init; проверка готовности: справочник участников, сетевые доступы, учётные записи, последний обмен с НРД

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-05 17:33:10 +03:00
parent 765d7b5994
commit 10305a095e
25 changed files with 634 additions and 95 deletions
+43 -3
View File
@@ -101,8 +101,41 @@ type flashDrive struct {
// keyWizardData — данные шаблона admin_keywizard.html.
type keyWizardData struct {
page
State *keyWizardState
Drives []flashDrive
State *keyWizardState
Drives []flashDrive
SuggestContour string // контур по сертификату в архиве: test3 (издатель «Тестовый УЦ») | prod | "" (не понятно)
SuggestIssuer string
}
// keyArchiveContour — контур ключа по сертификатам в распакованном архиве (не самоподписанным — это УЦ):
// издатель «Тестовый УЦ» — TEST3, иначе боевой. ГОСТ-сертификаты разбираются по TBS (parseNSDCert).
func keyArchiveContour(dir string) (contour, issuer string) {
_ = filepath.Walk(dir, func(p string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() || info.Size() > 64<<10 || contour != "" {
return nil
}
switch strings.ToLower(filepath.Ext(p)) {
case ".cer", ".crt", ".pem":
default:
return nil
}
raw, err := os.ReadFile(p)
if err != nil {
return nil
}
ci, _, err := parseNSDCert(raw)
if err != nil || ci.SelfSigned || ci.IssuerCN == "" {
return nil
}
issuer = ci.IssuerCN
if strings.Contains(strings.ToLower(ci.IssuerCN), "тестов") {
contour = "test3"
} else {
contour = "prod"
}
return nil
})
return contour, issuer
}
const keymediaMount = "/var/lib/igate/keymedia"
@@ -203,7 +236,11 @@ func (h *setupHandlers) renderKeyWizard(w http.ResponseWriter, r *http.Request)
if st.StagingID != "" && !st.Done {
drives = listFlashDrives()
}
render(w, h.tpl.a.keyWizard, keyWizardData{page: nowPage("Установка ключа", "setup"), State: st, Drives: drives})
d := keyWizardData{page: nowPage("Установка ключа", "setup"), State: st, Drives: drives}
if st.StagingID != "" && !st.Done {
d.SuggestContour, d.SuggestIssuer = keyArchiveContour(filepath.Join("/var/lib/bj/media/iso", st.StagingID))
}
render(w, h.tpl.a.keyWizard, d)
}
func (h *setupHandlers) keyWizardReset(w http.ResponseWriter, r *http.Request) {
@@ -384,6 +421,7 @@ func (h *setupHandlers) keyWizardInstall(w http.ResponseWriter, r *http.Request)
// Ключ уже на флешке и в ИШ — распаковка staging больше не нужна.
_ = os.RemoveAll(staging)
refreshCertStore(h.rc) // шаг «Сертификаты» и сроки — сразу по новому ключу, а не через 6 часов
final := "Готово! Ключ на флешке, справочник сформирован, ИШ перезапущен и работает."
if dev {
@@ -472,6 +510,8 @@ func igateRu(s string) string {
switch s {
case "connected":
return "сформирован, зарегистрирован и подключён к ИШ (cryptography.profile):"
case "pending-channel":
return "сформирован и зарегистрирован; канала этого контура в ИШ ещё нет — ключ подключится, когда вы настроите канал на шаге «Шлюз НРД»:"
case "ok":
return "сформирован и зарегистрирован (но не выбран в ИШ):"
case "skip":