mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-05-18 19:20:35 +02:00
Compare commits
27 commits
06fe63ba9e
...
3cf34e6182
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3cf34e6182 | ||
![]() |
414efb629f | ||
![]() |
6d6ac92371 | ||
![]() |
df1ec758bc | ||
![]() |
9e23802142 | ||
![]() |
7e1f4bca6c | ||
![]() |
a1383fa016 | ||
![]() |
94a57f997e | ||
![]() |
ab10d5b6dd | ||
![]() |
3ebc454b61 | ||
![]() |
20af68f7f2 | ||
![]() |
fa27f4b063 | ||
![]() |
8e8a515b64 | ||
![]() |
270cae1bc0 | ||
![]() |
14bb6c0e39 | ||
![]() |
033ce0986d | ||
![]() |
935396565c | ||
![]() |
e29837cb43 | ||
![]() |
8568b4bb9d | ||
![]() |
be1fa7a395 | ||
![]() |
b2f4e2d523 | ||
![]() |
7409966253 | ||
![]() |
40fb6579f6 | ||
![]() |
6ae91b024e | ||
![]() |
c2841dcc08 | ||
![]() |
df5ccb3f75 | ||
![]() |
9c6c2e1051 |
13 changed files with 512 additions and 417 deletions
|
@ -44,7 +44,7 @@ RUN \
|
||||||
|
|
||||||
# Download H2ORestart from GitHub using a pinned version and hash. Note that
|
# Download H2ORestart from GitHub using a pinned version and hash. Note that
|
||||||
# it's available in Debian repos, but not in Bookworm yet.
|
# it's available in Debian repos, but not in Bookworm yet.
|
||||||
RUN mkdir /libreoffice_ext && cd libreoffice_ext \
|
RUN mkdir /opt/libreoffice_ext && cd /opt/libreoffice_ext \
|
||||||
&& H2ORESTART_FILENAME=h2orestart.oxt \
|
&& H2ORESTART_FILENAME=h2orestart.oxt \
|
||||||
&& wget https://github.com/ebandal/H2Orestart/releases/download/$H2ORESTART_VERSION/$H2ORESTART_FILENAME \
|
&& wget https://github.com/ebandal/H2Orestart/releases/download/$H2ORESTART_VERSION/$H2ORESTART_FILENAME \
|
||||||
&& echo "$H2ORESTART_CHECKSUM $H2ORESTART_FILENAME" | sha256sum -c \
|
&& echo "$H2ORESTART_CHECKSUM $H2ORESTART_FILENAME" | sha256sum -c \
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
ARG DEBIAN_IMAGE_DATE={{DEBIAN_IMAGE_DATE}}
|
ARG DEBIAN_IMAGE_DATE={{DEBIAN_IMAGE_DATE}}
|
||||||
|
|
||||||
FROM debian:bookworm-${DEBIAN_IMAGE_DATE}-slim
|
FROM debian:bookworm-${DEBIAN_IMAGE_DATE}-slim as dangerzone-image
|
||||||
|
|
||||||
ARG GVISOR_ARCHIVE_DATE={{GVISOR_ARCHIVE_DATE}}
|
ARG GVISOR_ARCHIVE_DATE={{GVISOR_ARCHIVE_DATE}}
|
||||||
ARG DEBIAN_ARCHIVE_DATE={{DEBIAN_ARCHIVE_DATE}}
|
ARG DEBIAN_ARCHIVE_DATE={{DEBIAN_ARCHIVE_DATE}}
|
||||||
|
@ -44,7 +44,7 @@ RUN \
|
||||||
|
|
||||||
# Download H2ORestart from GitHub using a pinned version and hash. Note that
|
# Download H2ORestart from GitHub using a pinned version and hash. Note that
|
||||||
# it's available in Debian repos, but not in Bookworm yet.
|
# it's available in Debian repos, but not in Bookworm yet.
|
||||||
RUN mkdir /libreoffice_ext && cd libreoffice_ext \
|
RUN mkdir /opt/libreoffice_ext && cd /opt/libreoffice_ext \
|
||||||
&& H2ORESTART_FILENAME=h2orestart.oxt \
|
&& H2ORESTART_FILENAME=h2orestart.oxt \
|
||||||
&& wget https://github.com/ebandal/H2Orestart/releases/download/$H2ORESTART_VERSION/$H2ORESTART_FILENAME \
|
&& wget https://github.com/ebandal/H2Orestart/releases/download/$H2ORESTART_VERSION/$H2ORESTART_FILENAME \
|
||||||
&& echo "$H2ORESTART_CHECKSUM $H2ORESTART_FILENAME" | sha256sum -c \
|
&& echo "$H2ORESTART_CHECKSUM $H2ORESTART_FILENAME" | sha256sum -c \
|
||||||
|
@ -64,18 +64,71 @@ RUN touch /opt/dangerzone/dangerzone/__init__.py
|
||||||
# Copy only the Python code, and not any produced .pyc files.
|
# Copy only the Python code, and not any produced .pyc files.
|
||||||
COPY conversion/*.py /opt/dangerzone/dangerzone/conversion/
|
COPY conversion/*.py /opt/dangerzone/dangerzone/conversion/
|
||||||
|
|
||||||
# Let the entrypoint script write the OCI config for the inner container under
|
|
||||||
# /config.json.
|
|
||||||
RUN touch /config.json
|
|
||||||
RUN chown dangerzone:dangerzone /config.json
|
|
||||||
|
|
||||||
# Switch to the dangerzone user for the rest of the script.
|
|
||||||
USER dangerzone
|
|
||||||
|
|
||||||
# Create a directory that will be used by gVisor as the place where it will
|
# Create a directory that will be used by gVisor as the place where it will
|
||||||
# store the state of its containers.
|
# store the state of its containers.
|
||||||
RUN mkdir /home/dangerzone/.containers
|
RUN mkdir /home/dangerzone/.containers
|
||||||
|
|
||||||
|
# XXX: Create a new root hierarchy, that will be used in the final container
|
||||||
|
# image:
|
||||||
|
#
|
||||||
|
# /bin -> usr/bin
|
||||||
|
# /lib -> usr/lib
|
||||||
|
# /lib64 -> usr/lib64
|
||||||
|
# /root
|
||||||
|
# /run
|
||||||
|
# /tmp
|
||||||
|
# /usr -> /home/dangerzone/dangerzone-image/rootfs/usr/
|
||||||
|
#
|
||||||
|
# We have to create this hierarchy beforehand because we want to use the same
|
||||||
|
# /usr for both the inner and outer container. The problem though is that /usr
|
||||||
|
# is very sensitive, and you can't manipulate in a live system. That is, I
|
||||||
|
# haven't found a way to do the following, or something equivalent:
|
||||||
|
#
|
||||||
|
# rm -r /usr && ln -s /home/dangerzone/dangerzone-image/rootfs/usr/ /usr
|
||||||
|
#
|
||||||
|
# So, we prefer to create the symlinks here instead, and create the image
|
||||||
|
# manually in the next steps.
|
||||||
|
RUN mkdir /new_root
|
||||||
|
RUN mkdir /new_root/root /new_root/run /new_root/tmp
|
||||||
|
RUN chmod 777 /new_root/tmp
|
||||||
|
RUN ln -s /home/dangerzone/dangerzone-image/rootfs/usr/ /new_root/usr
|
||||||
|
RUN ln -s usr/bin /new_root/bin
|
||||||
|
RUN ln -s usr/lib /new_root/lib
|
||||||
|
RUN ln -s usr/lib64 /new_root/lib64
|
||||||
|
RUN ln -s usr/sbin /new_root/sbin
|
||||||
|
|
||||||
|
# Intermediate layer
|
||||||
|
|
||||||
|
FROM debian:bookworm-${DEBIAN_IMAGE_DATE}-slim as debian-utils
|
||||||
|
|
||||||
|
## Final image
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
# Copy the filesystem hierarchy that we created in the previous layer, so that
|
||||||
|
# /usr can be a symlink.
|
||||||
|
COPY --from=dangerzone-image /new_root/ /
|
||||||
|
|
||||||
|
# Copy some files that are necessary to use the outer container image, e.g., in
|
||||||
|
# order to run `apt`. We _could_ avoid doing this, but the space cost is very
|
||||||
|
# small.
|
||||||
|
COPY --from=dangerzone-image /etc/ /etc/
|
||||||
|
COPY --from=debian-utils /var/ /var/
|
||||||
|
|
||||||
|
# Copy the bare minimum to run Dangerzone in the inner container image.
|
||||||
|
COPY --from=dangerzone-image /etc/ /home/dangerzone/dangerzone-image/rootfs/etc/
|
||||||
|
COPY --from=dangerzone-image /usr/ /home/dangerzone/dangerzone-image/rootfs/usr/
|
||||||
|
COPY --from=dangerzone-image /opt/ /home/dangerzone/dangerzone-image/rootfs/opt/
|
||||||
|
RUN ln -s usr/bin /home/dangerzone/dangerzone-image/rootfs/bin
|
||||||
|
RUN ln -s usr/lib /home/dangerzone/dangerzone-image/rootfs/lib
|
||||||
|
RUN ln -s usr/lib64 /home/dangerzone/dangerzone-image/rootfs/lib64
|
||||||
|
|
||||||
|
# Allow our entrypoint script to make changes in the following folders.
|
||||||
|
RUN chown dangerzone:dangerzone /home/dangerzone /home/dangerzone/dangerzone-image/
|
||||||
|
|
||||||
|
# Switch to the dangerzone user for the rest of the script.
|
||||||
|
USER dangerzone
|
||||||
|
|
||||||
COPY container_helpers/entrypoint.py /
|
COPY container_helpers/entrypoint.py /
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.py"]
|
ENTRYPOINT ["/entrypoint.py"]
|
||||||
|
|
|
@ -302,7 +302,7 @@ def display_banner() -> None:
|
||||||
+ Back.BLACK
|
+ Back.BLACK
|
||||||
+ Fore.LIGHTWHITE_EX
|
+ Fore.LIGHTWHITE_EX
|
||||||
+ Style.BRIGHT
|
+ Style.BRIGHT
|
||||||
+ f"{' '*left_spaces}Dangerzone v{get_version()}{' '*right_spaces}"
|
+ f"{' ' * left_spaces}Dangerzone v{get_version()}{' ' * right_spaces}"
|
||||||
+ Fore.YELLOW
|
+ Fore.YELLOW
|
||||||
+ Style.DIM
|
+ Style.DIM
|
||||||
+ "│"
|
+ "│"
|
||||||
|
|
|
@ -153,21 +153,6 @@ oci_config: dict[str, typing.Any] = {
|
||||||
"source": "tmpfs",
|
"source": "tmpfs",
|
||||||
"options": ["nosuid", "noexec", "nodev"],
|
"options": ["nosuid", "noexec", "nodev"],
|
||||||
},
|
},
|
||||||
# Also mask some files that are usually mounted by Docker / Podman. These files
|
|
||||||
# should not contain any sensitive information, since we use the `--network
|
|
||||||
# none` flag, but we want to make sure in any case.
|
|
||||||
{
|
|
||||||
"destination": "/etc/hostname",
|
|
||||||
"type": "bind",
|
|
||||||
"source": "/dev/null",
|
|
||||||
"options": ["rbind", "ro"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/etc/hosts",
|
|
||||||
"type": "bind",
|
|
||||||
"source": "/dev/null",
|
|
||||||
"options": ["rbind", "ro"],
|
|
||||||
},
|
|
||||||
# LibreOffice needs a writable home directory, so just mount a tmpfs
|
# LibreOffice needs a writable home directory, so just mount a tmpfs
|
||||||
# over it.
|
# over it.
|
||||||
{
|
{
|
||||||
|
|
|
@ -253,7 +253,7 @@ class DocumentToPixels(DangerzoneConverter):
|
||||||
"unzip",
|
"unzip",
|
||||||
"-d",
|
"-d",
|
||||||
f"/usr/lib/libreoffice/share/extensions/{libreoffice_ext}/",
|
f"/usr/lib/libreoffice/share/extensions/{libreoffice_ext}/",
|
||||||
f"/libreoffice_ext/{libreoffice_ext}",
|
f"/opt/libreoffice_ext/{libreoffice_ext}",
|
||||||
]
|
]
|
||||||
await self.run_command(
|
await self.run_command(
|
||||||
unzip_args,
|
unzip_args,
|
||||||
|
|
|
@ -335,9 +335,9 @@ class IsolationProvider(ABC):
|
||||||
stderr_thread = self.start_stderr_thread(p, stderr)
|
stderr_thread = self.start_stderr_thread(p, stderr)
|
||||||
|
|
||||||
if platform.system() != "Windows":
|
if platform.system() != "Windows":
|
||||||
assert os.getpgid(p.pid) != os.getpgid(
|
assert os.getpgid(p.pid) != os.getpgid(os.getpid()), (
|
||||||
os.getpid()
|
"Parent shares same PGID with child"
|
||||||
), "Parent shares same PGID with child"
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield p
|
yield p
|
||||||
|
|
|
@ -5,11 +5,14 @@ import sys
|
||||||
import traceback
|
import traceback
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
import appdirs
|
try:
|
||||||
|
import platformdirs
|
||||||
|
except ImportError:
|
||||||
|
import appdirs as platformdirs
|
||||||
|
|
||||||
|
|
||||||
def get_config_dir() -> str:
|
def get_config_dir() -> str:
|
||||||
return appdirs.user_config_dir("dangerzone")
|
return platformdirs.user_config_dir("dangerzone")
|
||||||
|
|
||||||
|
|
||||||
def get_resource_path(filename: str) -> str:
|
def get_resource_path(filename: str) -> str:
|
||||||
|
|
2
debian/control
vendored
2
debian/control
vendored
|
@ -9,7 +9,7 @@ Rules-Requires-Root: no
|
||||||
|
|
||||||
Package: dangerzone
|
Package: dangerzone
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${misc:Depends}, ${python3:Depends}, podman, python3, python3-pyside2.qtcore, python3-pyside2.qtgui, python3-pyside2.qtwidgets, python3-pyside2.qtsvg, python3-appdirs, python3-click, python3-xdg, python3-colorama, python3-requests, python3-markdown, python3-packaging, tesseract-ocr-all
|
Depends: ${misc:Depends}, podman, python3, python3-pyside2.qtcore, python3-pyside2.qtgui, python3-pyside2.qtwidgets, python3-pyside2.qtsvg, python3-platformdirs | python3-appdirs, python3-click, python3-xdg, python3-colorama, python3-requests, python3-markdown, python3-packaging, tesseract-ocr-all
|
||||||
Description: Take potentially dangerous PDFs, office documents, or images
|
Description: Take potentially dangerous PDFs, office documents, or images
|
||||||
Dangerzone is an open source desktop application that takes potentially dangerous PDFs, office documents, or images and converts them to safe PDFs. It uses disposable VMs on Qubes OS, or container technology in other OSes, to convert the documents within a secure sandbox.
|
Dangerzone is an open source desktop application that takes potentially dangerous PDFs, office documents, or images and converts them to safe PDFs. It uses disposable VMs on Qubes OS, or container technology in other OSes, to convert the documents within a secure sandbox.
|
||||||
.
|
.
|
||||||
|
|
|
@ -21,7 +21,7 @@ IMAGE_NAME = "dangerzone.rocks/dangerzone"
|
||||||
|
|
||||||
def run(*args):
|
def run(*args):
|
||||||
"""Simple function that runs a command, validates it, and returns the output"""
|
"""Simple function that runs a command, validates it, and returns the output"""
|
||||||
logger.debug(f"Running command: {" ".join(args)}")
|
logger.debug(f"Running command: {' '.join(args)}")
|
||||||
return subprocess.run(
|
return subprocess.run(
|
||||||
args,
|
args,
|
||||||
check=True,
|
check=True,
|
||||||
|
|
|
@ -226,6 +226,11 @@ convert the documents within a secure sandbox.
|
||||||
sed -i 's/<3.13/<3.14/' pyproject.toml
|
sed -i 's/<3.13/<3.14/' pyproject.toml
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
# Bypass the version pin for Fedora as the 6.8.1.1 package is causing trouble
|
||||||
|
# A 6.8.1.1 package was only released with a wheel for macOS, but was picked by
|
||||||
|
# Fedora packagers. We cannot use "*" when PyPI is involved as it will fail to download the latest version.
|
||||||
|
# For Fedora, we can pick any of the released versions.
|
||||||
|
sed -i '/shiboken6 = \[/,/\]/c\shiboken6 = "*"' pyproject.toml
|
||||||
|
|
||||||
%generate_buildrequires
|
%generate_buildrequires
|
||||||
%pyproject_buildrequires -R
|
%pyproject_buildrequires -R
|
||||||
|
|
798
poetry.lock
generated
798
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,7 @@ include = [
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = ">=3.9,<3.13"
|
python = ">=3.9,<3.13"
|
||||||
click = "*"
|
click = "*"
|
||||||
appdirs = "*"
|
platformdirs = "*"
|
||||||
PySide6 = "^6.7.1"
|
PySide6 = "^6.7.1"
|
||||||
PyMuPDF = "^1.23.3" # The version in Fedora 39
|
PyMuPDF = "^1.23.3" # The version in Fedora 39
|
||||||
colorama = "*"
|
colorama = "*"
|
||||||
|
@ -23,6 +23,13 @@ pyxdg = {version = "*", platform = "linux"}
|
||||||
requests = "*"
|
requests = "*"
|
||||||
markdown = "*"
|
markdown = "*"
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
|
# shiboken6 released a 6.8.1.1 version only for macOS
|
||||||
|
# and it's getting picked by poetry, so pin it instead.
|
||||||
|
shiboken6 = [
|
||||||
|
{version = "*", platform = "darwin"},
|
||||||
|
{version = "<6.8.1.1", platform = "linux"},
|
||||||
|
{version = "<6.8.1.1", platform = "win32"},
|
||||||
|
]
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
dangerzone = 'dangerzone:main'
|
dangerzone = 'dangerzone:main'
|
||||||
|
|
|
@ -12,9 +12,9 @@ VERSION_FILE_NAME = "version.txt"
|
||||||
def test_get_resource_path() -> None:
|
def test_get_resource_path() -> None:
|
||||||
share_dir = Path("share").resolve()
|
share_dir = Path("share").resolve()
|
||||||
resource_path = Path(util.get_resource_path(VERSION_FILE_NAME)).parent
|
resource_path = Path(util.get_resource_path(VERSION_FILE_NAME)).parent
|
||||||
assert share_dir.samefile(
|
assert share_dir.samefile(resource_path), (
|
||||||
resource_path
|
f"{share_dir} is not the same file as {resource_path}"
|
||||||
), f"{share_dir} is not the same file as {resource_path}"
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(platform.system() != "Windows", reason="Windows-specific")
|
@pytest.mark.skipif(platform.system() != "Windows", reason="Windows-specific")
|
||||||
|
|
Loading…
Reference in a new issue