From ce75b934a41898b718d3a5cf61e26c7cfce447d3 Mon Sep 17 00:00:00 2001 From: deeplow Date: Wed, 11 Sep 2024 14:01:55 +0100 Subject: [PATCH] Add SecureDrop installation test --- README | 6 +- lib/installedtest.pm | 7 +- main.pm | 22 ++++++ tests/securedrop/install_pre_reboot.pm | 59 ++++++++++++++++ tests/securedrop/install_reboot_and_update.pm | 70 +++++++++++++++++++ tests/securedrop/upload_packages.pm | 59 ++++++++++++++++ tests/whonix_firstrun.pm | 16 ++++- 7 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 tests/securedrop/install_pre_reboot.pm create mode 100644 tests/securedrop/install_reboot_and_update.pm create mode 100644 tests/securedrop/upload_packages.pm diff --git a/README b/README index ab269ed6..25377c58 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -OpenQA Tests for Qubes OS +OpenQA Tests for Qubes OS To install, clone this repo to /var/lib/openqa/tests/qubesos @@ -67,3 +67,7 @@ Variables used in tests: - `INSTALL_OEM` - do fully automated OEM installation - `INSTALL_OEM_STARTUP` - start OEM installation, but still expect interactive prompts during installation - `HID` - for generalhw tests, tell it whether `USB` hid is used (default) or `PS2` one; in the latter case, sys-usb is not supposed to have input-proxy allowed by default + +SecureDrop variables used in tests: + - `SECUREDROP_INSTALL` - when set to `1`, SecureDrop Workstation is installed + - `SECUREDROP_TEST` - when set with a value, SecureDrop tests are run on top of an existing installation diff --git a/lib/installedtest.pm b/lib/installedtest.pm index b5df8d1a..2715777b 100644 --- a/lib/installedtest.pm +++ b/lib/installedtest.pm @@ -288,7 +288,12 @@ sub maybe_unlock_screen { sub save_and_upload_log { my ($self, $cmd, $file, $args) = @_; script_run("$cmd > $file", $args->{timeout}); - my $ret = upload_logs($file) unless $args->{noupload}; + assert_script_run("echo DEBUG: timeout (" . $args->{timeout} . ") failok (" . $args->{failok} . ")"); + my $ret = upload_logs( + $file, + timeout => $args->{timeout}, + failok => $args->{failok} + ) unless $args->{noupload}; save_screenshot if $args->{screenshot}; return $ret; } diff --git a/main.pm b/main.pm index 0790fc98..acb39f6b 100644 --- a/main.pm +++ b/main.pm @@ -18,6 +18,7 @@ use strict; use testapi; use autotest; +use OpenQA::Test::RunArgs; require 'qubesdistribution.pm'; testapi::set_distribution(qubesdistribution->new()); @@ -164,6 +165,26 @@ if (get_var('SYSTEM_TESTS')) { autotest::loadtest "tests/system_tests.pm"; } +if (check_var('SECUREDROP_INSTALL', '1')) { + # WIP: testing + autotest::loadtest("tests/securedrop/upload_packages.pm"); + + # Setup sys-whonix connection so it does not interfere later + autotest::loadtest("tests/whonix_firstrun.pm", name => "Setup_sys-whonix"); + + autotest::loadtest("tests/securedrop/install_pre_reboot.pm", name => "installing_SecureDrop"); + + # Setup sd-whonix connection + my $args = OpenQA::Test::RunArgs->new(); + $args->{whonix_gw_override} = 'sd-whonix'; + autotest::loadtest("tests/whonix_firstrun.pm", name =>"Setup_sd-whonix", run_args => $args); + + autotest::loadtest("tests/securedrop/install_reboot_and_update.pm", name => "reboot_and_finish_install"); + +} elsif (check_var('SECUREDROP_TEST', "basic_functionality")) { + autotest::loadtest("tests/securedrop/basic_functionality.pm"); +} + if (get_var('TEST_GUI_INTERACTIVE')) { autotest::loadtest "tests/simple_gui_apps.pm"; autotest::loadtest "tests/clipboard_and_web.pm"; @@ -211,6 +232,7 @@ if (get_var("STORE_HDD_1") || get_var("PUBLISH_HDD_1")) { autotest::loadtest "tests/shutdown.pm"; } + 1; # vim: set sw=4 et: diff --git a/tests/securedrop/install_pre_reboot.pm b/tests/securedrop/install_pre_reboot.pm new file mode 100644 index 00000000..c8527b17 --- /dev/null +++ b/tests/securedrop/install_pre_reboot.pm @@ -0,0 +1,59 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +use base "installedtest"; +use strict; +use testapi; +use networking; + +sub run { + my ($self) = @_; + + $self->select_gui_console; + assert_screen "desktop"; + + # Enable "presentation mode" to prevent the screen from going dark + assert_and_click('disable-screen-blanking-click-power-tray-icon'); + assert_and_click('disable-screen-blanking-click-presentation-mode'); + send_key('esc'); + + x11_start_program('xterm'); + send_key('alt-f10'); # maximize xterm to ease troubleshooting + + curl_via_netvm; + + assert_script_run('set -o pipefail'); # Ensure pipes fail + + # NOTE: These are done via qvm-run instead of gnome-terminal so that we + # can know in case they failed. + assert_script_run('qvm-run -p work -- gpg --keyserver hkps://keys.openpgp.org --recv-key "2359 E653 8C06 13E6 5295 5E6C 188E DD3B 7B22 E6A3"'); + assert_script_run('qvm-run -p work -- "gpg --armor --export 2359E6538C0613E652955E6C188EDD3B7B22E6A3 > securedrop-release-key.pub"'); + assert_script_run('qvm-run -p work -- sudo rpmkeys --import securedrop-release-key.pub'); + assert_script_run('qvm-run -p work -- "echo -e \"[sd]\nenabled=1\nbaseurl=https://yum-qa.securedrop.org/workstation/dom0/f37\nname=boostrap\" | sudo tee /etc/yum.repos.d/securedrop-temp.repo"'); + assert_script_run('qvm-run -p work -- dnf download -y securedrop-workstation-dom0-config'); + assert_script_run('qvm-run -p work -- "rpm -Kv securedrop-workstation-dom0-config-*.rpm"'); # TODO confirm output is correct + assert_script_run('qvm-run -p work -- "cat /home/user/securedrop-workstation-dom0-config-*.rpm" > securedrop-workstation.rpm'); + assert_script_run('sudo dnf -y install securedrop-workstation.rpm'); + assert_script_run('echo {\"submission_key_fpr\": \"65A1B5FF195B56353CC63DFFCC40EF1228271441\", \"hidserv\": {\"hostname\": \"bnbo6ryxq24fz27chs5fidscyqhw2hlyweelg4nmvq76tpxvofpyn4qd.onion\", \"key\": \"FDF476DUDSB5M27BIGEVIFCFGHQJ46XS3STAP7VG6Z2OWXLHWZPA\"}, \"environment\": \"prod\", \"vmsizes\": {\"sd_app\": 10, \"sd_log\": 5}} | sudo tee /usr/share/securedrop-workstation-dom0-config/config.json'); + assert_script_run('curl https://raw.githubusercontent.com/freedomofpress/securedrop/d91dc67/securedrop/tests/files/test_journalist_key.sec.no_passphrase | sudo tee /usr/share/securedrop-workstation-dom0-config/sd-journalist.sec'); + assert_script_run('sdw-admin --validate'); + + assert_script_run('env xset -dpms; env xset s off', valid => 0, timeout => 10); # disable screen blanking during long command + assert_script_run('sdw-admin --apply | tee /tmp/sdw-admin-apply.log', timeout => 2400); # long timeout due to slow virt. + upload_logs('/tmp/sdw-admin-apply.log'); + send_key('alt-f4'); # close terminal +} + +1; + +# vim: set sw=4 et: diff --git a/tests/securedrop/install_reboot_and_update.pm b/tests/securedrop/install_reboot_and_update.pm new file mode 100644 index 00000000..72a9e4c3 --- /dev/null +++ b/tests/securedrop/install_reboot_and_update.pm @@ -0,0 +1,70 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +use base "installedtest"; +use strict; +use testapi; +use networking; + +sub run { + my ($self) = @_; + $self->select_gui_console; + + x11_start_program('xterm'); + send_key('alt-f10'); # maximize xterm to ease troubleshooting + + # Reboot system + script_run('sudo reboot', timeout => 0); + $self->handle_system_startup; + + # HACK Whonix systemcheck still shows up for sys-whonix + # due to unnapplied updates + if (check_screen('whonix-systemcheck-derived-repo', timeout => 300)) { + assert_and_click('whonix-systemcheck-derived-repo-accept'); + } + + # Go through launcher + assert_and_click("securedrop-launcher"); + assert_screen("securedrop-launcher-updates-in-progress", timeout => 10); + assert_screen("securedrop-launcher-updates-complete", timeout => 1200); + if (check_screen("securedrop-launcher-updates-complete-reboot")) { + assert_and_click("securedrop-launcher-updates-complete-reboot"); + $self->handle_system_startup; + assert_and_click("securedrop-launch-from-desktop-icon", dclick => 1); + } else { + assert_and_click("securedrop-launcher-updates-complete-continue"); + } + if (check_screen('securedrop-client-login-screen', 5)) { + send_key('alt-f4'); # exit SecureDrop client + } + +} + +sub post_fail_hook { + my $self = shift; + + $self->SUPER::post_fail_hook(); + upload_logs('/home/user/.securedrop_updater/logs/updater.log', failok => 1); + upload_logs('/home/user/.securedrop_updater/logs/updater-detail.log', failok => 1); + + # WIP troubleshooting + upload_logs('/var/log/xen/console/guest-sd-base-bookworm-template.log', failok => 1); + upload_logs('/var/log/xen/console/guest-sd-small-bookworm-template.log', failok => 1); + upload_logs('/var/log/xen/console/guest-sd-large-bookworm-template.log', failok => 1); + + upload_logs('/tmp/sdw-admin-apply.log', failok => 1); +}; + +1; + +# vim: set sw=4 et: diff --git a/tests/securedrop/upload_packages.pm b/tests/securedrop/upload_packages.pm new file mode 100644 index 00000000..fceb5585 --- /dev/null +++ b/tests/securedrop/upload_packages.pm @@ -0,0 +1,59 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +use base "installedtest"; +use strict; +use testapi; +use networking; +use Mojo::File qw(path); + +sub upload_package_lists { + # Upload inventory of package versions (useful for troubleshooting bad versions) + # Borrowed from https://github.com/QubesOS/openqa-tests-qubesos/blob/7242736/tests/update2.pm#L121-L138 + + my ($self) = @_; + + x11_start_program('xterm'); + send_key('alt-f10'); # maximize xterm to ease troubleshooting + + curl_via_netvm; + + my $fname = $self->save_and_upload_log('rpm -qa', 'dom0-packages.txt'); + my $packages = path('ulogs', $fname)->slurp; + $packages = join("\n", sort split(/\n/, $packages)); + my $all_packages = "Dom0:\n" . $packages; + my $templates = script_output('qvm-ls --raw-data --fields name,klass'); + foreach (sort split /\n/, $templates) { + next unless /Template/; + s/\|.*//; + $fname = $self->save_and_upload_log("qvm-run --no-gui -ap $_ 'rpm -qa; dpkg -l; pacman -Q; true'", + "template-$_-packages.txt", {timeout => 90, failok => 1}); + $packages = path('ulogs', $fname)->slurp; + $packages = join("\n", sort split(/\n/, $packages)); + $all_packages .= "\n" . $_ . ":\n" . $packages; + #assert_script_run("qvm-run --service -p $_ qubes.PostInstall", timeout => 90); + script_output("qvm-features $_", timeout => 90); + assert_script_run("qvm-shutdown --wait $_", timeout => 90); + } + path("sut_packages.txt")->spew($all_packages); +} + + +sub run { + my ($self) = @_; + $self->upload_package_lists; +} + +1; + +# vim: set sw=4 et: diff --git a/tests/whonix_firstrun.pm b/tests/whonix_firstrun.pm index e44c283a..dc02dd7e 100644 --- a/tests/whonix_firstrun.pm +++ b/tests/whonix_firstrun.pm @@ -18,15 +18,25 @@ use base "installedtest"; use strict; use testapi; +use OpenQA::Test::RunArgs; sub run { - my ($self) = @_; + my ($self, $args) = @_; + + my $whonix_gateway = "sys-whonix"; + if (exists $args->{whonix_gw_override}) { + $whonix_gateway = $args->{whonix_gw_override}; + } else { + } $self->select_gui_console; - x11_start_program('qvm-start sys-whonix', valid => 0); + + my $start_whonix_gw_cmd = sprintf "qvm-start %s", $whonix_gateway; + x11_start_program($start_whonix_gw_cmd, valid => 0); if (!check_screen(['whonix-connected', 'whonix-firstrun'], 120)) { # no firstrun wizard? maybe already accepted - verify it - x11_start_program('qvm-run sys-whonix \'whonixcheck --gui\'', valid => 0); + my $run_whonixcheck_cmd = sprintf "qvm-run %s 'whonixcheck --gui'", $whonix_gateway; + x11_start_program($run_whonixcheck_cmd, valid => 0); assert_screen('whonix-connected', timeout => 60); }