1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
webvirtcloud/storages/tests.py

121 lines
5.4 KiB
Python

import os
import shutil
import tempfile
from unittest.mock import MagicMock, patch
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
from django.urls import reverse
from django.contrib.auth import get_user_model
from computes.models import Compute
from storages.views import handle_uploaded_file
from vrtManager.connection import CONN_SOCKET, CONN_SSH
User = get_user_model()
class StorageUploadSecurityTests(TestCase):
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.mock_socket_conn = MagicMock()
self.mock_socket_conn.conn = CONN_SOCKET
self.mock_ssh_conn = MagicMock()
self.mock_ssh_conn.conn = CONN_SSH
self.mock_ssh_conn.host = "127.0.0.1"
self.mock_ssh_conn.login = "test"
self.mock_ssh_conn.passwd = "test"
def tearDown(self):
shutil.rmtree(self.temp_dir, ignore_errors=True)
def test_handle_uploaded_file_invalid_names(self):
dummy_chunk = SimpleUploadedFile("test.iso", b"data")
invalid_names = ["", " ", ".", "..", "test\x00evil.iso", "../evil.iso", "../../etc/shadow"]
for bad_name in invalid_names:
clean_base = os.path.basename(bad_name).strip()
# bad_name either gets rejected as empty/dot/null or has basename extracted
if not clean_base or clean_base in (".", "..") or "\x00" in clean_base:
with self.assertRaises(ValueError):
handle_uploaded_file(self.mock_socket_conn, self.temp_dir, bad_name, dummy_chunk, is_last_chunk=True)
def test_handle_uploaded_file_successful_socket_upload(self):
dummy_chunk = SimpleUploadedFile("install.iso", b"ISODATA_BLOCK_123")
file_name = "install.iso"
# Chunk 1 (is_last_chunk=False)
handle_uploaded_file(self.mock_socket_conn, self.temp_dir, file_name, dummy_chunk, is_last_chunk=False)
part_path = os.path.join(self.temp_dir, f"{file_name}.part")
final_path = os.path.join(self.temp_dir, file_name)
self.assertTrue(os.path.exists(part_path))
self.assertFalse(os.path.exists(final_path))
# Chunk 2 (is_last_chunk=True)
dummy_chunk2 = SimpleUploadedFile("install.iso", b"_PART2")
handle_uploaded_file(self.mock_socket_conn, self.temp_dir, file_name, dummy_chunk2, is_last_chunk=True)
self.assertFalse(os.path.exists(part_path))
self.assertTrue(os.path.exists(final_path))
with open(final_path, "rb") as f:
self.assertEqual(f.read(), b"ISODATA_BLOCK_123_PART2")
def test_handle_uploaded_file_jail_containment(self):
dummy_chunk = SimpleUploadedFile("test.iso", b"data")
# Attempt traversal outside sandbox
with patch("os.path.basename", side_effect=lambda x: x): # simulate raw traversal name
with self.assertRaises(PermissionError):
handle_uploaded_file(self.mock_socket_conn, self.temp_dir, "../../../evil.iso", dummy_chunk, is_last_chunk=True)
def test_handle_uploaded_file_ssh_traversal_check(self):
dummy_chunk = SimpleUploadedFile("test.iso", b"data")
with patch("os.path.basename", side_effect=lambda x: x):
with self.assertRaises(PermissionError):
handle_uploaded_file(self.mock_ssh_conn, "/var/lib/libvirt/images", "../../../evil.iso", dummy_chunk, is_last_chunk=True)
class StorageUploadViewTests(TestCase):
def setUp(self):
self.admin = User.objects.create_superuser(username="storage_admin", password="password", email="storage_admin@example.com")
self.client.login(username="storage_admin", password="password")
self.compute = Compute.objects.create(name="LocalCompute", hostname="localhost", type=1, login="u", password="p")
@patch("storages.views.wvmStorage")
def test_iso_upload_missing_chunk(self, mock_wvm):
mock_conn = MagicMock()
mock_conn.get_status.return_value = 1
mock_conn.get_target_path.return_value = "/tmp"
mock_conn.get_type.return_value = "dir"
mock_conn.get_autostart.return_value = 1
mock_conn.get_size.return_value = [1000, 500]
mock_conn.update_volumes.return_value = []
mock_wvm.return_value = mock_conn
url = reverse("storage", args=[self.compute.id, "default"])
res = self.client.post(url, {"iso_upload": "1", "file_name": "test.iso"})
self.assertEqual(res.status_code, 400)
self.assertIn("No file chunk was submitted", res.json().get("error", ""))
@patch("storages.views.wvmStorage")
def test_iso_upload_invalid_filename(self, mock_wvm):
mock_conn = MagicMock()
mock_conn.get_status.return_value = 1
mock_conn.get_target_path.return_value = "/tmp"
mock_conn.get_type.return_value = "dir"
mock_conn.get_autostart.return_value = 1
mock_conn.get_size.return_value = [1000, 500]
mock_conn.update_volumes.return_value = []
mock_wvm.return_value = mock_conn
url = reverse("storage", args=[self.compute.id, "default"])
chunk = SimpleUploadedFile("test.iso", b"chunkdata")
res = self.client.post(url, {
"iso_upload": "1",
"file": chunk,
"file_name": "..\x00..",
"chunk_index": "0",
"total_chunks": "1",
})
self.assertEqual(res.status_code, 400)
self.assertIn("Invalid file name", res.json().get("error", ""))