Start making it possible to execute podman inside the VM

This commit is contained in:
Micah Lee 2021-07-01 16:45:25 -07:00
parent c7bd8a317a
commit 2904d44aad
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
5 changed files with 85 additions and 42 deletions

View file

@ -4,12 +4,12 @@ import subprocess
import sys
import pipes
import shutil
import os
import json
# What is the container runtime for this platform?
if platform.system() == "Darwin":
container_tech = "docker"
container_runtime = "/usr/local/bin/docker"
container_tech = "dangerzone-vm"
container_runtime = shutil.which("docker")
elif platform.system() == "Windows":
container_tech = "docker"
container_runtime = shutil.which("docker.exe")
@ -29,24 +29,11 @@ else:
startupinfo = None
def exec_container(args):
args = [container_runtime] + args
def exec(args):
args_str = " ".join(pipes.quote(s) for s in args)
print("> " + args_str)
sys.stdout.flush()
# In Tails, tell the container runtime to download over Tor
if (
platform.system() == "Linux"
and os.getlogin() == "amnesia"
and os.getuid() == 1000
):
env = os.environ.copy()
env["HTTP_PROXY"] = "socks5://127.0.0.1:9050"
else:
env = None
with subprocess.Popen(
args,
stdin=None,
@ -55,12 +42,51 @@ def exec_container(args):
bufsize=1,
universal_newlines=True,
startupinfo=startupinfo,
env=env,
) as p:
p.communicate()
return p.returncode
def exec_vm(args, vm_info):
if container_tech == "dangerzone-vm" and vm_info is None:
print("--vm-info-path required on this platform")
return
args = [
"/usr/bin/ssh",
"-q",
"-i",
vm_info["client_key_path"],
"-p",
vm_info["tunnel_port"],
"-o",
"StrictHostKeyChecking=no",
"user@127.0.0.1",
] + args
return exec(args)
def exec_container(args, vm_info):
if container_tech == "dangerzone-vm" and vm_info is None:
print("--vm-info-path required on this platform")
return
if container_tech == "dangerzone-vm":
args = ["podman"] + args
return exec_vm(args, vm_info)
args = [container_runtime] + args
return exec(args)
def load_vm_info(vm_info_path):
if not vm_info_path:
return None
with open(vm_info_path) as f:
return json.loads(f.read())
@click.group()
def container_main():
"""
@ -71,23 +97,21 @@ def container_main():
@container_main.command()
@click.option("--vm-info-path", default=None)
@click.option("--container-name", default="docker.io/flmcode/dangerzone")
def ls(container_name):
def ls(vm_info_path, container_name):
"""docker image ls [container_name]"""
sys.exit(exec_container(["image", "ls", container_name]))
@container_main.command()
def pull():
"""docker pull flmcode/dangerzone"""
sys.exit(exec_container(["pull", "docker.io/flmcode/dangerzone"]))
sys.exit(
exec_container(["image", "ls", container_name]), load_vm_info(vm_info_path)
)
@container_main.command()
@click.option("--vm-info-path", default=None)
@click.option("--document-filename", required=True)
@click.option("--pixel-dir", required=True)
@click.option("--container-name", default="docker.io/flmcode/dangerzone")
def documenttopixels(document_filename, pixel_dir, container_name):
def documenttopixels(vm_info_path, document_filename, pixel_dir, container_name):
"""docker run --network none -v [document_filename]:/tmp/input_file -v [pixel_dir]:/dangerzone [container_name] document-to-pixels"""
args = ["run", "--network", "none"]
@ -103,16 +127,17 @@ def documenttopixels(document_filename, pixel_dir, container_name):
container_name,
"document-to-pixels",
]
sys.exit(exec_container(args))
sys.exit(exec_container(args, load_vm_info(vm_info_path)))
@container_main.command()
@click.option("--vm-info-path", default=None)
@click.option("--pixel-dir", required=True)
@click.option("--safe-dir", required=True)
@click.option("--container-name", default="docker.io/flmcode/dangerzone")
@click.option("--ocr", required=True)
@click.option("--ocr-lang", required=True)
def pixelstopdf(pixel_dir, safe_dir, container_name, ocr, ocr_lang):
def pixelstopdf(vm_info_path, pixel_dir, safe_dir, container_name, ocr, ocr_lang):
"""docker run --network none -v [pixel_dir]:/dangerzone -v [safe_dir]:/safezone [container_name] -e OCR=[ocr] -e OCR_LANGUAGE=[ocr_lang] pixels-to-pdf"""
sys.exit(
exec_container(
@ -130,6 +155,7 @@ def pixelstopdf(pixel_dir, safe_dir, container_name, ocr, ocr_lang):
f"OCR_LANGUAGE={ocr_lang}",
container_name,
"pixels-to-pdf",
]
],
load_vm_info(vm_info_path),
)
)

View file

@ -443,6 +443,8 @@ class GlobalCommon(object):
def exec_dangerzone_container(self, args):
args = [self.dz_container_path] + args
if self.vm:
args += ["--vm-info-path", self.vm.vm_info_path]
args_str = " ".join(pipes.quote(s) for s in args)
print(Style.DIM + "> " + Style.NORMAL + Fore.CYAN + args_str)

View file

@ -1,9 +1,11 @@
from dangerzone import global_common
import shutil
import os
import platform
import tempfile
import subprocess
from PySide2 import QtCore, QtGui, QtWidgets
from .tasks import ConvertToPixels, ConvertToPDF
from ..common import Common

View file

@ -60,6 +60,7 @@ class Vm(QtCore.QObject):
)
self.sshd_pid_path = os.path.join(self.state_dir.name, "sshd.pid")
self.sshd_log_path = os.path.join(self.state_dir.name, "sshd.log")
self.vm_info_path = os.path.join(self.state_dir.name, "info.json")
self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img")
# UDID for VM
@ -145,8 +146,6 @@ class Vm(QtCore.QObject):
"-o",
"Compression=yes",
"-o",
"ForceCommand=/usr/bin/whoami",
"-o",
"UseDNS=no",
"-o",
f"AuthorizedKeysFile={self.ssh_client_pubkey_path}",
@ -157,7 +156,7 @@ class Vm(QtCore.QObject):
# Create a JSON object to pass into the VM
# This is a 512kb file that starts with a JSON object, followed by null bytes
vm_info = {
guest_vm_info = {
"id_ed25519": ssh_client_key,
"id_ed25519.pub": ssh_client_pubkey,
"user": getpass.getuser(),
@ -166,9 +165,17 @@ class Vm(QtCore.QObject):
"tunnel_port": self.sshd_tunnel_port,
}
with open(self.vm_disk_img_path, "wb") as f:
vm_info_bytes = json.dumps(vm_info).encode()
f.write(vm_info_bytes)
f.write(b"\x00" * (512 * 1024 - len(vm_info_bytes)))
guest_vm_info_bytes = json.dumps(guest_vm_info).encode()
f.write(guest_vm_info_bytes)
f.write(b"\x00" * (512 * 1024 - len(guest_vm_info_bytes)))
# Create a JSON object for the container process to read
vm_info = {
"client_key_path": self.ssh_client_key_path,
"tunnel_port": self.sshd_tunnel_port,
}
with open(self.vm_info_path, "w") as f:
f.write(json.dumps(vm_info))
# Run VPNKit
args = [

View file

@ -31,15 +31,25 @@ def main():
f.write(info["id_ed25519.pub"])
f.write("\n")
with open("/home/user/.ssh/config", "w") as f:
f.write("Host hostbox\n")
f.write(f" Hostname {info['ip']}\n")
f.write(f" Port {info['port']}\n")
f.write(f" User {info['user']}\n")
f.write(" IdentityFile /home/user/.ssh/id_ed25519\n")
f.write("\n")
os.chmod("/home/user/.ssh", 0o700)
os.chmod("/home/user/.ssh/id_ed25519", 0o600)
os.chmod("/home/user/.ssh/id_ed25519.pub", 0o644)
os.chmod("/home/user/.ssh/authorized_keys", 0o600)
os.chmod("/home/user/.ssh/config", 0o600)
shutil.chown("/home/user/.ssh", "user", "user")
shutil.chown("/home/user/.ssh/id_ed25519", "user", "user")
shutil.chown("/home/user/.ssh/id_ed25519.pub", "user", "user")
shutil.chown("/home/user/.ssh/authorized_keys", "user", "user")
shutil.chown("/home/user/.ssh/config", "user", "user")
# Start SSH reverse port forward
subprocess.run(
@ -50,14 +60,10 @@ def main():
"/usr/bin/ssh",
"-o",
"StrictHostKeyChecking=no",
"-i",
"/home/user/.ssh/id_ed25519",
"-N",
"-R",
f"{info['tunnel_port']}:127.0.0.1:22",
"-p",
str(info["port"]),
f"{info['user']}@{info['ip']}",
"hostbox",
]
)