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>
133 lines
4.7 KiB
Go
133 lines
4.7 KiB
Go
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
|
|
}
|