freedomofpress / dangerzone

Take potentially dangerous PDFs, office documents, or images and convert them to safe PDFs
https://dangerzone.rocks/
GNU Affero General Public License v3.0
3.58k stars 168 forks source link

Add Podman Desktop support on Windows and OSX #925

Open almet opened 1 week ago

almet commented 1 week ago

As part of the search for alternatives to docker desktop (which is closed source) on OSX and windows (see #118), I tried Podman desktop, which is provided under an Apache2 license.

We still need some more discussion about which technology would be the best for us, but at least I'm happy to report that I was able to run it both via CLI and in the GUI, with minimal changes in how we detect the "runtimes".

Including a patch here in case it helps, which shortcuts the detection of the container tech to podman, and hardcodes the path to the binary, which obviously is not ideal, but was done just to check it would work :


diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py
index 7d4e3c6..5585e95 100644
--- a/dangerzone/gui/main_window.py
+++ b/dangerzone/gui/main_window.py
@@ -511,7 +511,7 @@ class WaitingWidgetContainer(WaitingWidget):

     def state_change(self, state: str, error: Optional[str] = None) -> None:
         if state == "not_installed":
-            if platform.system() == "Linux":
+            if self.dangerzone.isolation_provider.get_runtime_name() == "podman":
                 self.label.setText(
                     "<strong>Dangerzone requires Podman</strong><br><br>"
                     "Install it and retry."
@@ -524,7 +524,7 @@ class WaitingWidgetContainer(WaitingWidget):
                 )
             self.buttons.show()
         elif state == "not_running":
-            if platform.system() == "Linux":
+            if self.dangerzone.isolation_provider.get_runtime_name() == "podman":
                 # "not_running" here means that the `podman image ls` command failed.
                 message = (
                     "<strong>Dangerzone requires Podman</strong><br><br>"
diff --git a/dangerzone/isolation_provider/container.py b/dangerzone/isolation_provider/container.py
index 7137d57..2378e36 100644
--- a/dangerzone/isolation_provider/container.py
+++ b/dangerzone/isolation_provider/container.py

@@ -40,6 +43,7 @@ class Container(IsolationProvider):

     @staticmethod
     def get_runtime_name() -> str:
+        return "podman"
         if platform.system() == "Linux":
             runtime_name = "podman"
         else:
@@ -64,7 +68,7 @@ class Container(IsolationProvider):
         else:
             query = "{{.Server.Version}}"

-        cmd = [runtime, "version", "-f", query]
+        cmd = [Container.get_runtime(), "version", "-f", query]
         try:
             version = subprocess.run(
                 cmd,
@@ -91,7 +95,7 @@ class Container(IsolationProvider):
     @staticmethod
     def get_runtime() -> str:
         container_tech = Container.get_runtime_name()
-        runtime = shutil.which(container_tech)
+        runtime = "/opt/podman/bin/podman"
         if runtime is None:
             raise NoContainerTechException(container_tech)
         return runtime
deeplow commented 1 week ago

After reading the gVisor blog post it occurred to me now that Docker became only a portability layer there is not such a pressure to ensure this is always up to date:

[...] By doing so, Dangerzone now has two containers with different responsibilities:

  • The outer Docker/Podman container acts as the portability layer for Dangerzone. Its main responsibility is to bundle the necessary config files, scripts, and programs to run gVisor. It’s also responsible for bundling the container image that gVisor will spawn a container from.
    • The inner gVisor container acts as the isolation layer for Dangerzone. Its sole responsibility is to run the actual Dangerzone logic for rendering documents to pixels.

https://dangerzone.rocks/news/2024-09-23-gvisor/

What I'm implying is that we could even bundle podman (the non-desktop version) in Dangerzone's installer. This way the user user not be bothered at all by any extra user interface.

There are of course-edge cases that need to be considered:

EtiennePerot commented 1 week ago

what happens if we bundle podman and the user also happens to be a developer using podman for something else?

podman (and other OCI container runtimes) can be directed to store all their files in a specific directory using the --root flag. If Dangerzone were to bundle podman inside of it, it could specify --root to point to some directory owned by Dangerzone, and this would avoid interfering with any other non-Dangerzone containers or podman installations on the machine.

deeplow commented 1 week ago

Oh, great! Then that's a non-issue! (Updated the original comment)

almet commented 1 week ago

That's a very good idea, thanks! It would simplify our life with {Docker, Podman} Desktop versions compatibility (on Windows and OSX, at least). That's pretty exciting, thanks for bringing it up.

apyrgio commented 1 week ago

Bringing this comment to your attention as well: https://github.com/freedomofpress/dangerzone/issues/736#issuecomment-1971782435

I have a small reservation (not verified yet), that {Podman,Docker} Desktop are also responsible for the instrumentation of the Linux VM. The binaries we're talking about are just the clients to the container engine (within the VM), and I guess they are the easy part to vendor within our project. Let's find out though.