mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-12-19 04:47:54 +00:00
Impoved docker volumes user input validation
This commit is contained in:
parent
0c19bc8d43
commit
81ddb0cfe6
@ -26,6 +26,7 @@ import shlex
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||||
from gns3server.utils.asyncio.raw_command_server import AsyncioRawCommandServer
|
from gns3server.utils.asyncio.raw_command_server import AsyncioRawCommandServer
|
||||||
@ -255,12 +256,15 @@ class DockerVM(BaseNode):
|
|||||||
self._volumes = ["/etc/network"]
|
self._volumes = ["/etc/network"]
|
||||||
volumes = list((image_info.get("Config", {}).get("Volumes") or {}).keys())
|
volumes = list((image_info.get("Config", {}).get("Volumes") or {}).keys())
|
||||||
for volume in self._extra_volumes:
|
for volume in self._extra_volumes:
|
||||||
if not volume.strip() or volume[0] != "/":
|
if not volume.strip() or volume[0] != "/" or volume.find("..") >= 0:
|
||||||
raise DockerError("Additional volume '{}' has invalid format.".format(volume))
|
raise DockerError("Persistent volume '{}' has invalid format. It must start with a '/' and not contain '..'.".format(volume))
|
||||||
volumes.extend(self._extra_volumes)
|
volumes.extend(self._extra_volumes)
|
||||||
|
# define lambdas for validation checks
|
||||||
|
nf = lambda x: re.sub(r"//+", "/", (x if x.endswith("/") else x + "/"))
|
||||||
|
incompatible = lambda v1, v2: nf(v1).startswith(nf(v2)) or nf(v2).startswith(nf(v1))
|
||||||
for volume in volumes:
|
for volume in volumes:
|
||||||
if volume in self._volumes:
|
if [ v for v in self._volumes if incompatible(v, volume) ] :
|
||||||
raise DockerError("Duplicate persistent volume {}".format(volume))
|
raise DockerError("Duplicate persistent volume {} detected.\n\nVolumes specified in docker image as well as user specified persistent volumes must be unique.".format(volume))
|
||||||
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
|
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
|
||||||
os.makedirs(source, exist_ok=True)
|
os.makedirs(source, exist_ok=True)
|
||||||
binds.append("{}:/gns3volumes{}".format(source, volume))
|
binds.append("{}:/gns3volumes{}".format(source, volume))
|
||||||
|
@ -483,6 +483,18 @@ def test_create_with_extra_volumes_invalid_format_2(loop, project, manager):
|
|||||||
with pytest.raises(DockerError):
|
with pytest.raises(DockerError):
|
||||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||||
|
|
||||||
|
def test_create_with_extra_volumes_invalid_format_3(loop, project, manager):
|
||||||
|
|
||||||
|
response = {
|
||||||
|
"Id": "e90e34656806",
|
||||||
|
"Warnings": []
|
||||||
|
}
|
||||||
|
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
|
||||||
|
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||||
|
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol1/.."])
|
||||||
|
with pytest.raises(DockerError):
|
||||||
|
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||||
|
|
||||||
def test_create_with_extra_volumes_duplicate_1_image(loop, project, manager):
|
def test_create_with_extra_volumes_duplicate_1_image(loop, project, manager):
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
@ -512,6 +524,30 @@ def test_create_with_extra_volumes_duplicate_2_user(loop, project, manager):
|
|||||||
with pytest.raises(DockerError):
|
with pytest.raises(DockerError):
|
||||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||||
|
|
||||||
|
def test_create_with_extra_volumes_duplicate_3_subdir(loop, project, manager):
|
||||||
|
|
||||||
|
response = {
|
||||||
|
"Id": "e90e34656806",
|
||||||
|
"Warnings": [],
|
||||||
|
}
|
||||||
|
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
|
||||||
|
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||||
|
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol/1/", "/vol"])
|
||||||
|
with pytest.raises(DockerError):
|
||||||
|
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||||
|
|
||||||
|
def test_create_with_extra_volumes_duplicate_4_backslash(loop, project, manager):
|
||||||
|
|
||||||
|
response = {
|
||||||
|
"Id": "e90e34656806",
|
||||||
|
"Warnings": [],
|
||||||
|
}
|
||||||
|
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
|
||||||
|
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||||
|
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol//", "/vol"])
|
||||||
|
with pytest.raises(DockerError):
|
||||||
|
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||||
|
|
||||||
def test_create_with_extra_volumes(loop, project, manager):
|
def test_create_with_extra_volumes(loop, project, manager):
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
|
Loading…
Reference in New Issue
Block a user