mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-09 19:56:48 +00:00
test: test files named by their topic, one file per topic
- console settings were split over four files; who sees the form, the listen address, and the settings themselves are test_console_settings, and who may open a console is test_console_access; - the three template files are test_templates; - the quota lock test joins test_quota; - accounts' test_security_fixes held two topics: the SSH key tests are test_ssh_keys, the owner-row delete redirect is in test_views; - instances' test_security_mutations, who may change a VM, is test_permissions. The suite runs the same 2097 tests.
This commit is contained in:
parent
bdc8a6755c
commit
f3003bb414
15 changed files with 541 additions and 606 deletions
|
|
@ -1,64 +0,0 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from accounts.models import UserInstance, UserSSHKey
|
||||
from accounts.utils import validate_ssh_key
|
||||
from computes.models import Compute
|
||||
from instances.models import Instance
|
||||
|
||||
|
||||
class AccountsSecurityFixesTestCase(TestCase):
|
||||
def setUp(self):
|
||||
User = get_user_model()
|
||||
self.admin = User.objects.create_superuser(
|
||||
username="sec_acc_admin", email="admin@example.com", password="password"
|
||||
)
|
||||
self.user = User.objects.create_user(
|
||||
username="sec_acc_user", password="password"
|
||||
)
|
||||
self.compute = Compute.objects.create(
|
||||
name="acc-comp", hostname="127.0.0.1", login="root", type=1
|
||||
)
|
||||
self.instance = Instance.objects.create(
|
||||
compute=self.compute, name="acc-vm", uuid="99999999-9999-9999-9999-999999999999"
|
||||
)
|
||||
self.user_inst = UserInstance.objects.create(
|
||||
instance=self.instance, user=self.user
|
||||
)
|
||||
|
||||
def test_open_redirect_prevented_in_user_instance_delete(self):
|
||||
self.client.force_login(self.admin)
|
||||
url = reverse("accounts:user_instance_delete", args=[self.user_inst.id])
|
||||
|
||||
# Attempt external malicious redirect
|
||||
res = self.client.post(f"{url}?next=https://malicious-attacker.com")
|
||||
self.assertEqual(res.status_code, 302)
|
||||
# Should redirect to safe internal URL (user account page), NOT external site
|
||||
self.assertNotIn("malicious-attacker.com", res.url)
|
||||
self.assertEqual(res.url, reverse("accounts:account", args=[self.user.id]))
|
||||
|
||||
def test_ssh_key_cascade_deletion(self):
|
||||
key = UserSSHKey.objects.create(
|
||||
user=self.user,
|
||||
keyname="my-key",
|
||||
keypublic="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGabcdef123456 test@example.com",
|
||||
)
|
||||
self.assertTrue(UserSSHKey.objects.filter(id=key.id).exists())
|
||||
|
||||
# When user is deleted, key should be deleted via CASCADE (not left orphan)
|
||||
self.user.delete()
|
||||
self.assertFalse(UserSSHKey.objects.filter(id=key.id).exists())
|
||||
|
||||
def test_validate_ssh_key_supports_keys_with_and_without_comment(self):
|
||||
rsa_base = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6OOdbfv27QVnSC6sKxGaHb6YFc+3gxCkyVR3cTSXE/n5BEGf8aOgBpepULWa1RZfxYHY14PlKULDygdXSdrrR2kNSwoKz/Oo4d+3EE92L7ocl1+djZbptzgWgtw1OseLwbFik+iKlIdqPsH+IUQvX7yV545ZQtAP8Qj1R+uCqkw=="
|
||||
# Key with comment
|
||||
key_with_comment = f"{rsa_base} test@test"
|
||||
self.assertTrue(validate_ssh_key(key_with_comment))
|
||||
|
||||
# Key without comment
|
||||
key_without_comment = rsa_base
|
||||
self.assertTrue(validate_ssh_key(key_without_comment))
|
||||
|
||||
# Invalid key
|
||||
self.assertFalse(validate_ssh_key("not a valid key string"))
|
||||
35
accounts/tests/test_ssh_keys.py
Normal file
35
accounts/tests/test_ssh_keys.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
"""A user's SSH keys: they go with the user, and a key is valid with or without a comment."""
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.test import TestCase
|
||||
|
||||
from accounts.models import UserSSHKey
|
||||
from accounts.utils import validate_ssh_key
|
||||
|
||||
|
||||
class SshKeyTestCase(TestCase):
|
||||
def test_ssh_key_cascade_deletion(self):
|
||||
user = get_user_model().objects.create_user(username="sec_acc_user", password="password")
|
||||
key = UserSSHKey.objects.create(
|
||||
user=user,
|
||||
keyname="my-key",
|
||||
keypublic="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGabcdef123456 test@example.com",
|
||||
)
|
||||
self.assertTrue(UserSSHKey.objects.filter(id=key.id).exists())
|
||||
|
||||
# When user is deleted, key should be deleted via CASCADE (not left orphan)
|
||||
user.delete()
|
||||
self.assertFalse(UserSSHKey.objects.filter(id=key.id).exists())
|
||||
|
||||
def test_validate_ssh_key_supports_keys_with_and_without_comment(self):
|
||||
rsa_base = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6OOdbfv27QVnSC6sKxGaHb6YFc+3gxCkyVR3cTSXE/n5BEGf8aOgBpepULWa1RZfxYHY14PlKULDygdXSdrrR2kNSwoKz/Oo4d+3EE92L7ocl1+djZbptzgWgtw1OseLwbFik+iKlIdqPsH+IUQvX7yV545ZQtAP8Qj1R+uCqkw=="
|
||||
# Key with comment
|
||||
key_with_comment = f"{rsa_base} test@test"
|
||||
self.assertTrue(validate_ssh_key(key_with_comment))
|
||||
|
||||
# Key without comment
|
||||
key_without_comment = rsa_base
|
||||
self.assertTrue(validate_ssh_key(key_without_comment))
|
||||
|
||||
# Invalid key
|
||||
self.assertFalse(validate_ssh_key("not a valid key string"))
|
||||
|
|
@ -335,3 +335,22 @@ class OwnerRightsReturnTestCase(TestCase):
|
|||
with self.subTest(next_url):
|
||||
response = self.client.post(f"{update}?next={next_url}", {"is_change": True})
|
||||
self.assertRedirects(response, back, fetch_redirect_response=False)
|
||||
|
||||
|
||||
class UserInstanceDeleteTestCase(TestCase):
|
||||
def test_open_redirect_prevented_in_user_instance_delete(self):
|
||||
User = get_user_model()
|
||||
admin = User.objects.create_superuser(username="sec_acc_admin", email="admin@example.com", password="password")
|
||||
user = User.objects.create_user(username="sec_acc_user", password="password")
|
||||
compute = Compute.objects.create(name="acc-comp", hostname="127.0.0.1", login="root", type=1)
|
||||
instance = Instance.objects.create(compute=compute, name="acc-vm", uuid="99999999-9999-9999-9999-999999999999")
|
||||
user_inst = UserInstance.objects.create(instance=instance, user=user)
|
||||
self.client.force_login(admin)
|
||||
url = reverse("accounts:user_instance_delete", args=[user_inst.id])
|
||||
|
||||
# Attempt external malicious redirect
|
||||
res = self.client.post(f"{url}?next=https://malicious-attacker.com")
|
||||
self.assertEqual(res.status_code, 302)
|
||||
# Should redirect to safe internal URL (user account page), NOT external site
|
||||
self.assertNotIn("malicious-attacker.com", res.url)
|
||||
self.assertEqual(res.url, reverse("accounts:account", args=[user.id]))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue