Образ на Ubuntu 22.04 LTS (автоустановка) со встроенной СКЗИ «Валидата Клиент L»: сборщик build-iso-ubuntu.sh, шаг установщика «СКЗИ Валидата» (из комплекта образа, с совместимой libldap 2.4), установщик принимает Ubuntu 22.04
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -144,6 +144,7 @@ func (in *installer) run() error {
|
|||||||
all := []step{
|
all := []step{
|
||||||
{"precheck", "Проверка системы", in.stepPrecheck},
|
{"precheck", "Проверка системы", in.stepPrecheck},
|
||||||
{"packages", "Системные пакеты", in.stepPackages},
|
{"packages", "Системные пакеты", in.stepPackages},
|
||||||
|
{"validata", "СКЗИ «Валидата Клиент L»", in.stepValidata},
|
||||||
{"system", "Пользователь bj и каталоги", in.stepSystem},
|
{"system", "Пользователь bj и каталоги", in.stepSystem},
|
||||||
{"license", "Активация лицензии", in.stepLicense},
|
{"license", "Активация лицензии", in.stepLicense},
|
||||||
{"database", "База данных PostgreSQL", in.stepDatabase},
|
{"database", "База данных PostgreSQL", in.stepDatabase},
|
||||||
@@ -203,9 +204,10 @@ func (in *installer) stepPrecheck() (string, error) {
|
|||||||
name := pick(osr["PRETTY_NAME"], id+" "+ver)
|
name := pick(osr["PRETTY_NAME"], id+" "+ver)
|
||||||
switch {
|
switch {
|
||||||
case id == "debian" && strings.HasPrefix(ver, "13"):
|
case id == "debian" && strings.HasPrefix(ver, "13"):
|
||||||
|
case id == "ubuntu" && strings.HasPrefix(ver, "22.04"):
|
||||||
case id == "astra" || strings.Contains(like, "astra") || strings.Contains(strings.ToLower(name), "astra"):
|
case id == "astra" || strings.Contains(like, "astra") || strings.Contains(strings.ToLower(name), "astra"):
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("поддерживаются Debian 13 и Astra Linux, а на сервере %s", name)
|
return "", fmt.Errorf("поддерживаются Ubuntu 22.04, Debian 13 и Astra Linux, а на сервере %s", name)
|
||||||
}
|
}
|
||||||
if runtime.GOARCH != "amd64" {
|
if runtime.GOARCH != "amd64" {
|
||||||
return "", fmt.Errorf("нужна архитектура x86_64, а на сервере %s", runtime.GOARCH)
|
return "", fmt.Errorf("нужна архитектура x86_64, а на сервере %s", runtime.GOARCH)
|
||||||
@@ -667,6 +669,37 @@ func (in *installer) componentsFromBundle() (string, error) {
|
|||||||
return detail, nil
|
return detail, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validataDir — пакеты «Валидата Клиент L», положенные образом ISO (zpki, zsdk и совместимая libldap-2.4-2).
|
||||||
|
const validataDir = "/var/lib/bj/validata"
|
||||||
|
|
||||||
|
// stepValidata — ставит СКЗИ «Валидата Клиент L» из комплекта образа, если её ещё нет.
|
||||||
|
func (in *installer) stepValidata() (string, error) {
|
||||||
|
if out, err := run("dpkg-query", "-W", "-f", "${Version}", "zpki"); err == nil && strings.TrimSpace(out) != "" {
|
||||||
|
return "уже установлена, версия " + strings.TrimSpace(out), nil
|
||||||
|
}
|
||||||
|
debs, _ := filepath.Glob(in.P(validataDir) + "/*.deb")
|
||||||
|
if len(debs) == 0 {
|
||||||
|
return "не входит в комплект этой установки — поставьте по инструкции «Справка → Криптография»", nil
|
||||||
|
}
|
||||||
|
if in.root != "" {
|
||||||
|
return "проверка в песочнице: пакеты " + strings.Join(debs, ", "), nil
|
||||||
|
}
|
||||||
|
ld, _ := run("sh", "-c", "ldconfig -p 2>/dev/null | grep -c 'libldap_r-2.4.so.2' || true")
|
||||||
|
var args []string
|
||||||
|
for _, d := range debs {
|
||||||
|
if strings.Contains(filepath.Base(d), "libldap") && strings.TrimSpace(ld) != "0" && strings.TrimSpace(ld) != "" {
|
||||||
|
continue // в системе уже есть libldap 2.4
|
||||||
|
}
|
||||||
|
args = append(args, d)
|
||||||
|
}
|
||||||
|
env := append(os.Environ(), "DEBIAN_FRONTEND=noninteractive")
|
||||||
|
if out, err := runEnv(env, "apt-get", append([]string{"install", "-y", "-qq", "--no-install-recommends"}, args...)...); err != nil {
|
||||||
|
return "", fmt.Errorf("установка Валидаты: %v\n%s", err, tail(out, 12))
|
||||||
|
}
|
||||||
|
ver, _ := run("dpkg-query", "-W", "-f", "${Version}", "zpki")
|
||||||
|
return "установлена с образа, версия " + strings.TrimSpace(ver), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (in *installer) stepServices() (string, error) {
|
func (in *installer) stepServices() (string, error) {
|
||||||
var files []string
|
var files []string
|
||||||
err := fs.WalkDir(deploy.Files, ".", func(p string, d fs.DirEntry, err error) error {
|
err := fs.WalkDir(deploy.Files, ".", func(p string, d fs.DirEntry, err error) error {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ show_accounts() {
|
|||||||
setup_accounts
|
setup_accounts
|
||||||
clear
|
clear
|
||||||
printf '\n Bridge&Join: установка на сервер\n ────────────────────────────────────────────────────────────\n'
|
printf '\n Bridge&Join: установка на сервер\n ────────────────────────────────────────────────────────────\n'
|
||||||
printf ' Debian установлен. Осталось установить bj.\n\n'
|
printf ' Система установлена. Осталось установить bj.\n\n'
|
||||||
if [ -f "$BUNDLE/manifest.json" ]; then
|
if [ -f "$BUNDLE/manifest.json" ]; then
|
||||||
printf ' Ключ продукта (BJ-XXXX-XXXX-XXXX) есть в портале клиента %s/portal/.\n' "$SERVER"
|
printf ' Ключ продукта (BJ-XXXX-XXXX-XXXX) есть в портале клиента %s/portal/.\n' "$SERVER"
|
||||||
printf ' Вводить его здесь необязательно: нажмите Enter — ядро bj установится с образа,\n а ключ вы введёте в браузере на первой странице настройки (там его удобно вставить).\n\n'
|
printf ' Вводить его здесь необязательно: нажмите Enter — ядро bj установится с образа,\n а ключ вы введёте в браузере на первой странице настройки (там его удобно вставить).\n\n'
|
||||||
|
|||||||
Executable
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Сборка образа ISO Bridge&Join на основе Ubuntu 22.04 LTS Server (автоустановка).
|
||||||
|
#
|
||||||
|
# deploy/iso/build-iso-ubuntu.sh <ubuntu-22.04.x-live-server-amd64.iso> <bj-installer> <версия> <каталог релиза> <каталог Валидаты> [канал] [выходной.iso]
|
||||||
|
#
|
||||||
|
# Каталог релиза — dist с подписанным manifest.json (в образ кладётся ядро bj: установка без ключа продукта).
|
||||||
|
# Каталог Валидаты — zpki/zsdk (ПК «Валидата Клиент L» для Linux, fs.moex.com ClientL_Other.zip)
|
||||||
|
# и libldap-2.4-2 из Ubuntu 20.04 (нужна zpki, в 22.04 её нет). Ubuntu 22.04 — ОС, на которой
|
||||||
|
# «Валидата Клиент L» ставится официально (Debian 13 её установщик не принимает).
|
||||||
|
# Меню загрузки (grub, BIOS и UEFI): по умолчанию — установка Bridge&Join с автоответами.
|
||||||
|
set -eu
|
||||||
|
SRC=${1:?ubuntu-22.04.x-live-server-amd64.iso}
|
||||||
|
INSTALLER=${2:?файл bj-installer}
|
||||||
|
VERSION=${3:?версия образа}
|
||||||
|
BUNDLE=${4:?каталог релиза с manifest.json}
|
||||||
|
VALIDATA=${5:?каталог с zpki/zsdk/libldap-2.4-2}
|
||||||
|
CHANNEL=${6:-stable}
|
||||||
|
OUT=${7:-bj-ubuntu22-$VERSION.iso}
|
||||||
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
command -v xorriso >/dev/null || { echo "нужен xorriso"; exit 1; }
|
||||||
|
WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT
|
||||||
|
mkdir -p "$WORK/bj/bundle" "$WORK/bj/validata" "$WORK/nocloud" "$WORK/grub"
|
||||||
|
|
||||||
|
install -m 0755 "$INSTALLER" "$WORK/bj/bj-installer"
|
||||||
|
install -m 0755 "$HERE/bj-firstboot" "$WORK/bj/bj-firstboot"
|
||||||
|
cp "$HERE/bj-firstboot.service" "$WORK/bj/"
|
||||||
|
install -m 0755 "$HERE/../linux/sbin/bj-welcome" "$WORK/bj/bj-welcome"
|
||||||
|
cp "$HERE/../systemd/bj-welcome.service" "$HERE/../systemd/bj-welcome.timer" "$WORK/bj/"
|
||||||
|
echo "$CHANNEL" > "$WORK/bj/channel"; echo "$VERSION" > "$WORK/bj/version"
|
||||||
|
|
||||||
|
# ядро bj: подписанный манифест + bj-server, bj-component-install
|
||||||
|
[ -s "$BUNDLE/manifest.json" ] || { echo "в $BUNDLE нет manifest.json"; exit 1; }
|
||||||
|
cp "$BUNDLE/manifest.json" "$WORK/bj/bundle/"
|
||||||
|
FILES=$(python3 -c 'import json,sys,base64;s=json.load(open(sys.argv[1]));m=json.loads(base64.b64decode(s["payload"]));print(" ".join(a["file"] for a in m["artifacts"] if a["name"] in ("bj-server","bj-component-install")))' "$BUNDLE/manifest.json")
|
||||||
|
[ -n "$FILES" ] || { echo "в релизе нет компонентов ядра"; exit 1; }
|
||||||
|
for f in $FILES; do cp "$BUNDLE/$f" "$WORK/bj/bundle/"; done
|
||||||
|
|
||||||
|
# Валидата
|
||||||
|
n=0; for p in zpki zsdk libldap-2.4-2; do
|
||||||
|
f=$(ls "$VALIDATA"/${p}_*.deb "$VALIDATA"/${p}-*.deb 2>/dev/null | grep -E 'amd64\.deb$' | head -1 || true)
|
||||||
|
[ -n "$f" ] || { echo "в $VALIDATA нет пакета $p"; exit 1; }
|
||||||
|
cp "$f" "$WORK/bj/validata/"; n=$((n+1))
|
||||||
|
done
|
||||||
|
|
||||||
|
# автоответы (пароль root_bj — случайный и нигде не сохраняется: настоящий задаёт bj-firstboot)
|
||||||
|
HASH=$(openssl passwd -6 "$(head -c 32 /dev/urandom | base64)")
|
||||||
|
sed "s#@@PASSHASH@@#$HASH#" "$HERE/ubuntu/user-data.tmpl" > "$WORK/nocloud/user-data"
|
||||||
|
: > "$WORK/nocloud/meta-data"
|
||||||
|
|
||||||
|
# меню загрузки: первый пункт — установка Bridge&Join
|
||||||
|
xorriso -osirrox on -indev "$SRC" -extract /boot/grub/grub.cfg "$WORK/grub/grub.orig" >/dev/null 2>&1
|
||||||
|
{
|
||||||
|
echo "set default=0"
|
||||||
|
echo "set timeout=10"
|
||||||
|
echo "loadfont unicode"
|
||||||
|
echo "menuentry --hotkey=b 'Install Bridge&Join $VERSION (Ubuntu 22.04)' {"
|
||||||
|
echo " set gfxpayload=keep"
|
||||||
|
echo " linux /casper/vmlinuz autoinstall ds=nocloud\;s=/cdrom/nocloud/ ---"
|
||||||
|
echo " initrd /casper/initrd"
|
||||||
|
echo "}"
|
||||||
|
sed '/^set timeout/d;/^loadfont/d' "$WORK/grub/grub.orig"
|
||||||
|
} > "$WORK/grub/grub.cfg"
|
||||||
|
|
||||||
|
rm -f "$OUT"
|
||||||
|
xorriso -indev "$SRC" -outdev "$OUT" -boot_image any replay \
|
||||||
|
-volid "BJ_UBUNTU22" \
|
||||||
|
-map "$WORK/bj" /bj -map "$WORK/nocloud" /nocloud \
|
||||||
|
-map "$WORK/grub/grub.cfg" /boot/grub/grub.cfg \
|
||||||
|
-end >/dev/null 2>"$WORK/xorriso.log" || { cat "$WORK/xorriso.log"; exit 1; }
|
||||||
|
echo "Образ собран: $OUT ($(du -h "$OUT" | cut -f1)), канал $CHANNEL; ядро: $FILES; Валидата: $n пакета"
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#cloud-config
|
||||||
|
# Автоустановка Ubuntu 22.04 для образа Bridge&Join (deploy/iso/build-iso-ubuntu.sh).
|
||||||
|
# Спрашиваются только сеть (если DHCP нет — задать вручную) и диск (подтверждение стирания).
|
||||||
|
# Учётная запись root_bj (sudo) создаётся с неизвестным никому паролем — настоящие пароли
|
||||||
|
# root_bj и user_bj задаёт bj-firstboot при первой загрузке и показывает один раз.
|
||||||
|
autoinstall:
|
||||||
|
version: 1
|
||||||
|
interactive-sections:
|
||||||
|
- network
|
||||||
|
- storage
|
||||||
|
locale: ru_RU.UTF-8
|
||||||
|
keyboard:
|
||||||
|
layout: us,ru
|
||||||
|
toggle: grp:alt_shift_toggle
|
||||||
|
timezone: Europe/Moscow
|
||||||
|
identity:
|
||||||
|
hostname: bj-server
|
||||||
|
realname: "Администратор сервера bj"
|
||||||
|
username: root_bj
|
||||||
|
password: "@@PASSHASH@@"
|
||||||
|
ssh:
|
||||||
|
install-server: true
|
||||||
|
allow-pw: true
|
||||||
|
storage:
|
||||||
|
layout:
|
||||||
|
name: direct
|
||||||
|
updates: security
|
||||||
|
late-commands:
|
||||||
|
- mkdir -p /target/var/lib/bj /target/etc/bj /target/usr/local/sbin
|
||||||
|
- cp -r /cdrom/bj/bundle /target/var/lib/bj/bundle
|
||||||
|
- cp -r /cdrom/bj/validata /target/var/lib/bj/validata
|
||||||
|
- install -m 0755 /cdrom/bj/bj-installer /cdrom/bj/bj-firstboot /cdrom/bj/bj-welcome /target/usr/local/sbin/
|
||||||
|
- install -m 0644 /cdrom/bj/bj-firstboot.service /cdrom/bj/bj-welcome.service /cdrom/bj/bj-welcome.timer /target/etc/systemd/system/
|
||||||
|
- install -m 0644 /cdrom/bj/channel /target/etc/bj/channel
|
||||||
|
- curtin in-target --target=/target -- systemctl enable bj-firstboot.service bj-welcome.service bj-welcome.timer
|
||||||
Reference in New Issue
Block a user