feat: живой цикл M2M с НРД + мастер установки ключа на флешку
Инфраструктура 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>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// runPrechecks — все системные проверки на стадии "Проверка системы".
|
||||
// Возвращает срез результатов, по каждому видно ✓/✗ + объяснение.
|
||||
//
|
||||
// Ничего не модифицирует — просто читает /etc/os-release, проверяет
|
||||
// наличие нужных бинарей, права root, свободное место, артефакты в
|
||||
// artifactsDir и т.п. UI отрисовывает таблицей.
|
||||
func runPrechecks(artifactsDir string) []PrecheckResult {
|
||||
var out []PrecheckResult
|
||||
|
||||
out = append(out, checkRoot())
|
||||
out = append(out, checkArch())
|
||||
out = append(out, checkDistro())
|
||||
out = append(out, checkAptAvailable())
|
||||
out = append(out, checkSystemd())
|
||||
out = append(out, checkDiskSpace())
|
||||
out = append(out, checkArtifacts(artifactsDir))
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func checkRoot() PrecheckResult {
|
||||
if os.Geteuid() == 0 {
|
||||
return PrecheckResult{ID: "root", Title: "Запуск от root", OK: true}
|
||||
}
|
||||
return PrecheckResult{ID: "root", Title: "Запуск от root", OK: false, Message: "Требуется sudo"}
|
||||
}
|
||||
|
||||
func checkArch() PrecheckResult {
|
||||
if runtime.GOARCH == "amd64" {
|
||||
return PrecheckResult{ID: "arch", Title: "Архитектура amd64", OK: true, Message: runtime.GOARCH}
|
||||
}
|
||||
return PrecheckResult{ID: "arch", Title: "Архитектура amd64", OK: false, Message: "Валидата собрана только под amd64, у вас " + runtime.GOARCH}
|
||||
}
|
||||
|
||||
func checkDistro() PrecheckResult {
|
||||
id, pretty := readOSRelease()
|
||||
switch id {
|
||||
case "debian", "astra":
|
||||
return PrecheckResult{ID: "distro", Title: "Поддерживаемая ОС", OK: true, Message: pretty}
|
||||
case "ubuntu":
|
||||
return PrecheckResult{ID: "distro", Title: "Поддерживаемая ОС", OK: true, Message: pretty + " (поддерживается на свой страх)"}
|
||||
default:
|
||||
return PrecheckResult{ID: "distro", Title: "Поддерживаемая ОС", OK: false, Message: "ОС не в списке поддерживаемых: " + pretty}
|
||||
}
|
||||
}
|
||||
|
||||
func checkAptAvailable() PrecheckResult {
|
||||
if _, err := exec.LookPath("apt-get"); err != nil {
|
||||
return PrecheckResult{ID: "apt", Title: "Доступен apt-get", OK: false, Message: "apt-get не найден — это не Debian-семейство"}
|
||||
}
|
||||
return PrecheckResult{ID: "apt", Title: "Доступен apt-get", OK: true}
|
||||
}
|
||||
|
||||
func checkSystemd() PrecheckResult {
|
||||
if _, err := os.Stat("/run/systemd/system"); err != nil {
|
||||
return PrecheckResult{ID: "systemd", Title: "systemd работает", OK: false, Message: "/run/systemd/system нет"}
|
||||
}
|
||||
return PrecheckResult{ID: "systemd", Title: "systemd работает", OK: true}
|
||||
}
|
||||
|
||||
func checkDiskSpace() PrecheckResult {
|
||||
var fs syscall.Statfs_t
|
||||
if err := syscall.Statfs("/var", &fs); err != nil {
|
||||
return PrecheckResult{ID: "disk", Title: "Свободное место в /var", OK: false, Message: err.Error()}
|
||||
}
|
||||
freeBytes := fs.Bavail * uint64(fs.Bsize)
|
||||
freeGiB := freeBytes / (1 << 30)
|
||||
if freeGiB < 2 {
|
||||
return PrecheckResult{ID: "disk", Title: "Свободное место в /var", OK: false, Message: fmt.Sprintf("Свободно %d GiB, нужно ≥ 2", freeGiB)}
|
||||
}
|
||||
return PrecheckResult{ID: "disk", Title: "Свободное место в /var", OK: true, Message: fmt.Sprintf("%d GiB свободно", freeGiB)}
|
||||
}
|
||||
|
||||
func checkArtifacts(dir string) PrecheckResult {
|
||||
required := []struct {
|
||||
Glob string
|
||||
Name string
|
||||
}{
|
||||
{filepath.Join(dir, "ClientL_Other", "zpki-*.deb"), "zpki (Валидата)"},
|
||||
{filepath.Join(dir, "bj-server"), "bj-server (Go-бинарь)"},
|
||||
{filepath.Join(dir, "crypto-service.jar"), "crypto-service.jar"},
|
||||
}
|
||||
var missing []string
|
||||
for _, r := range required {
|
||||
matches, _ := filepath.Glob(r.Glob)
|
||||
if len(matches) == 0 {
|
||||
missing = append(missing, r.Name)
|
||||
}
|
||||
}
|
||||
if len(missing) > 0 {
|
||||
return PrecheckResult{
|
||||
ID: "artifacts",
|
||||
Title: "Артефакты дистрибутива",
|
||||
OK: false,
|
||||
Message: "Отсутствуют: " + strings.Join(missing, ", ") + " (положите в " + dir + ")",
|
||||
}
|
||||
}
|
||||
return PrecheckResult{ID: "artifacts", Title: "Артефакты дистрибутива", OK: true, Message: "Все на месте в " + dir}
|
||||
}
|
||||
|
||||
func readOSRelease() (id, pretty string) {
|
||||
b, err := os.ReadFile("/etc/os-release")
|
||||
if err != nil {
|
||||
return "", "неизвестно"
|
||||
}
|
||||
for _, line := range strings.Split(string(b), "\n") {
|
||||
k, v, ok := strings.Cut(line, "=")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
v = strings.Trim(v, `"`)
|
||||
switch k {
|
||||
case "ID":
|
||||
id = v
|
||||
case "PRETTY_NAME":
|
||||
pretty = v
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user