1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
Commit graph

1423 commits

Author SHA1 Message Date
catborise
d250915e17 fix(instances): edit_volume bus change and format, full-string validation
- edit_volume passed driver_type to attach_disk, which has no such
  parameter, so every bus change failed after the disk was detached; pass
  format_type.
- A disk without a driver type shows "None" in the edit form; keep the
  disk's current format instead of rejecting it.
- Validate with fullmatch, so a trailing newline is no longer accepted,
  and use one volume-name pattern for disk views and clone.
2026-10-02 22:31:25 +03:00
catborise
fe5bb578d8 Merge branch 'fix/wave0-socketiod-disable' into wave0-integration 2026-10-02 22:27:39 +03:00
catborise
4252ad9280 fix(console): keep socketiod behind nginx and off by default there too
- Comment out the nginx /socket.io/ location: a firewall on 6081 does not
  protect a console that nginx proxies on 80/443.
- Default SOCKETIO_HOST to 127.0.0.1.
- README: short enable steps and the changes existing installs need.
- test_socketiod_disabled writes its settings module to a temporary
  directory instead of the source tree.
2026-10-02 22:27:39 +03:00
catborise
22fe0871f3 test: check per-role URL reachability in the authorization matrix
For six roles (global view_instances with and without is_staff, and VM
owners with no flags, is_change, is_delete, and is_change+is_vnc as staff)
walk every URL and compare the reachable set with the expected one in both
directions, so both privilege leaks and lost access fail the test. Each
request runs in a rolled-back transaction so destructive views do not
affect the following requests. The expectations mirror the roles table in
README.md and depend on all Wave 0 fixes, so the test lives on the
integration branch.
2026-10-02 22:19:50 +03:00
catborise
634e9acb69 Merge branch 'fix/wave0-template-flag' into wave0-integration 2026-10-02 22:14:40 +03:00
catborise
34851b8dc2 Merge branch 'fix/wave0-staff-console-password' into wave0-integration 2026-10-02 22:14:40 +03:00
catborise
51db12acfe Merge branch 'fix/wave0-authorization-matrix' into wave0-integration
# Conflicts:
#	datasource/views.py
2026-10-02 22:14:40 +03:00
catborise
fbb48fb3ea Merge branch 'fix/wave0-clone-permission' into wave0-integration 2026-10-02 22:14:29 +03:00
catborise
3df2e68431 Merge branch 'fix/wave0-xss' into wave0-integration 2026-10-02 22:14:29 +03:00
catborise
dc90ab0437 Merge branch 'fix/wave0-socketiod-disable' into wave0-integration 2026-10-02 22:14:29 +03:00
catborise
ce00b19b1c Merge branch 'fix/wave0-disk-tenant-isolation' into wave0-integration 2026-10-02 22:14:29 +03:00
catborise
385a332197 fix(instances): only superusers and staff may change the template flag
change_options set is_template for any owner with is_change; the
"staff only" rule existed only as a disabled checkbox in the UI. A
non-staff owner could mark or unmark templates with a POST, and because a
disabled checkbox is not submitted, a non-staff owner who only edited a
template's title or description silently unmarked it, which lifted the
template-only restrictions.

Only change is_template for superusers and staff (for them an unchecked,
unsubmitted checkbox still means "not a template"); leave it alone for
everyone else.
2026-10-02 22:13:46 +03:00
catborise
75c91f8d53 docs(readme): correct the is_staff and 404/403 notes in the roles section
is_staff does not reveal console settings or VNC passwords (fixed on
fix/wave0-staff-console-password), but staff owners with is_change may
also change VMs marked as templates. Superuser-only pages answer 403 to
everyone else, and the console page answers 403 both for a missing VM and
for a VM the user may not open.
2026-10-02 22:04:45 +03:00
catborise
8e23699987 fix(instances): show console settings and the VNC password only to console managers
The console settings form on the VM detail page renders the VNC password
(PasswordInput(render_value=True)) and was shown to every is_staff user.
A staff user with the global view_instances permission, or a staff owner
without is_vnc, could read the VNC password of every VM they could see.

