The xterm console never connected: socketiod expected a different token
format, its worker had no compute credentials, one global console was
shared by every client and its output broadcast to all of them, and the
Docker image did not run socketiod at all.
- console/tokens.py: one authorize() for noVNC and socketiod; the signed
token is the only credential, checked at connect time.
- socketiod: one pty worker per client (consolecallback with the
instance id), one session per VM, a session cap, input and resize
checked; the parent never opens libvirt. The engine.io same-origin
check is on.
- consolecallback: opens the console with the compute's credentials and
exits with a message when it cannot.
- Docker runs socketiod as a runit service; nginx proxies /socket.io/
with Host and the scheme for the origin check. Supervisor and systemd
start it as well; WEBVIRTCLOUD_SERIAL_CONSOLE=1 enables it.
- Tests: token and session unit tests, socketiod as a process, and a
live test that reads SeaBIOS from a wvc-test VM on the TCP and SSH
hosts.
The web app (wsgi.py), novncd and socketiod set SIGCHLD to SIG_IGN at
import. The kernel then reaps every child at once, so subprocess loses
the exit status and a failing command reports 0, in the server and in
anything else run in that process: the test suite had to reset the
signal in two tests.
It was added in 2023 against one defunct bash per gunicorn worker and
per novncd. That bash came from the settings template of the time,
which ran .dec_ldap_pwd.sh with Popen and never waited for it; the
template stopped doing that in 561fedf. A settings.py still holding
that line leaves at most one zombie per process, not a growing number.
- wsgi.py, novncd, socketiod: the global SIG_IGN is removed. subprocess
reaps its own children, websockify installs its own SIGCHLD reaper
for novncd's connection processes, and novncd's SSH tunnels wait for
their ssh process.
- socketiod: the pty child execs consolecallback instead of running it
and then returning into the server's code; disconnect reaps that
child (waitpid) instead of any child (wait).
- The settings template drops its unused subprocess import; the two
test workarounds are removed.
New tests load the web app and novncd in a fresh interpreter and check
that SIGCHLD is untouched and a failing command still returns 1; both
fail on the previous code. A patched novncd in the test container
served five connections and left no child behind.
novncd accepted signed tokens without the user part, which skipped the
per-user access check, and accepted unsigned "host-uuid" tokens whenever
"test" appeared in sys.argv. The console view always signs
host:uuid:user_id, so anything else is now rejected with PermissionError,
and the user check always runs.
Add webvirtcloud/test_authorization_matrix.py, which walks every named URL
and checks that a user without any VM/compute relation only reaches an
explicit allowlist, and that the global view_instances permission does not
open consoles. It found:
- /computes/<id>/... views without any check (compute_graph,
get_compute_*, get_dom_capabilities, storages.get_volumes): the whole
computes URL namespace is now wrapped with superuser_only, so a view
added there later cannot be exposed by a missing decorator.
- guess_mac_address (leaks dhcpd.conf host/MAC pairs), random_mac_address
and guess_clone_name: superuser-only, like the buttons that use them.
- check_instance: cross-tenant VM name lookup with no caller; removed.
- getvvfile and get_vdi_url: reachable with only view_instances, and the
.vv file contains the VNC password.
Console access now follows one rule, instances.utils.can_open_console:
an active superuser or an active owner of the VM. The global
view_instances permission is read-only. It is used by the console page,
novncd, getvvfile and get_vdi_url (getvvfile and the VDI tab are kept for
virt-viewer users). The console page answers 403 instead of 500 when
access is denied, with the same answer for a missing VM.
- Computes API: mark password as write_only in ComputeSerializer, restrict ComputeViewSet and architectures to IsAdminUser.
- Instances API: enforce user ownership tenant isolation in InstanceViewSet.list, restrict MigrateViewSet and CreateInstanceViewSet to IsAdminUser, require IsAdminUser for mutating FlavorViewSet.
- Storage, Network, and Interface APIs: restrict StorageViewSet, VolumeViewSet, NetworkViewSet, InterfaceViewSet to IsAdminUser.
- AppSettings & NWFilters: protect appsettings and nwfilter views with @superuser_only (403 Forbidden for non-superusers).
- noVNC Console: sign tokens with TimestampSigner (salt='console.novnc', max_age=600), verify signature and user authorization in novncd with backward-compatible fallback for debug/test mode.
- Accounts: avoid hardcoded default admin password; generate cryptographically secure random password unless ADMIN_PASSWORD is set (preserve 'admin' in test runner).
- gstfsd daemon: bind to 127.0.0.1 by default instead of 0.0.0.0.
- Tests: added comprehensive test coverage for API security, token expiration/rejection, and view permissions (132 tests passing).
* Add rest framework for API: First Commit
* modify some shell scripts to make variable references safer; modify some python scripts to reduce the code complexity and cyclomatic complexity of functions.
* Add REST API for some webvirtcloud functions. Instance list/delete/create, compute list/delete/create, storages-network list/retrieve. Add swagger and redoc for API interface
* update requirements
Co-authored-by: herengui <herengui@uniontech.com>