Qt-based client for working with SecureDrop submissions on the SecureDrop Qubes Workstation. In Qubes, this application runs within a VM that has no direct network access, and files open in individual, non-networked, disposable VMs. API requests and responses to and from the SecureDrop application server are sent through an intermediate VM using the Qubes SecureDrop proxy. For additional background, see the main SecureDrop Workstation repository, and read about the user research and design work that informs this work.
IMPORTANT: This project is in alpha and should not be used in production environments. There are known bugs which can be found in this projectโs issue tracker.
This client is under active development and currently supports a minimal feature set. Major supported features include:
- the download and decryption of files, messages, and replies (using Qubes split-gpg)
- the display of decrypted messages and replies in a new conversation view
- the opening of all files in individual, non-networked, Qubes disposable VMs
- replying to sources
- deleting sources
- exporting files to LUKS-encrypted USB drives
- printing to supported printers
Set up a Python 3 virtual environment and set up dependencies:
virtualenv --python=python3.7 .venv
source .venv/bin/activate
pip install --require-hashes -r dev-requirements.txt
Please install system libraries for PyQt rather than using PyPI-managed libraries- this makes packaging possible later. On Debian, apt install python3-pyqt5 python3-pyqt5.qtsvg will install what you need.
In order to run the test suite you should also install the xvfb package (to
make the xvfb-run command available): apt install xvfb. You may also need
to install the sqlite3 command: apt install sqlite3.
# install Homebrew https://brew.sh/
brew install pyenv
# follow step 3 onwards of https://github.com/pyenv/pyenv#basic-github-checkout
# install and select the latest version of python 3.7.x
pyenv install 3.7
pyenv local 3.7.x
brew install pip
pip install virtualenv
virtualenv --python=python3.7 .venv
source .venv/bin/activate
pip install --require-hashes -r dev-requirements.txt
We have several dependency files: dev-requirements.txt and requirements.txt point to python software foundation hashes, and build-requirements.txt points to our builds of the wheels from our own pip mirror. Whenever a dependency in build-requirements.txt changes, our team needs to manually review the code in the dependency diff with a focus on spotting vulnerabilities.
If you're adding or updating a dependency, you need to:
-
Modify either
requirements.inordev-requirements.in(depending on whether it is prod or dev only) and then runmake update-pip-requirements. This will generatedev-requirements.txtandrequirements.txt. -
For building a debian package from this project, we use the requirements in
build-requirements.txtwhich uses our pip mirror, i.e. the hashes in that file point to wheels on our pip mirror. A maintainer will need to add the updated dependency to our pip mirror (you can request this in the PR). -
Once the pip mirror is updated, you should checkout the securedrop-debian-packaging repo and run
make requirements. Commit thebuild-requirements.txtthat results and add it to your PR.
You can then run the client with an ephemeral data directory:
./run.sh
If you want to persist data across restarts, you will need to run the client with:
./run.sh --sdc-home /path/to/my/dir/
An AppArmor profile is available for mandatory access control. When installing securedrop-client from a .deb package, the AppArmor profile will automatically be copied and enforced. Below are instructions to use the profile in non-production scenarios.
-
The entrypoint for the application must be through
/usr/bin/securedrop-clientwith application code in/opt/venvs/securedrop-client. -
The kernel must support AppArmor (running
sudo aa-statuswill return zero if AppArmor is supported). -
The
apparmor-utilspackage is installed (sudo apt install apparmor-utilsin Debian).
-
Copy
files/usr.bin.securedrop-clientto/etc/apparmor.d/. -
sudo aa-enforce /etc/apparmor.d/usr.bin.securedrop-client/. -
sudo aa-statusand observe securedrop-client profile is being enforced.
-
Update the profile in
/etc/apparmor.d/usr.bin.securedrop-client. -
sudo aa-teardown. -
sudo service apparmor restart. -
Once you've made all the changes necessary (e.g.: no apparmor errors in
/var/log/syslog) you can copy/etc/apparmor.d/usr.bin.securedrop-clientintofiles/usr.bin.securedrop-clientin this repository and commit the changes.
To use pdb, add these lines:
from PyQt5.QtCore import pyqtRemoveInputHook; pyqtRemoveInputHook()
import pdb; pdb.set_trace()
Then you can use pdb commands as normal.
Logs can be found in the {sdc-home}/logs. If you are debugging a version of this application installed from a deb package in Qubes, you can debug issues by looking at the log file in ~/.securedrop_client/logs/client.log. You can also add additional log lines in the running code in
/opt/venvs/securedrop-client/lib/python3.7/site-packages/securedrop_client/.
In order to login, or take other actions involving network access, you will need to use the SecureDrop server dev container.
Follow the instructions in the SecureDrop documentation to set that up.
The client uses the SecureDrop SDK to interact with the SecureDrop Journalist API.
After you run the server container, the journalist interface API will be running on 127.0.0.1:8081 with a test journalist, admin, and test sources and replies.
To ensure that file decryption works, please import this test private key into your GnuPG keyring. Submissions in the SecureDrop server dev environment can be decrypted with this test key.
To run everything, run:
make checkTo individually run the unit tests, run make test to run the suite in parallel (fast), or run make test-random to run the tests in random order (slower, but this is what make check runs and what runs in CI).
The quickest way to get started with running the client is to use the developer environment that runs against a test server running in a local docker container. This differs from a staging or production environment where the client receives and sends requests over Tor. Things are a lot snappier in the developer environment and can sometimes lead to a much different user experience, which is why it is important to do end-to-end testing in Qubes using the staging environment, especially if you are modifying code paths involving how we handle server requests and responses.
For reproducing production bugs or running demos, we recommend using the Production Environment that will allow you to test a nightly build of the client.
We support running the developer environment on a non-Qubes OS for developer convenience. If this is your preferred environment, keep in mind that you, or a PR reviewer, will need to run tests in Qubes if you modify code paths involving any of the following:
- cryptography
- opening of files in VMs
- network (via the RPC service) traffic
- fine tuning of the graphical user interface
- Run by
run.shinside a virtual env in thesd-devAppVM - Requires
qvm-tags sd-dev add sd-clientto be run indom0(substitute your dev VM forsd-dev) - Works with SecureDrop running in a local docker container, see SecureDrop docs for setup instructions, including post-installation steps for allowing docker to be run as a non-root user, which is a requirement on Qubes
- Uses a temporary directory as its configuration directory, instead of
~/.securedrop_client - Uses a development gpg private key inside a gpg keychain stored in the temporary configuration directory
- Submissions will be opened in DispVMs
- Tor is not used
- Run by
run.shinside a virtual env on a non-Qubes OS - Works with SecureDrop running in a local docker container, see SecureDrop docs for setup instructions
- Uses a temporary directory as its configuration directory, instead of
~/.securedrop_client - Uses a development gpg private key inside a gpg keychain stored in the temporary configuration directory
- Does not support opening submissions
- Tor is not used
- Run by directly invoking the client
python -m securedrop_clienton thesd-appAppVM - Requires that
make allin thesecuredrop-workstationrepository has completed successfully - Requires that the installed client (e.g., nightly build) has been run at least once, or that the database has been manually initialized
- Uses
~/.securedrop_clientas its configuration directory - Uses the gpg key in the
sd-gpgAppVM configured duringmake all - Tor is used: Requests/responses proxied via the
securedrop-proxyRPC service - For convienient access to network in order to clone the repository and push branches, you'll need to add a NetVM (
sys-firewall)
- Run by executing
securedrop-clientin thesd-appAppVM (see workstation documentation here) - Requires that
make allin thesecuredrop-workstationrepository has completed successfully - Uses
~/.securedrop_clientas its configuration directory - Uses the gpg key in the
sd-gpgAppVM configured duringmake all - Tor is used: Requests/responses proxied via the
securedrop-proxyRPC service
rm -f svs.sqlite
sqlite3 svs.sqlite .databases > /dev/null
alembic upgrade head
alembic revision --autogenerate -m "describe your revision here"This project aims to have at most one migration per release. There may be cases where this is not feasible, but developers should merge their migration into the latest migration that has been generated since the last release. The above mentioned autogenerate command will not do this for you.
- Update versions:
./update_version.sh $new_version_numberand add a new entry in the changelog. - Commit the changes with commit message
securedrop-client $new_version_numberand make a PR. - You should confirm via a manual debian package build and manual testing in Qubes that there are no regressions (this is limited pre-release QA).
- Once your PR is approved, you can add a tag:
git tag -a $new_version_number. - Perform the release signing ceremony on the tag. Push the tag.
- The signer should create the source tarball via
python3 setup.py sdist. - Add a detached signature (with the release key) for the source tarball.
- Submit the source tarball and signature via PR into this repository along with the debian changelog addition. This tarball and changelog will be used by the package builder.