From d50a4314aa7c83a9c03938ee5f35683e6f8fb151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80?= Date: Sun, 27 Sep 2026 15:54:01 +0900 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B1=D0=BE=D1=80=D0=BA=D0=B0=20ISO=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=BD=D1=8B=D0=B5?= =?UTF-8?q?=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0=20=D0=B0=D0=B4=D0=BC=D0=B8?= =?UTF-8?q?=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?(admin,=20root,=20kvm):=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=89=D0=B8=D0=BA=20Ubuntu=20=D0=B8=D1=85=20=D0=BE=D1=82?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D0=B3=D0=B0=D0=B5=D1=82,=20=D0=B8=20=D0=B0?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D1=87=D0=B5=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=D1=8F=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=BB=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B2=D0=BE=D0=BC=20=D1=88=D0=B0?= =?UTF-8?q?=D0=B3=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/IMAGE.md | 4 +- image/build-iso.sh | 1 + image/reserved-usernames | 127 +++++++++++++++++++++++++++++++++++++++ tests/test_core.py | 10 +++ 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 image/reserved-usernames diff --git a/docs/IMAGE.md b/docs/IMAGE.md index 3a81eee..f2599d1 100644 --- a/docs/IMAGE.md +++ b/docs/IMAGE.md @@ -98,9 +98,11 @@ make iso ISO_ARGS="--web-port 8089 --no-auto-update --timezone Europe/Moscow" Для массовой раскатки: ```bash -make iso ISO_ARGS="--unattended --username admin --password-hash '$(openssl passwd -6)' --hostname node01" +make iso ISO_ARGS="--unattended --username sysadmin --password-hash '$(openssl passwd -6)' --hostname node01" ``` +Системные имена вроде `admin`, `root` или `kvm` установщик Ubuntu не принимает, и установка остановится на первом шаге. Поэтому `build-iso.sh` сразу отказывается собирать образ с таким `--username`. Полный список лежит в `image/reserved-usernames`, это копия списка из установщика Ubuntu. + > ⚠️ Такой образ сам уходит в установку через 10 секунд в меню и **без подтверждения стирает самый большой диск** машины. Файл получает суффикс `-unattended`, пункты меню — пометку «автоматически, диск будет стёрт». Не оставляйте такую флешку в серверах. --- diff --git a/image/build-iso.sh b/image/build-iso.sh index c8a79db..0f7cf78 100755 --- a/image/build-iso.sh +++ b/image/build-iso.sh @@ -106,6 +106,7 @@ esac [[ "$WEB_PORT" =~ ^[0-9]+$ ]] && (( WEB_PORT >= 1 && WEB_PORT <= 65535 )) || die "invalid --web-port: $WEB_PORT" if [[ "$UNATTENDED" == "1" ]]; then [[ "$USERNAME" =~ ^[a-z_][a-z0-9_-]{0,31}$ ]] || die "--unattended needs a valid --username" + ! grep -qxF "$USERNAME" "${IMAGE_DIR}/reserved-usernames" || die "--username ${USERNAME} is reserved by the Ubuntu installer (like admin, root, kvm); pick another name" [[ "$PASSWORD_HASH" == \$* ]] || die "--unattended needs --password-hash (generate: openssl passwd -6)" [[ "$HOSTNAME_VALUE" =~ ^[a-zA-Z0-9][a-zA-Z0-9-]{0,62}$ ]] || die "invalid --hostname" fi diff --git a/image/reserved-usernames b/image/reserved-usernames new file mode 100644 index 0000000..9a29be1 --- /dev/null +++ b/image/reserved-usernames @@ -0,0 +1,127 @@ +# Имена, которые установщик Ubuntu (subiquity) не даёт выбрать для первого пользователя. +# Копия https://github.com/canonical/subiquity/blob/main/reserved-usernames (27.09.2026). +# build-iso.sh проверяет по ней --username, иначе автоматическая установка падает на первом шаге. + +# Static users from base-passwd/passwd.master (3.5.41). +root +daemon +bin +sys +sync +games +man +lp +mail +news +uucp +proxy +www-data +backup +list +irc +gnats +nobody + +# Other static groups from base-passwd/group.master (3.5.41). +adm +tty +disk +kmem +dialout +fax +voice +cdrom +floppy +tape +sudo +audio +dip +operator +src +shadow +utmp +video +sasl +plugdev +staff +users +nogroup + +# Reserved usernames listed in base-passwd/README (3.5.41). +netplan +ftn +mysql +tac-plus +alias +qmail +qmaild +qmails +qmailr +qmailq +qmaill +qmailp +asterisk +vpopmail +vchkpw +slurm +hacluster +haclient +grsec-tpe +grsec-sock-all +grsec-sock-clt +grsec-sock-srv +grsec-proc +ceph +opensrf +libvirt-qemu + +# Ubuntu creates the admin group and adds the first user to it in order to +# grant them sudo privileges. +admin + +# Other miscellaneous system users/groups created by common packages. While +# it's useful to add things here that people might run into, it's not +# absolutely critical; the worst that will happen is that the installation +# will fail at some later point. +Debian-exim +bind +crontab +cupsys +dcc +dhcp +dictd +dnsmasq +dovecot +fetchmail +firebird +ftp +fuse +gdm +haldaemon +hplilp +identd +input +jwhois +klog +kvm +lpadmin +maas +messagebus +mythtv +netdev +powerdev +radvd +render +saned +sbuild +scanner +sgx +slocate +ssh +sshd +ssl-cert +sslwrap +statd +syslog +telnetd +tftpd diff --git a/tests/test_core.py b/tests/test_core.py index e86905b..02db236 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -194,3 +194,13 @@ def test_stable_channel_follows_release_tags(tmp_path, monkeypatch, data_dirs): (tmp_path / "web.env").write_text("VIRTUALITY_UPDATE_CHANNEL=main\n") data = update_core.check_updates(fetch=True) assert data["channel"] == "main" and data["target"] == "main" and data["has_update"] + + +@pytest.mark.parametrize("username", ["admin", "root", "kvm", "libvirt-qemu"]) +def test_build_iso_refuses_names_the_ubuntu_installer_rejects(username): + """Установщик Ubuntu не принимает системные имена: автоматический образ с таким именем падал на первом шаге.""" + import subprocess + + result = subprocess.run(["bash", str(ROOT / "image" / "build-iso.sh"), "--unattended", "--username", username, "--password-hash", "$6$salt$hash"], capture_output=True, text=True) + assert result.returncode != 0 and "reserved by the Ubuntu installer" in result.stderr +