mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00

Loading an image built with Buildkit in Podman 3.4 messes up its name. The tag somehow becomes the name of the loaded image. We know that older Podman versions are not generally affected, since Podman v3.0.1 on Debian Bullseye works properly. Also, Podman v4.0 is not affected, so it makes sense to target only Podman v3.4 for a fix. The fix is simple, tag the image properly based on the expected tag from `share/image-id.txt` and delete the incorrect tag. Refs containers/podman#16490
210 lines
6.4 KiB
Python
210 lines
6.4 KiB
Python
import os
|
|
import platform
|
|
|
|
import pytest
|
|
from pytest_mock import MockerFixture
|
|
from pytest_subprocess import FakeProcess
|
|
|
|
from dangerzone import container_utils, errors
|
|
from dangerzone.isolation_provider.container import Container
|
|
from dangerzone.isolation_provider.qubes import is_qubes_native_conversion
|
|
from dangerzone.util import get_resource_path
|
|
|
|
from .base import IsolationProviderTermination, IsolationProviderTest
|
|
|
|
# Run the tests in this module only if we can spawn containers.
|
|
if is_qubes_native_conversion():
|
|
pytest.skip("Qubes native conversion is enabled", allow_module_level=True)
|
|
elif os.environ.get("DUMMY_CONVERSION", False):
|
|
pytest.skip("Dummy conversion is enabled", allow_module_level=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def provider() -> Container:
|
|
return Container()
|
|
|
|
|
|
class TestContainer(IsolationProviderTest):
|
|
def test_is_available_raises(self, provider: Container, fp: FakeProcess) -> None:
|
|
"""
|
|
NotAvailableContainerTechException should be raised when
|
|
the "podman image ls" command fails.
|
|
"""
|
|
fp.register_subprocess(
|
|
[container_utils.get_runtime(), "image", "ls"],
|
|
returncode=-1,
|
|
stderr="podman image ls logs",
|
|
)
|
|
with pytest.raises(errors.NotAvailableContainerTechException):
|
|
provider.is_available()
|
|
|
|
def test_is_available_works(self, provider: Container, fp: FakeProcess) -> None:
|
|
"""
|
|
No exception should be raised when the "podman image ls" can return properly.
|
|
"""
|
|
fp.register_subprocess(
|
|
[container_utils.get_runtime(), "image", "ls"],
|
|
)
|
|
provider.is_available()
|
|
|
|
def test_install_raise_if_image_cant_be_installed(
|
|
self, provider: Container, fp: FakeProcess
|
|
) -> None:
|
|
"""When an image installation fails, an exception should be raised"""
|
|
|
|
fp.register_subprocess(
|
|
[container_utils.get_runtime(), "image", "ls"],
|
|
)
|
|
|
|
# First check should return nothing.
|
|
fp.register_subprocess(
|
|
[
|
|
container_utils.get_runtime(),
|
|
"image",
|
|
"list",
|
|
"--format",
|
|
"{{ .Tag }}",
|
|
"dangerzone.rocks/dangerzone",
|
|
],
|
|
occurrences=2,
|
|
)
|
|
|
|
fp.register_subprocess(
|
|
[
|
|
container_utils.get_runtime(),
|
|
"load",
|
|
"-i",
|
|
get_resource_path("container.tar"),
|
|
],
|
|
returncode=-1,
|
|
)
|
|
|
|
with pytest.raises(errors.ImageInstallationException):
|
|
provider.install()
|
|
|
|
def test_install_raises_if_still_not_installed(
|
|
self, provider: Container, fp: FakeProcess
|
|
) -> None:
|
|
"""When an image keep being not installed, it should return False"""
|
|
fp.register_subprocess(
|
|
["podman", "version", "-f", "{{.Client.Version}}"],
|
|
stdout="4.0.0",
|
|
)
|
|
|
|
fp.register_subprocess(
|
|
[container_utils.get_runtime(), "image", "ls"],
|
|
)
|
|
|
|
# First check should return nothing.
|
|
fp.register_subprocess(
|
|
[
|
|
container_utils.get_runtime(),
|
|
"image",
|
|
"list",
|
|
"--format",
|
|
"{{ .Tag }}",
|
|
"dangerzone.rocks/dangerzone",
|
|
],
|
|
occurrences=2,
|
|
)
|
|
|
|
fp.register_subprocess(
|
|
[
|
|
container_utils.get_runtime(),
|
|
"load",
|
|
"-i",
|
|
get_resource_path("container.tar"),
|
|
],
|
|
)
|
|
with pytest.raises(errors.ImageNotPresentException):
|
|
provider.install()
|
|
|
|
@pytest.mark.skipif(
|
|
platform.system() not in ("Windows", "Darwin"),
|
|
reason="macOS and Windows specific",
|
|
)
|
|
def test_old_docker_desktop_version_is_detected(
|
|
self, mocker: MockerFixture, provider: Container, fp: FakeProcess
|
|
) -> None:
|
|
fp.register_subprocess(
|
|
[
|
|
"docker",
|
|
"version",
|
|
"--format",
|
|
"{{.Server.Platform.Name}}",
|
|
],
|
|
stdout="Docker Desktop 1.0.0 (173100)",
|
|
)
|
|
|
|
mocker.patch(
|
|
"dangerzone.isolation_provider.container.MINIMUM_DOCKER_DESKTOP",
|
|
{"Darwin": "1.0.1", "Windows": "1.0.1"},
|
|
)
|
|
assert (False, "1.0.0") == provider.check_docker_desktop_version()
|
|
|
|
@pytest.mark.skipif(
|
|
platform.system() not in ("Windows", "Darwin"),
|
|
reason="macOS and Windows specific",
|
|
)
|
|
def test_up_to_date_docker_desktop_version_is_detected(
|
|
self, mocker: MockerFixture, provider: Container, fp: FakeProcess
|
|
) -> None:
|
|
fp.register_subprocess(
|
|
[
|
|
"docker",
|
|
"version",
|
|
"--format",
|
|
"{{.Server.Platform.Name}}",
|
|
],
|
|
stdout="Docker Desktop 1.0.1 (173100)",
|
|
)
|
|
|
|
# Require version 1.0.1
|
|
mocker.patch(
|
|
"dangerzone.isolation_provider.container.MINIMUM_DOCKER_DESKTOP",
|
|
{"Darwin": "1.0.1", "Windows": "1.0.1"},
|
|
)
|
|
assert (True, "1.0.1") == provider.check_docker_desktop_version()
|
|
|
|
fp.register_subprocess(
|
|
[
|
|
"docker",
|
|
"version",
|
|
"--format",
|
|
"{{.Server.Platform.Name}}",
|
|
],
|
|
stdout="Docker Desktop 2.0.0 (173100)",
|
|
)
|
|
assert (True, "2.0.0") == provider.check_docker_desktop_version()
|
|
|
|
@pytest.mark.skipif(
|
|
platform.system() not in ("Windows", "Darwin"),
|
|
reason="macOS and Windows specific",
|
|
)
|
|
def test_docker_desktop_version_failure_returns_true(
|
|
self, mocker: MockerFixture, provider: Container, fp: FakeProcess
|
|
) -> None:
|
|
fp.register_subprocess(
|
|
[
|
|
"docker",
|
|
"version",
|
|
"--format",
|
|
"{{.Server.Platform.Name}}",
|
|
],
|
|
stderr="Oopsie",
|
|
returncode=1,
|
|
)
|
|
assert provider.check_docker_desktop_version() == (True, "")
|
|
|
|
@pytest.mark.skipif(
|
|
platform.system() != "Linux",
|
|
reason="Linux specific",
|
|
)
|
|
def test_linux_skips_desktop_version_check_returns_true(
|
|
self, provider: Container
|
|
) -> None:
|
|
assert (True, "") == provider.check_docker_desktop_version()
|
|
|
|
|
|
class TestContainerTermination(IsolationProviderTermination):
|
|
pass
|