Add instances.utils.can_manage_console (active superuser, or an active
owner with is_change and is_vnc), which matches what update_console
already enforced. The detail view only builds the form, and so only puts
the password into the page, when it returns True; the template and
update_console use the same rule.
2026-10-02 22:04:05 +03:00
catborise
e385014ba9 docs(readme): document users, roles and permissions
Describe the access model: superuser, the global permissions
(view_instances as a read-only auditor role, clone_instances,
snapshot_instances, passwordless_console, change_password) and per-VM
ownership flags (is_change, is_delete, is_vnc), with a table of which
VM actions each combination allows.

The table describes the state after all Wave 0 branches are merged:
disk/media views are superuser-only (fix/wave0-disk-tenant-isolation) and
clone requires is_change except for templates (fix/wave0-clone-permission).
2026-10-02 20:36:24 +03:00
catborise
b7a39d24e2 fix(console): accept only signed host:uuid:user_id tokens in novncd
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.
2026-10-02 20:35:29 +03:00
catborise
4d34d9d07c fix: add an authorization matrix test and close the endpoints it finds
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.
2026-10-02 20:33:12 +03:00
catborise
5758073e82 fix(instances): require change permission to clone and stop trusting clone POST data
clone only required "view" access, so a user with clone_instances and the
global view_instances permission could clone anyone's VM and read its
disks. It also copied every POST field into clone_data, which let the
client override the server-set disk_owner_uid/gid, and disk-<dev> values
went unvalidated into volume XML and os.path.join.

- Require change permission on the source VM, except for templates,
  which any user who can view them may clone.
- Build clone_data from an allowlist: name, title and description for
  everyone; disk names and MAC addresses only from superusers.
- For non-superusers, derive disk names (get_clone_disk_name) and MAC
  addresses (DHCP or random) on the server; their form only sent the
  source VM's own values, which could never work.
- Validate every MAC address (not only the first) and every disk name;
  a missing MAC is an error message instead of a KeyError.
2026-10-02 19:07:53 +03:00
catborise
4546653b5a fix: serve JSON endpoints as application/json and build DOM safely
Several views returned json.dumps() output through HttpResponse, i.e. as
text/html, and guess_mac_address reflects the URL's vname into it
(reflected XSS). Templates filled the log table and volume dropdowns by
concatenating server data into HTML strings, and log messages contain
user-entered snapshot/disk/clone names (stored XSS that runs when a
superuser opens the Logs tab).

- Use JsonResponse in guess_mac_address, random_mac_address,
  guess_clone_name, sshkeys, storages.get_volumes,
  datasource.os_metadata_json and logs.vm_logs; sshkeys?plain=true is
  served as text/plain.
- stats_tab.html builds log rows with .text(); instance.html and
  create_instance_w2.html build <option> elements with .val().text().
2026-10-02 18:29:11 +03:00
catborise
1547e58e55 fix(console): disable the unauthenticated serial console by default
socketiod does not validate the console token, keeps a single global PTY
and broadcasts its output to every connected client, so anyone who can
reach port 6081 can read and write a serial console that someone opened.
It is also broken for legitimate users, since console/views.py now writes
signed tokens that socketiod cannot parse.

Until it is rewritten, turn the serial console off by default:

- Add SERIAL_CONSOLE_ENABLED = False to the settings template; installs
  whose settings.py lacks it are treated as disabled.
- The console view shows an error instead of the xterm page for pty
  consoles while the setting is off.
- socketiod refuses to start unless SERIAL_CONSOLE_ENABLED is True.
- Supervisor: autostart=false for socketiod; drop -d (debug) from the
  supervisor and systemd definitions; fix the systemd unit description;
  conf/systemd/install.sh no longer suggests enabling socketiod.
- README: stop opening port 6081 and document how to enable the serial
  console on a trusted network.
2026-10-02 17:22:20 +03:00
catborise
8a3ee13b41 fix(instances): restrict disk views to superusers and validate disk input
Disk and media mutation views (add_new_vol, add_existing_vol, edit_volume,
delete_vol, detach_vol, add_cdrom, detach_cdrom, mount_iso, unmount_iso)
were reachable by any owner with is_change, although the UI only shows the
Disk tab to superusers. An ordinary user could delete any volume on the
compute or attach arbitrary host files to their VM.

- Require superuser for all disk/media views, matching the UI.
- delete_vol resolves the volume from the VM's own disk XML by dev and
  ignores the posted storage/name.
- Validate bus/cache/io/discard/detect_zeroes against the hypervisor's
  lists, and format/serial/volume name against strict patterns.
