From 0b83c58e4f76cf5bd349cfc78ca7d09d12bee82c Mon Sep 17 00:00:00 2001 From: Rowen S Date: Wed, 15 Jan 2025 15:38:07 -0500 Subject: [PATCH 1/5] Update README to include release/update instructions --- README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eee51c0..1dd3c66 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,26 @@ # SecureDrop Worskatation Keyring (RPM) -This package contains the SecureDrop Release Public Key and a yum .repo file that points to the SecureDrop Workstation production repo. -It will be used for ease of bootstrapping SecureDrop Workstation on QubesOS. +This package contains the SecureDrop Release Public Key and a yum .repo file that points +to the SecureDrop Workstation production repo. It will be used for ease of bootstrapping +SecureDrop Workstation on QubesOS. **At the moment this repo is experimental and should not be part of a production SDW installation.** ## SecureDrop Release Key -See https://media.securedrop.org/media/documents/securedrop-release-key-2021-2.asc for verification. +See https://media.securedrop.org/media/documents/securedrop-release-key-2021-2.asc +for verification. + +## Package updates +Any updates to the SecureDrop Release Signing Key will require an updated version of +this package to be released. Submit a PR to this repository that contains the updated +SecureDrop Release Public Key and updates the rpm key ID, which will change any time the +key or its subkeys are changed. (The rpm key ID is ``gpg-pubkey-xxxxxxxx-yyyyyyyy``, used +in the ``.spec`` file and in ``tests``, and the new rpm key ID can be found by importing +the updated pubkey into rpmdb and querying for it via +``rpm -qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' | grep 'SecureDrop Release Signing Key'``). + +Then follow [the RPM release documentation](https://developers.securedrop.org/en/latest/workstation_release_management.html#release-an-rpm-package) to release an updated keyring +package. + +Refer to the internal SecureDrop developer documentation for information on release key +update procedures. From a92caec02acd02507287827352afc8dc2b8751d3 Mon Sep 17 00:00:00 2001 From: Rowen S Date: Wed, 15 Jan 2025 15:37:37 -0500 Subject: [PATCH 2/5] Add smoketest that ensures package is installed, keyring and repo files are present, and key is imported into rpmdb --- tests/test_keyring.py | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/test_keyring.py diff --git a/tests/test_keyring.py b/tests/test_keyring.py new file mode 100644 index 0000000..18856af --- /dev/null +++ b/tests/test_keyring.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +import subprocess +from pathlib import Path + +# +# Basic acceptance testing for keyring package (Fedora-based) +# + +# Update this pubkey ID if the key or its subkeys are updated; see README +GPG_PUBKEY_ID = "gpg-pubkey-7b22e6a3-609966ad" +RPM_QUERY_PACKAGE = ["rpm", "-q"] +RPM_GPG_QUERY_SD_RELEASE_KEY = ["rpm", "-q", GPG_PUBKEY_ID] +REPOFILE_PATH = "/etc/yum.repos.d/securedrop-workstation-dom0.repo" +KEYFILE_PATH = "/etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation" + +def is_fedora(): + with open("/etc/os-release") as f: + for line in f: + if line.startswith("NAME"): + return "Fedora" in line.split("=")[-1] + return False + +def is_package_installed(package_name: str): + query = RPM_QUERY_PACKAGE + [package_name] + + # raise if package is not installed + subprocess.check_call(args=query, stdout=subprocess.DEVNULL) + +def is_repo_file_installed(): + repofile = Path(REPOFILE_PATH) + return repofile.exists() + +def is_key_in_etc_pki(): + keyfile = Path(KEYFILE_PATH) + return keyfile.exists() + +def is_key_in_rpmdb(): + subprocess.check_call(RPM_GPG_QUERY_SD_RELEASE_KEY, + stdout=subprocess.DEVNULL) + +if __name__ == "__main__": + assert is_fedora() + assert is_package_installed("systemd") + assert is_package_installed("securedrop-workstation-keyring") + assert is_repo_file_installed() + assert is_key_in_etc_pki() + assert is_key_in_rpmdb() From a424e343e84f5708b72ed0da249269d8c42f2cfb Mon Sep 17 00:00:00 2001 From: Rowen S Date: Thu, 16 Jan 2025 17:15:43 -0500 Subject: [PATCH 3/5] Add smoketest make target. Support containerized smoketest. Option to specify rpm if prebuilt. --- Makefile | 7 ++++++- scripts/smoketest.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100755 scripts/smoketest.sh diff --git a/Makefile b/Makefile index eb12d57..dc2506c 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ build-deps: ## Install package dependencies to build RPMs test-deps: build-deps ## Install package dependencies for running tests dnf install -y \ python3-pip rpmlint which libfaketime ShellCheck \ - hostname + hostname systemd dnf --setopt=install_weak_deps=False -y install reprotest .PHONY: lint @@ -41,6 +41,11 @@ rpmlint: ## Runs rpmlint on the spec file shellcheck: ## Runs shellcheck on all shell scripts ./scripts/shellcheck.sh +.PHONY: smoketest +smoketest: ## Run smoketest (builds rpm if none provided) + # Run against a prebuilt rpm via `make smoketest RPM=path-to-rpm` + $(CONTAINER) ./scripts/smoketest.sh $(RPM) + # Explanation of the below shell command should it ever break. # 1. Set the field separator to ": ##" to parse lines for make targets. # 2. Check for second field matching, skip otherwise. diff --git a/scripts/smoketest.sh b/scripts/smoketest.sh new file mode 100755 index 0000000..42d9ae4 --- /dev/null +++ b/scripts/smoketest.sh @@ -0,0 +1,28 @@ +#!/usr/bin/bash +set -e +set -u +set -o pipefail + +# If no rpm supplied as commandline arg, build one +if [[ "$#" -eq 0 ]]; then + echo "No RPM supplied for smoketest, building..." + source "$(dirname "$0")/build-rpm.sh" + # Choose the fc37.noarch rpm + RPM=$(find rpm-build/ -type f -iname "${PROJECT}-$(cat "${TOPLEVEL}/VERSION")*fc37.noarch.rpm") +elif [[ "$#" -eq 1 ]]; then + RPM="${1}" + source "$(dirname "$0")/common.sh" +else + echo "Usage: smoketest.sh [path-to-rpm]" + exit 1 +fi + +echo "Installing RPM..." +sudo dnf install -y "${RPM}" + +echo "RPM installed. (Wait 60 seconds to begin smoketest)..." +# rpmdb isn't modified right away +sleep 60 + +echo "Begin smoketest..." +python3 "${TOPLEVEL}/tests/test_keyring.py" && echo "Test complete" || echo "Test failed" From 3ea544847c356d6f3d2f607ec5c6c9c070b919bd Mon Sep 17 00:00:00 2001 From: Rowen S Date: Thu, 16 Jan 2025 17:15:55 -0500 Subject: [PATCH 4/5] Add smoketest run to github actions. --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ scripts/smoketest.sh | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 496a4f6..3667093 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,3 +40,31 @@ jobs: run: | make test-deps make reprotest + - uses: actions/upload-artifact@v4 + id: upload + with: + name: rpm-build + path: rpm-build/RPMS/noarch/*.rpm + if-no-files-found: error + test-rpm: + runs-on: ubuntu-latest + container: + image: registry.fedoraproject.org/fedora:37 + needs: build-rpm + steps: + - run: dnf install -y git make + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Install dependencies + run: | + git config --global --add safe.directory '*' + make test-deps + - uses: actions/download-artifact@v4 + with: + name: rpm-build + path: rpm-build/RPMS/noarch/ + pattern: "*.rpm" + - name: Install RPM and run smoketest + run: | + make smoketest RPM=rpm-build/RPMS/noarch/*fc37.noarch.rpm diff --git a/scripts/smoketest.sh b/scripts/smoketest.sh index 42d9ae4..4eca893 100755 --- a/scripts/smoketest.sh +++ b/scripts/smoketest.sh @@ -25,4 +25,4 @@ echo "RPM installed. (Wait 60 seconds to begin smoketest)..." sleep 60 echo "Begin smoketest..." -python3 "${TOPLEVEL}/tests/test_keyring.py" && echo "Test complete" || echo "Test failed" +python3 "${TOPLEVEL}/tests/test_keyring.py" \ No newline at end of file From a89bd5b106ce45c8f2c31c05605e55a96d081138 Mon Sep 17 00:00:00 2001 From: Rowen S Date: Mon, 20 Jan 2025 10:29:16 -0500 Subject: [PATCH 5/5] Skip tests on CI requiring systemd. --- tests/test_keyring.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_keyring.py b/tests/test_keyring.py index 18856af..7784059 100644 --- a/tests/test_keyring.py +++ b/tests/test_keyring.py @@ -40,8 +40,12 @@ def is_key_in_rpmdb(): if __name__ == "__main__": assert is_fedora() - assert is_package_installed("systemd") assert is_package_installed("securedrop-workstation-keyring") assert is_repo_file_installed() assert is_key_in_etc_pki() - assert is_key_in_rpmdb() + + # TODO: CI does not have systemd installed and booted with PID 1, + # so skip the test that checks that the key was imported to rpmdb + # using systemd-run + if is_package_installed("systemd"): + assert is_key_in_rpmdb()