Enhance UVM installation and configuration for Ubuntu 22.04 root filesystem

- Update README and USAGE documentation to reflect changes in rootfs handling, including the default local build from Ubuntu 22.04 packages.
- Modify the installer to support building the rootfs locally with authenticated packages and to require SHA-256 checksums for prebuilt images.
- Implement checks for setuid permissions on sudo and update the provisioning logic for guest users to ensure proper sudo access.
- Adjust tests to validate the new rootfs building process and ensure that existing functionality is preserved.
- Refactor code to improve clarity and maintainability, including the introduction of constants for Ubuntu release and guest packages.
This commit is contained in:
2026-09-22 00:33:05 +05:30
parent 71425a98e3
commit 4bf4c0853c
10 changed files with 523 additions and 63 deletions
+41 -7
View File
@@ -545,6 +545,13 @@ The new `/home/USERNAME` directory is mode `0700`, owned by the new UID/GID;
Directory ownership/modes and account-file writes are read back before the
disk can be marked ready. The default `root` account must already exist.
Custom login users are VM administrators. Provisioning requires a root-owned,
setuid `/usr/bin/sudo` and `/etc/sudoers`, and appends a user-scoped `PASSWD: ALL`
rule with root/target/runas-password defaults disabled. Sudo authenticates with
the login user's password; root's separate shadow entry is not changed. Global
sshd directives precede managed and existing `Match` blocks so standard Ubuntu
`UsePAM`/`Subsystem` settings remain valid.
UVM replaces conventional RSA, ECDSA, and Ed25519 host keys in each private
disk and removes the known public login key from Firecracker's bionic image.
A VM must never rely on reusable SSH private keys from a shared template.
@@ -557,14 +564,19 @@ A VM must never rely on reusable SSH private keys from a shared template.
- A local `integrity.json` manifest recording artifact hashes and whether the
installation was verified.
Strict installation requires all of these values:
Strict installation requires these values for downloaded artifacts:
```text
UVM_FIRECRACKER_SHA256
UVM_KERNEL_SHA256
UVM_ROOTFS_SHA256
```
The default rootfs is built from signature-verified Ubuntu packages and its
resulting digest is recorded in the same manifest. `UVM_ROOTFS_URL` explicitly
selects a prebuilt ext4 download and additionally requires `UVM_ROOTFS_SHA256`.
A rootfs checksum without a URL is rejected during installation to avoid using
a stale Bionic-image checksum for a local build.
`UVM_ALLOW_UNVERIFIED_DOWNLOADS=1` is a local-development escape hatch. It
writes a manifest marked `verified: false`; a later strict run will not treat
that manifest as publisher trust. Use `install --force` with trusted digests to
@@ -694,12 +706,30 @@ handling, downloads, and integrity-manifest publication.
`Settings` detects and normalizes the host architecture at construction time
(`amd64` to `x86_64`, `arm64` to `aarch64`) and rejects unsupported architectures.
The same architecture selects the Firecracker release archive, guest kernel,
rootfs, and architecture-specific boot arguments. Default guest URLs use
Firecracker's `img/quickstart_guide/<architecture>/` assets: `kernels/vmlinux.bin`
and `rootfs/bionic.rootfs.ext4`. Kernel and rootfs URL overrides are independent;
custom assets and trusted digests must match the host architecture. ARM64
native rootfs packages, and architecture-specific boot arguments. The default
kernel URL uses Firecracker's `img/quickstart_guide/<architecture>/kernels/vmlinux.bin`.
An empty `Settings.rootfs_url` selects the built Ubuntu 22.04 (Jammy) template.
Explicit kernel/rootfs URLs and trusted digests must match the host architecture. ARM64
uses an uncompressed Linux `Image` (PE format) and an ARM64 ext4 rootfs.
The default rootfs builder installs `debootstrap` and `ubuntu-keyring`, uses
`--force-check-gpg`, and includes main/universe plus updates/security suites.
amd64 uses `archive.ubuntu.com/ubuntu`; arm64 uses `ports.ubuntu.com/ubuntu-ports`.
Package scripts execute in private mount/PID namespaces with a temporary
`policy-rc.d` suppressing service startup. No mounts survive the build process.
The staged tree retains `/var/lib/dpkg` and apt metadata, validates installed
apt/sudo/sshd/systemd packages, enables SSH/networkd, preserves kernel-provided
static networking, and supplies guest DNS. Template host keys and machine IDs
are cleared for per-VM initialization. `mkfs.ext4 -d` creates a sparse 2 GiB
template with a guest-kernel-compatible feature set; `e2fsck` and fsync precede
atomic publication. Create still grows each private disk to at least 30 GiB.
Only a checksum-verified manifest and matching `/etc/uvm-image` recipe marker
permit reuse of a built template. Old demo images and unverified caches are
rebuilt, and `install --force` always rebuilds. A failed staging build retains
the old template. Installation holds the existing operation lock throughout;
existing VM disks are never upgraded or reprovisioned by installation.
The host package list includes `nftables` and `conntrack` as well as the
existing iproute2/iptables, ext4, OpenSSL, OpenSSH, download, and util-linux
tools. UVM adds no reconciliation daemon or tested external firewall-manager
@@ -892,6 +922,9 @@ sparse ext4 images when the tools are installed: default 30 GiB creation,
growth, shrinking, geometry, and retained data/password-hash/host-key fixtures.
`test_images.py` uses temporary ext4 images to verify custom-user creation,
UID/GID allocation, account/home metadata, existing accounts, and password hashes.
`test_install.py` simulates package bootstrap and exercises real ext4 formatting
and readback for retained dpkg metadata, sudo modes, template configuration,
staging failures, and checksum provenance. It does not run debootstrap or boot a VM.
Lifecycle resize tests use fake processes/networking to verify ordering,
single-lock ownership, identity preservation, pending intent, and failure recovery.
@@ -926,7 +959,8 @@ on an isolated Linux host:
1. Strict checked installation.
2. `create` and successful guest boot.
3. Guest IP reachability and egress.
4. SSH with unique guest host keys.
4. SSH with unique guest host keys, `sudo -i` for a custom login, and
`sudo apt update && sudo apt install htop` in a newly built Ubuntu guest.
5. Stop/start/restart with retained guest data, SSH keys, and credentials.
6. Live private-port close in both directions, empty policy, and explicit sync
after deliberately lost rules inside the isolated setup.