- add_existing_vol only accepts volumes that exist in the selected pool.
- edit_volume only accepts a dev attached to the VM.
- vrtManager: escape all values interpolated into disk XML and pass dev
  as an XPath variable in detach_disk/edit_disk.
2026-10-02 17:11:12 +03:00
catborise
b1ab1d47fa docs(readme): translate purpose, architecture and features sections to English
Remove the inaccurate "periodic synchronization" claim; external changes
are picked up when the instance list page is loaded.
2026-10-02 13:55:49 +03:00
catborise
b51acdc3ef docs(readme): update intro and setup instructions for current setup
- Rewrite purpose/features intro around libvirt as single source of truth
- Generate SECRET_KEY into data/secret_key instead of editing settings.py
- Consolidate local development setup into one flow using
  --system-site-packages, settings-dev and runserver --nostatic
- Document the generated admin password instead of admin/admin
- Use the shared supervisor config on RHEL (adds missing socketiod)
  and add supervisor setup on openSUSE
- Document SOCKETIO_PUBLIC_PORT and CSRF_TRUSTED_ORIGINS for proxies
- Point test setup at the dev virtualenv
2026-10-02 12:29:00 +03:00
catborise
3ba1baa60b chore: ignore runtime data directory
data/ holds the generated secret_key; keep it out of version control.
2026-10-02 12:04:41 +03:00
catborise
0f362f697c fix(wsgi): only install SIGCHLD handler from the main thread
runserver imports the WSGI application from a worker thread, where
signal.signal() raises ValueError and the dev server fails to start.
Gunicorn imports it from the worker's main thread, so production
keeps reaping child processes as before.
2026-10-02 12:04:41 +03:00
catborise
a3a6961155 chore: keep roadmap local and untracked 2026-09-28 15:10:33 +03:00
catborise
2441b21c0c feat(storage): support resilient ISO uploads across connection types 2026-09-28 14:57:31 +03:00
catborise
73d8fd71fb fix(instances): guard mutations and refresh lists after sync 2026-09-28 14:56:19 +03:00
catborise
2cdf5dfca1 fix(reconciliation): serialize compute sync and enforce UUID identity 2026-09-28 14:55:49 +03:00
catborise
30c436ecde fix(snapshot): preserve loader XML during snapshot operations 2026-09-28 14:55:24 +03:00
catborise
ce67778d2f docs(roadmap): update Phase 2 P1 status with completed security & reliability milestones 2026-09-27 13:28:40 +03:00
catborise
5e240236c3 feat(security): harden storage uploads and vrtManager snapshot XML handling 2026-09-27 13:28:17 +03:00
catborise
b3e6fb2b7a feat(security): enforce require_POST on power actions, prevent open redirects, and isolate instance permissions 2026-09-27 13:20:45 +03:00
catborise
3f8eeb04bd fix(reconciliation): implement UUID-based domain reconciliation and connection safety 2026-09-27 13:13:43 +03:00
catborise
dbef70131b docs(roadmap): update Phase 1 P0 status with Codex review hardening 2026-09-27 11:30:30 +03:00
catborise
708b986e8e feat(security): apply Codex review hardening to console tokens and superuser authorization 2026-09-27 11:30:03 +03:00
catborise
1227674d8f feat(security): implement P0 critical security fixes for API, console, and access control
- 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).
2026-09-27 10:50:09 +03:00
catborise
1c561de4d2 docs: add comprehensive security audit and architecture roadmap 2026-09-27 00:36:36 +03:00
catborise
33550e5e3a chore(deps): update production and development requirements for Django 4.2 LTS
- Upgraded Django to 4.2.30 (latest Django 4.x LTS release)
- Upgraded production dependencies in conf/requirements.txt:
  * django_bootstrap5 to 26.2 (latest supporting Django 4.2)
  * django-otp to 1.7.3
  * django-auth-ldap to 5.3.0
  * djangorestframework to 3.17.2 (latest supporting Django 4.2)
  * drf-nested-routers to 0.95.3
  * drf-spectacular[sidecar] to 0.30.0
  * eventlet to 0.41.2
  * gunicorn to 26.2.0
  * markdown to 3.10 (supporting Python 3.10+)
  * paramiko to 5.0.0
  * python-engineio to 4.14.0
  * python-socketio to 5.17.0
  * whitenoise to 6.12.0
  * zipp to 4.1.0
