mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
- One searchable card: each secret's type, usage and UUID, whether it is kept on disk or in memory and private, and the VMs and pools that use it, linked. A row menu sets its value or deletes it; Delete is disabled while the secret is in use, and its confirmation says what is not checked. - One Set value dialog for every secret; its label and help follow the type (Ceph key, CHAP password, passphrase), and it says a new passphrase does not encrypt anew what the old one encrypted. - New secret dialog: the usage's and value's labels and help follow the type; the value is optional; Private and Ephemeral are switches with help.
58 lines
3.3 KiB
Python
58 lines
3.3 KiB
Python
"""The secrets page never holds a secret's value: the Set value dialog only
|
|
writes a new one. Each secret shows the VMs and pools that use it, and one in
|
|
use is not offered for deletion."""
|
|
|
|
from unittest.mock import patch
|
|
|
|
from computes.models import Compute
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
from instances.models import Instance
|
|
from lxml import html
|
|
|
|
UUID = "0e5b1f0a-8f3e-4c1a-9d2b-5c6d7e8f9a0b"
|
|
|
|
|
|
class SecretsPageTests(TestCase):
|
|
def page(self, usage_type="ceph", users=None):
|
|
compute = Compute.objects.create(name="secrets-page", hostname="localhost", login="", password="", type=4)
|
|
Instance.objects.create(compute=compute, name="db-1", uuid="00000000-0000-4000-8000-0000000000d1")
|
|
self.client.force_login(get_user_model().objects.create_superuser("page", "page@example.com", "pw"))
|
|
with patch("virtsecrets.views.wvmSecrets") as conn:
|
|
conn.return_value.get_secrets_info.return_value = [
|
|
{"uuid": UUID, "usage_type": usage_type, "usage": "client.libvirt", "ephemeral": False, "private": True}]
|
|
conn.return_value.get_users.return_value = users or {}
|
|
response = self.client.get(reverse("virtsecrets", args=[compute.id]))
|
|
self.assertEqual(response.status_code, 200)
|
|
return html.fromstring(response.content)
|
|
|
|
def test_a_vtpm_secret_is_listed(self):
|
|
self.assertEqual(self.page("vtpm").xpath("//tbody/tr/td[1]/span/text()"), ["vTPM"])
|
|
|
|
def test_the_page_holds_no_secret_value(self):
|
|
field = self.page().get_element_by_id("set_value")
|
|
self.assertIsNone(field.get("value"))
|
|
self.assertEqual(field.get("type"), "password")
|
|
|
|
def test_a_secret_in_use_shows_its_users_and_is_not_deleted(self):
|
|
page = self.page(users={UUID: {"vms": ["db-1", "gone-1"], "pools": ["ceph-rbd"]}})
|
|
instance = Instance.objects.get(name="db-1")
|
|
self.assertEqual(page.xpath("//tbody/tr/td[4]//a/@href")[0], reverse("instances:instance", args=[instance.id]))
|
|
self.assertIn("gone-1", page.xpath("string(//tbody/tr/td[4])"))
|
|
self.assertTrue(page.xpath("//tbody/tr/td[4]//a[contains(., 'ceph-rbd')]"))
|
|
self.assertIsNotNone(page.xpath("//button[@name='delete']")[0].get("disabled"))
|
|
|
|
def test_an_unused_secret_can_be_deleted(self):
|
|
self.assertIsNone(self.page().xpath("//button[@name='delete']")[0].get("disabled"))
|
|
|
|
def test_a_secret_without_usage_is_named_by_its_uuid(self):
|
|
compute = Compute.objects.create(name="secrets-none", hostname="localhost", login="", password="", type=4)
|
|
self.client.force_login(get_user_model().objects.create_superuser("none", "none@example.com", "pw"))
|
|
with patch("virtsecrets.views.wvmSecrets") as conn:
|
|
conn.return_value.get_secrets_info.return_value = [
|
|
{"uuid": UUID, "usage_type": "none", "usage": "", "ephemeral": True, "private": False}]
|
|
conn.return_value.get_users.return_value = {}
|
|
page = html.fromstring(self.client.get(reverse("virtsecrets", args=[compute.id])).content)
|
|
self.assertEqual(page.xpath("//button[@data-bs-target='#SetSecretValue']/@data-usage"), [UUID])
|
|
self.assertEqual(page.xpath("//tbody/tr/td[1]/span/text()"), ["none"])
|