feat: multi-user support in sandboxes - #27
Open
Tyler Payne (tylerpayne) wants to merge 2 commits into
Open
Conversation
Add OS-user management to the Quicksand API. Sandbox.create_user() and Sandbox.delete_user() manage accounts inside the guest, and execute() accepts a user= parameter (or use the returned SandboxUser handle) to run commands with that user's uid/gid/groups and HOME. Multiple users share one VM, giving per-user isolation without per-user VM overhead. The guest agent implements the accounts natively by editing /etc/passwd, /etc/group and /etc/shadow, so behaviour is identical across distros with no dependency on adduser/useradd. Commands drop privileges via initgroups/setgid/setuid in a pre_exec hook. Both the HTTP and virtio-serial transports expose create_user/delete_user and the user field on execute/execute_stream. Since the Dockerfiles compile the agent from a build-context copy the Dockerfile text does not reference, the image cache key now folds in a hash of the agent source, with a sidecar file to validate caller-supplied output paths. The ubuntu hatch hook now always delegates to build_image so a cached-but-stale qcow2 is rebuilt instead of packaged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The quicksand-qemu wheel hardcoded manylinux_2_17, but its bundled binaries link against the build runner's glibc, which can be newer. pip would then install a wheel that fails to load on older hosts instead of rejecting it at install time. BinaryBundler now scans the bundled ELF files for the glibc symbol versions they reference and asks auditwheel which manylinux policy that implies, raising on any failure rather than guessing. auditwheel becomes a Linux-only build dependency of quicksand-qemu. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds OS-user management to the Quicksand API so multiple isolated users can share one VM.
Sandbox.create_user(name)returns aSandboxUserhandle (uid, gid, home) andSandbox.delete_user(name, remove_home=...)kills the user's processes and removes the account.Sandbox.execute(..., user=...)(orSandboxUser.execute) runs commands with that user's uid/gid/supplementary groups andHOME, defaulting cwd to the user's home./etc/passwd,/etc/group, and/etc/shadowdirectly, so behaviour is identical on Alpine, Ubuntu, and any other guest with no dependency onadduser/useradd. Privileges drop viainitgroups/setgid/setuidin apre_exechook. Account-file mutations are serialised behind a mutex, and usernames are validated to prevent injection into the colon/newline-delimited files.create_user/delete_userand theuserfield onexecute/execute_stream..buildhashsidecar validating caller-supplied output paths. The ubuntu hatch hook always delegates tobuild_imageso an agent-only change rebuilds the packaged image instead of shipping a stale qcow2.Also includes one standalone build fix. The quicksand-qemu wheel hardcoded
manylinux_2_17, letting pip install wheels whose bundled binaries need a newer glibc than the host and then crash on load. The manylinux tag is now derived from the glibc symbol versions the bundled ELF binaries actually reference (via auditwheel, a new Linux-only build dependency).Fixes applied during review
Cargo.toml,main.rs). The multiuser changes predated the virtio-serial writer-task refactor, so they were ported onto it: handlers emit frames throughsend_frameand commands still run on spawned tasks so a long command cannot stall the read loop.custom-<hash>.qcow2name already encodes the input hash, so requiring a sidecar there needlessly invalidated existing caches.executesignature and the cache-key test to include the agent source hash.Testing
cargo checkandcargo clippyclean on the guest agent (the two clippy warnings are pre-existing).SandboxUserhandle routing, and error propagation.ruff check,ruff format, andty checkall pass.🤖 Generated with Claude Code