- Upgraded development dependencies in dev/requirements.txt:
  * coverage to 7.16.1
  * django-debug-toolbar to 6.3.0 (latest supporting Django 4.2)
  * pycodestyle to 2.15.0
  * pyflakes to 4.0.0
  * pylint to 4.0.9
  * black to 26.5.1
2026-09-27 00:22:38 +03:00
catborise
2ea6652a0e chore(frontend): upgrade Bootswatch and Bootstrap SCSS to v5.3.3
- Upgraded Bootswatch SCSS source files across all 25 themes (dev/scss/bootswatch/) to v5.3.3
- Upgraded Bootstrap SCSS source files (dev/scss/bootstrap/) to v5.3.3 to match static/js/bootstrap.bundle.min.js
- Updated dev/scss/bootstrap-overrides.scss to import bootstrap/variables-dark
- Verified error-free LibSass compilation for all 26 themes (25 Bootswatch + bootstrap-orj)
- Recompiled static/css/wvc-main.min.css
2026-09-26 23:57:02 +03:00
catborise
ac91248a29 feat(ui): make authentication pages 100% compatible with Bootswatch themes
- Replace hardcoded colors with Bootstrap & Bootswatch CSS custom properties
- Adapt background, card, borders, and inputs dynamically to active light and dark themes
- Inherit primary color, border-radius, and font-family from active theme
- Use native Bootswatch alert and button styles for consistent visual hierarchy
2026-09-26 23:31:24 +03:00
catborise
2996adae3a feat(ui): redesign authentication pages with modern virtualization theme
- Overhaul signin.css with responsive dark glassmorphic card and ambient lighting
- Add server virtualization branding badge and typography hierarchy
- Enhance input fields with leading Bootstrap icons and interactive password visibility toggle
- Modernize 2FA/OTP login and signed-out pages to match design language
- Add real-time loading feedback on form submission
2026-09-26 23:22:33 +03:00
catborise
e980aca2ff feat(console): remove deprecated SPICE support in favor of noVNC
- Remove obsolete spice-html5 static assets and SPICE console templates
- Restrict default console types to VNC with migration 0012
- Filter out SPICE in VM creation form and backend capabilities
- Return friendly deprecation notice if legacy VM is opened with SPICE
- Clean up docs, architecture references, and libvirt-bootstrap scripts
2026-09-26 22:43:40 +03:00
catborise
4b55630b2d style(console): fix flake8 E303 blank lines and line length in console tests 2026-09-26 21:45:54 +03:00
catborise
fb55a24009 fix(console): fix unexpected token syntax error in full vnc resize setting 2026-09-26 19:56:34 +03:00
catborise
f19c30840e fix(console): prevent DOM-based XSS in console views and escape JS strings
- Validate and coerce console query parameters (view_only, scale, resize_session, clip_viewport) to strict booleans via to_bool in console/views.py
- Sanitize view parameter to strictly 'lite' or 'full'
- Apply escapejs filter to all JS string interpolations in console-vnc-full.html, console-vnc-lite.html, console-spice-lite.html, and console-xterm.html
- Replace unsafe '| safe' filter in console-spice-lite.html with escapejs
- Add unit tests for XSS query param mitigation and escapejs character encoding
2026-09-26 19:28:22 +03:00
catborise
3d4accf1b4 feat(novnc): upgrade noVNC from 1.2.0 to 1.7.0
- Upgrade vendored noVNC library in static/js/novnc/ from 1.2.0 to 1.7.0
- Remove obsolete IE11 polyfills (promise.js, browser-es-module-loader)
- Preserve custom app/styles/lite.css for embedded lite view
- Update console-vnc-full.html stylesheets, modern icon set, and dialogs
- Modernize console-vnc-full.html startup via UI.start() with Django context mapping
- Dynamically resolve package.json and localization dictionaries via import.meta.url
2026-09-26 18:25:44 +03:00
catborise
57f9f55db7 refactor(console): add RFB connection state guard and micro-delay for key combinations 2026-09-26 16:28:52 +03:00
catborise
59255eda5e fix(linter): sort imports for super-linter and narrow spec type for mypy 2026-09-26 15:39:23 +03:00
catborise
5449e2a9ce style(console): fix isort, black, flake8, and pylint in console app 2026-09-26 15:29:48 +03:00