9737c787f9
Инфраструктура M2M (живой обмен с НРД через ИШ): - обработка M2MTransferResponse: ERROR(M2Mxx) → заявка Отклонена, сохранение ответа; INFO → ждём Decision; идемпотентность поллера - fallback-корреляция ответов с нулевым GUID (M2M14/M2M17) по FIFO - сырой XML ответа НРД в карточке заявки (для пересылки в ТП) - тестовый пакет роботу приведён к эталону m2m_robot_samples (CostInfo=Yes, 4 бумаги, IsolationStatus, DocumentSeries=сценарий); override паспорта - редирект из теста сразу в карточку заявки Мастер установки ключа Валидаты на флешку (admin/setup/keywizard): - пошаговый: загрузка .7z+пароль → выбор флешки → запись → справочник сертификатов (CRL) → перезапуск+проверка ИШ → готово - привилегированный воркер (bj-keymedia) в host-namespace через файл-обмен, bj-server остаётся в песочнице - сохранение структуры профиля архива (spr<N>), перечисление съёмных USB Прочее: - пакет-доказательство для ТП НРД + форма регистрации участника M2M - эталонные образцы робота (DOC/m2m_robot_samples) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
112 lines
3.8 KiB
Go
112 lines
3.8 KiB
Go
// Package main — bj-installer.
|
|
//
|
|
// Web-инсталлятор для bj-server: на машине клиента после установки
|
|
// Debian/Astra поднимает локальный HTTP на 127.0.0.1:8181, проводит
|
|
// через 5-страничный wizard (welcome → precheck → config → install → done)
|
|
// и за кадром выполняет 20+ шагов установки Валидаты + bj-server + ИШ.
|
|
//
|
|
// Прогресс шагов прилетает в UI через Server-Sent Events. Каждый шаг
|
|
// идемпотентен — можно повторно запускать инсталлятор на уже настроенной
|
|
// машине, он пропустит то, что сделано.
|
|
//
|
|
// Запуск: sudo ./bj-installer [--addr 127.0.0.1:8181] [--no-browser]
|
|
// Артефакты ожидаются рядом с бинарём в каталоге ./artifacts/:
|
|
//
|
|
// artifacts/ClientL_Other/zpki-*.deb
|
|
// artifacts/ClientL_Other/zsdk-*.deb
|
|
// artifacts/bj-server (Go-бинарь)
|
|
// artifacts/crypto-service.jar (Java-сайдкар)
|
|
// artifacts/ish/igate_*.deb (ИШ НРД)
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"runtime"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
const banner = `
|
|
======================================================================
|
|
bj-installer — мастер установки Bridge-and-Join-s
|
|
======================================================================
|
|
`
|
|
|
|
func main() {
|
|
addr := flag.String("addr", "127.0.0.1:8181", "адрес web-инсталлятора")
|
|
noBrowser := flag.Bool("no-browser", false, "не пытаться открыть браузер автоматически")
|
|
artifactsDir := flag.String("artifacts", "./artifacts", "каталог с дистрибутивами (Validata deb, bj-server, ish)")
|
|
flag.Parse()
|
|
|
|
if os.Geteuid() != 0 {
|
|
fmt.Fprintln(os.Stderr, "Установщик должен быть запущен от root (sudo).")
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Print(banner)
|
|
fmt.Printf(" адрес: http://%s\n", *addr)
|
|
fmt.Printf(" артефакты: %s\n", *artifactsDir)
|
|
fmt.Println("======================================================================")
|
|
|
|
st := newState(*artifactsDir)
|
|
|
|
srv := newServer(st)
|
|
httpSrv := &http.Server{
|
|
Addr: *addr,
|
|
Handler: srv,
|
|
ReadHeaderTimeout: 10 * time.Second,
|
|
}
|
|
|
|
// SIGINT/SIGTERM → корректный shutdown
|
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
defer stop()
|
|
|
|
go func() {
|
|
if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
log.Fatalf("HTTP-сервер упал: %v", err)
|
|
}
|
|
}()
|
|
|
|
url := "http://" + *addr
|
|
log.Printf("Откройте в браузере: %s", url)
|
|
if !*noBrowser {
|
|
tryOpenBrowser(url)
|
|
}
|
|
|
|
<-ctx.Done()
|
|
log.Println("Завершаем работу...")
|
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
_ = httpSrv.Shutdown(shutdownCtx)
|
|
}
|
|
|
|
// tryOpenBrowser — без фанатизма. Если xdg-open/sensible-browser есть и
|
|
// $DISPLAY поднят (xrdp, Fly DE) — откроем. Иначе пользователь увидит URL
|
|
// в выводе и перейдёт сам с другого компа (типичный сценарий headless).
|
|
func tryOpenBrowser(url string) {
|
|
if os.Getenv("DISPLAY") == "" && os.Getenv("WAYLAND_DISPLAY") == "" {
|
|
return
|
|
}
|
|
var bin string
|
|
switch runtime.GOOS {
|
|
case "linux":
|
|
for _, cand := range []string{"xdg-open", "sensible-browser", "x-www-browser"} {
|
|
if p, err := exec.LookPath(cand); err == nil {
|
|
bin = p
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if bin == "" {
|
|
return
|
|
}
|
|
_ = exec.Command(bin, url).Start()
|
|
}
|