Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ test-app: test-prereqs ## Runs tests for SD APP VM config
test-proxy: test-prereqs ## Runs tests for SD Proxy VM
pytest -v tests/test_proxy_vm.py

test-whonix: test-prereqs ## Runs tests for SD Whonix VM
pytest -v tests/test_sd_whonix.py

test-gpg: test-prereqs ## Runs tests for SD GPG functionality
pytest -v tests/test_gpg.py

Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ The current architecture replaces the *Journalist Workstation* and *Secure Viewi

Currently, the following VMs are provisioned:

- `sd-proxy` is where the SecureDrop proxy and the Tor gateway reside, which allows the non-networked `sd-app` vm to communicate with the *Journalist Interface* over Tor.
- `sd-proxy` is where the SecureDrop proxy resides, which allows the non-networked `sd-app` vm to communicate with the *Journalist Interface* over Tor. It's configured with the auth key for the hidden service.
- `sd-app` is a non-networked VM in which the *SecureDrop Client* runs used to store and explore submissions after they're unarchived and decrypted. Any files opened in this VM are opened in a disposable VM.
- `sd-gpg` is a Qubes split-gpg AppVM, used to hold submission decryption keys and do the actual submission crypto.
- `sd-viewer` is an AppVM used as the template for the disposable VMs used for processing and opening files.
Expand Down Expand Up @@ -92,11 +92,10 @@ This repo also contains the following developer-facing components:
SecureDrop Workstation has a companion repository, [SecureDrop Client](https://github.com/freedomofpress/securedrop-client/),
that contains component code for all of the packages we ship in individual VMs once they have been provisioned:
- The [SecureDrop Client](https://github.com/freedomofpress/securedrop-client/tree/main/client#readme) is installed in `sd-app` and will be used to access the SecureDrop server *Journalist Interface* via the SecureDrop proxy.
- The [SecureDrop Proxy](https://github.com/freedomofpress/securedrop-client/tree/main/proxy#readme) is installed in `sd-proxy` to communicate to the SecureDrop server *Journalist Interface* via `sd-whonix`.
- The [SecureDrop Proxy](https://github.com/freedomofpress/securedrop-client/tree/main/proxy#readme) is installed in `sd-proxy` to communicate to the SecureDrop server *Journalist Interface* via Tor.
- [SecureDrop Export](https://github.com/freedomofpress/securedrop-client/tree/main/export#readme) is installed in `sd-devices` and is used to manage printing and exporting files.
- The *SecureDrop Client* opens all submissions in the networkless, disposable `sd-viewer` VM
- A logging VM, `sd-log`, is provisioned to capture logs locally from various parts of the system
- A [Whonix](https://www.whonix.org/wiki/Homepage) VM, `sd-whonix`, is provisioned with instance-specific information required to access the authenticated onion service used by journalists.

### Additional Notes:

Expand Down
13 changes: 4 additions & 9 deletions files/sdw-admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

from qubesadmin import Qubes

from sdw_util import Util

# The max concurrency reduction (4->2) was required to avoid "did not return clean data"
# errors from qubesctl. It may be possible to raise this again.
MAX_CONCURRENCY = 2
Expand Down Expand Up @@ -111,12 +109,15 @@ def provision_and_configure():
provision("Provisioning base template", "securedrop_salt.sd-base-template")
configure("Configuring base template", ["sd-base-bookworm-template"])
provision_all()
configure("Enabling Whonix customizations", [f"whonix-gateway-{Util.get_whonix_version()}"])
configure(
"Configure all SecureDrop Workstation VMs with service-specific configs",
[q.name for q in Qubes().domains if "sd-workstation" in q.tags],
)

if "whonix-gateway-17" in Qubes().domains:
# Qubes installations without whonix
configure("Disabling Whonix customizations", ["whonix-gateway-17"])

sync_appmenus()

if "sd-fedora-42-dvm" in Qubes().domains:
Expand Down Expand Up @@ -213,14 +214,8 @@ def sync_appmenus():
run_cmd(["qvm-sync-appmenus", "sd-large-bookworm-template"])
run_cmd(["qvm-shutdown", "sd-large-bookworm-template"])

whonix_gateway = f"whonix-gateway-{Util.get_whonix_version()}"
run_cmd(["qvm-start", "--skip-if-running", whonix_gateway])
run_cmd(["qvm-sync-appmenus", whonix_gateway])
run_cmd(["qvm-shutdown", whonix_gateway])

# These are the ones we show in prod VMs, so sync explicitly
run_cmd(["qvm-sync-appmenus", "--regenerate-only", "sd-devices"])
run_cmd(["qvm-sync-appmenus", "--regenerate-only", "sd-whonix"])
run_cmd(["qvm-sync-appmenus", "--regenerate-only", "sd-log"])


Expand Down
14 changes: 5 additions & 9 deletions launcher/tests/test_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"sd-viewer",
"sd-gpg",
"sd-proxy",
"sd-whonix",
"sd-devices",
]

Expand Down Expand Up @@ -53,14 +52,12 @@
}


@mock.patch("sdw_util.Util.get_whonix_version", return_value=WHONIX_VERSION)
def test__get_current_vms(mocked_get_whonix_version):
assert len(Updater._get_current_vms()) == 8
def test__get_current_vms():
assert len(Updater._get_current_vms()) == 7


@mock.patch("sdw_util.Util.get_whonix_version", return_value=WHONIX_VERSION)
def test__get_current_templates(mocked_get_whonix_version):
assert len(Updater._get_current_templates()) == 4
def test__get_current_templates():
assert len(Updater._get_current_templates()) == 3


@mock.patch("sdw_updater.Updater._write_updates_status_flag_to_disk")
Expand Down Expand Up @@ -130,8 +127,7 @@ def test_apply_templates_success(
),
],
)
@mock.patch("sdw_util.Util.get_whonix_version", return_value=WHONIX_VERSION)
def test_apply_templates(whonix_ver_mock, templates, stderr, expected):
def test_apply_templates(templates, stderr, expected):
with (
mock.patch(
"sdw_updater.Updater._start_qubes_updater_proc",
Expand Down
11 changes: 0 additions & 11 deletions launcher/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,3 @@ def test_is_sdapp_halted_error(patched_subprocess, os_release_fixture, version_c
"""

assert not Util.is_sdapp_halted()


@mock.patch("subprocess.check_output", return_value=str(WHONIX_VERSION))
def test_get_whonix_version(patched_subprocess):
assert Util.get_whonix_version() == WHONIX_VERSION


@mock.patch("subprocess.check_output", side_effect=subprocess.CalledProcessError(1, "check_output"))
def test_get_whonix_version__on_error(patched_subprocess):
with pytest.raises(RuntimeError, match="Whonix version could not be obtained"):
Util.get_whonix_version()
2 changes: 0 additions & 2 deletions sdw_updater/Updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@

def _get_current_vms():
debian_version = "bookworm"
whonix_version = Util.get_whonix_version()

# The are the TemplateVMs that require full patch level at boot in order to start the client,
# as well as their associated TemplateVMs.
Expand All @@ -51,7 +50,6 @@ def _get_current_vms():
"sd-log": f"sd-small-{debian_version}-template",
"sd-devices": f"sd-large-{debian_version}-template",
"sd-proxy": f"sd-small-{debian_version}-template",
"sd-whonix": f"whonix-gateway-{whonix_version}",
"sd-gpg": f"sd-small-{debian_version}-template",
}

Expand Down
34 changes: 0 additions & 34 deletions sdw_util/Util.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,40 +148,6 @@ def get_qubes_version():
return version


def get_whonix_version():
"""
Obtain Whonix version from /srv/formulas/base/virtual-machine-formula/qvm/whonix.jinja

In '.sls' files the whonix version is obtained with

{% import "qvm/whonix.jinja" as whonix %}
{{ whonix.whonix_version }}

This function extracts this value so that it can be on this script.

NOTE: function takes a few seconds to run
"""

try:
output = subprocess.check_output(
[
"sudo",
"qubesctl",
"jinja.load_map",
"qvm/whonix.jinja",
"whonix_version",
"--out",
"newline_values_only",
], # avoid "local:" prefix
universal_newlines=True,
)
whonix_version = int(output.strip())
except (AttributeError, ValueError, subprocess.CalledProcessError):
raise RuntimeError("Whonix version could not be obtained")

return whonix_version


def get_logger(prefix=SD_LOGGER_PREFIX, module=None):
if module is None:
return logging.getLogger(prefix)
Expand Down
1 change: 0 additions & 1 deletion securedrop_salt/sd-base-template-packages.sls
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ install-qubes-vm-recommended:
sd-base-template-install-securedrop-packages:
pkg.installed:
- pkgs:
- securedrop-qubesdb-tools
- securedrop-workstation-config
- securedrop-workstation-grsec
- require:
Expand Down
7 changes: 0 additions & 7 deletions securedrop_salt/sd-clean-all.sls
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :

{% import_json "securedrop_salt/config.json" as d %}
{% import "qvm/whonix.jinja" as whonix %}

set-fedora-as-default-dispvm:
cmd.run:
Expand Down Expand Up @@ -75,12 +74,6 @@ sd-cleanup-sys-firewall:
- qvm-run sys-firewall 'sudo rm -f /etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation'
- qvm-run sys-firewall 'sudo rm -f /etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation-test'

sd-cleanup-whonix-gateway:
cmd.run:
- names:
- qvm-run whonix-gateway-{{ whonix.whonix_version }} 'sudo apt purge --yes securedrop-keyring securedrop-qubesdb-tools securedrop-whonix-config'
- qvm-run whonix-gateway-{{ whonix.whonix_version }} 'sudo rm -f /etc/apt/sources.list.d/apt-test_freedom_press.sources'

# Reset desktop icon size to its original value
dom0-reset-icon-size-xfce:
cmd.script:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@
# WARNING: only remove when complete reinstall is assumed (e.g. 1.0.0 release)
# This is because the workstation may have been offline for a while
# and skipped some salt updates.
{% for untagged_qube in ["sd-retain-logvm"] %}
{% for qube_name in ["sd-retain-logvm", "sd-whonix"] %}

poweroff-before-removal-{{ untagged_qube }}:
poweroff-before-removal-{{ qube_name }}:
qvm.shutdown:
- name: {{ untagged_qube }}
- name: {{ qube_name }}
- flags:
- force
- wait
- onlyif:
- qvm-check --quiet {{ untagged_qube }}
- qvm-check --quiet {{ qube_name }}
- order: last

remove-{{ untagged_qube }}:
remove-{{ qube_name }}:
qvm.absent:
- name: {{ untagged_qube }}
- name: {{ qube_name }}
- require:
- qvm: poweroff-before-removal-{{ untagged_qube }}
- qvm: poweroff-before-removal-{{ qube_name }}
- onlyif:
- qvm-check --quiet {{ untagged_qube }}
- qvm-check --quiet {{ qube_name }}
- order: last

{% endfor %}
18 changes: 18 additions & 0 deletions securedrop_salt/sd-remove-whonix-packages.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :

##
# Remove workstation components in whonix-gateway-17
#
# NOTE: this file should be safe to remove after a few releases. Even if some
# Workstations miss some updates (due to not being in use for a while), the
# mere presence of the repo/package, does not affect regular system behavior.
##

# NOTE: 'cmd.run' necessary since 'pkg.del_repo' or 'pkg.purge' fail due to:
# "The pkg module could not be loaded: unsupported OS family"
sd-cleanup-whonix-gateway:
cmd.run:
- names:
- "sudo apt-get purge --yes securedrop-keyring securedrop-qubesdb-tools securedrop-whonix-config ||:"
- "sudo rm -f /etc/apt/sources.list.d/apt_freedom_press.sources ||:"
18 changes: 18 additions & 0 deletions securedrop_salt/sd-reset-whonix-prefs.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :

# NOTE: this file may be removed after Qubes 4.2 is EOL (Whonix 17 assumed non-existent)

# Disable apparmor on workstation and gateway templates. Originally Whonix
# shipped without kernel parameters. This reverts a previous workstation change
# that added AppArmor

{% for (vm, component) in [('sys-whonix', 'gateway'), ('anon-whonix', 'workstation')] %}
whonix-{{ component }}-17-remove-apparmor:
qvm.vm:
- name: whonix-{{ component }}-17
- prefs:
- kernelopts: "*default*"
- onlyif:
- qvm-check --quiet {{ vm }}
{% endfor %}
66 changes: 0 additions & 66 deletions securedrop_salt/sd-sys-whonix-vms.sls

This file was deleted.

9 changes: 0 additions & 9 deletions securedrop_salt/sd-whonix-config.sls

This file was deleted.

Loading