1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
webvirtcloud/instances/tests/test_console_settings_access.py
catborise ac8ff62e7e feat(instances): USB devices of the host given to a VM
- A Host devices tab on the VM page lists the VM's USB host devices, each
  once: how it is chosen (its address, or any device of its model), the
  device the running VM holds and whether its next start has it; its other
  host devices (PCI, SCSI, mediated) are listed for the XML editor.
- Superusers add a USB device of the host and take it back, on a running
  VM too. The add form is loaded when the tab opens, as its choices read
  every VM of the host; a hub, a device the host has its own disks or
  network interfaces on, or one another VM names is not offered, with the
  reason, and refused on the server under the compute's claim. A device is
  chosen by model when the host has one of it, else by its address.
- A VM without a USB controller is refused; a device is taken from each
  definition as that definition describes it.
- A clone gets none of the VM's host devices (the clone form says so), and
  a VM with host devices is not migrated. A snapshot revert is refused when
  it would give the VM a device another VM names or the host uses.
- A NIC that is a host device is no longer edited or removed from the
  Network tab: the XML editor changes it.
2026-10-29 13:33:23 +03:00

88 lines
3.8 KiB
Python

"""
The console settings form on the VM detail page carries the VNC password
(PasswordInput(render_value=True)). It must only be rendered for users who may
change console settings, which is the rule update_console enforces: a
superuser, or an owner with both is_change and is_vnc. In particular, is_staff
and the global view_instances permission must not reveal the VNC password.
"""
from unittest.mock import PropertyMock, patch
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.test import TestCase
from django.urls import reverse
from accounts.models import UserInstance
from computes.models import Compute
from instances.models import Instance
VNC_PASSWORD = "s3cretVNCpass"
class ConsoleSettingsAccessTestCase(TestCase):
def setUp(self):
User = get_user_model()
view_perm = Permission.objects.get(codename="view_instances")
self.superuser = User.objects.create_superuser(
username="vncpw_super", email="vncpw_super@example.com", password="x"
)
self.staff_viewer = User.objects.create_user(
username="vncpw_staff_viewer", password="x", is_staff=True
)
self.staff_viewer.user_permissions.add(view_perm)
self.staff_owner = User.objects.create_user(
username="vncpw_staff_owner", password="x", is_staff=True
)
self.vnc_owner = User.objects.create_user(username="vncpw_vnc_owner", password="x")
self.compute = Compute.objects.create(
name="vncpw-compute", hostname="127.0.0.1:1", login="root", password="", type=1
)
self.instance = Instance.objects.create(
compute=self.compute,
name="vncpw-vm",
uuid="cccccccc-dddd-eeee-ffff-000000000000",
)
UserInstance.objects.create(
instance=self.instance, user=self.staff_owner, is_change=True, is_vnc=False
)
UserInstance.objects.create(
instance=self.instance, user=self.vnc_owner, is_change=True, is_vnc=True
)
def _detail_page(self, user):
self.client.force_login(user)
with patch("instances.models.wvmInstance") as mock_wvm, patch.object(
Compute, "status", new_callable=PropertyMock, return_value=True
):
proxy = mock_wvm.return_value
proxy.get_memory.return_value = 1024
proxy.get_cur_memory.return_value = 1024
proxy.get_max_memory.return_value = 4096
proxy.get_networks.return_value = []
proxy.get_ifaces.return_value = []
proxy.get_hostdevs.return_value = ([], [])
proxy.get_storages.return_value = []
proxy.get_console_passwd.return_value = VNC_PASSWORD
proxy.get_console_type.return_value = "vnc"
proxy.get_status.return_value = 5
proxy.get_disk_devices.return_value = []
proxy.get_media_devices.return_value = []
proxy.get_net_devices.return_value = []
response = self.client.get(
reverse("instances:instance", args=[self.instance.id])
)
self.assertEqual(response.status_code, 200)
return response.content.decode()
def test_staff_with_view_instances_does_not_see_vnc_password(self):
self.assertFalse(VNC_PASSWORD in self._detail_page(self.staff_viewer), "VNC password leaked")
def test_staff_owner_without_is_vnc_does_not_see_vnc_password(self):
self.assertFalse(VNC_PASSWORD in self._detail_page(self.staff_owner), "VNC password leaked")
def test_owner_with_is_change_and_is_vnc_sees_console_settings(self):
self.assertTrue(VNC_PASSWORD in self._detail_page(self.vnc_owner), "console settings missing")
def test_superuser_sees_console_settings(self):
self.assertTrue(VNC_PASSWORD in self._detail_page(self.superuser), "console settings missing")