From 79bc08947b74bb1543e14b1687b866ae0e3ae2d2 Mon Sep 17 00:00:00 2001 From: John Hensley Date: Tue, 5 Mar 2019 15:38:35 -0500 Subject: [PATCH 1/3] Try harder to attach to an existing tmux session If in the course of an ssh/tmux session the tmux package is upgraded and the ssh connection broken, the next ssh attempt will encounter an error because of the tmux protocol version mismatch. The old tmux can be used to reattach by searching for the tmux process under /proc and using its reference to the old tmux executable. This change attempts to do that automatically if a first "tmux attach" attempt fails, but we can see that a previous session still exists. --- .../securedrop_application_server.yml | 2 +- .../group_vars/securedrop_monitor_server.yml | 2 +- .../common/files/bashrc_securedrop_additions | 9 -------- .../roles/common/tasks/create_users.yml | 11 --------- .../securedrop-config/DEBIAN/control | 2 +- .../etc/profile.d/securedrop_additions.sh | 17 ++++++++++++++ .../staging/common/test_user_config.py | 23 +++++++++++-------- 7 files changed, 34 insertions(+), 32 deletions(-) delete mode 100644 install_files/ansible-base/roles/common/files/bashrc_securedrop_additions create mode 100644 install_files/securedrop-config/etc/profile.d/securedrop_additions.sh diff --git a/install_files/ansible-base/group_vars/securedrop_application_server.yml b/install_files/ansible-base/group_vars/securedrop_application_server.yml index 761a2c2fe4..5cc4a0f1f6 100644 --- a/install_files/ansible-base/group_vars/securedrop_application_server.yml +++ b/install_files/ansible-base/group_vars/securedrop_application_server.yml @@ -7,7 +7,7 @@ ip_info: ### Used by the install_local_deb_pkgs role ### local_deb_packages: - "securedrop-keyring-0.1.2+{{ securedrop_app_code_version }}-amd64.deb" - - "securedrop-config-0.1.2+{{ securedrop_app_code_version }}-amd64.deb" + - "securedrop-config-0.1.3+{{ securedrop_app_code_version }}-amd64.deb" - "securedrop-ossec-agent-3.0.0+{{ securedrop_app_code_version }}-amd64.deb" - "{{ securedrop_app_code_deb }}.deb" - "ossec-agent-3.0.0-amd64.deb" diff --git a/install_files/ansible-base/group_vars/securedrop_monitor_server.yml b/install_files/ansible-base/group_vars/securedrop_monitor_server.yml index 921c639b45..45db3040cb 100644 --- a/install_files/ansible-base/group_vars/securedrop_monitor_server.yml +++ b/install_files/ansible-base/group_vars/securedrop_monitor_server.yml @@ -7,7 +7,7 @@ ip_info: ### Used by the install_local_deb_pkgs role ### local_deb_packages: - "securedrop-keyring-0.1.2+{{ securedrop_app_code_version }}-amd64.deb" - - "securedrop-config-0.1.2+{{ securedrop_app_code_version }}-amd64.deb" + - "securedrop-config-0.1.3+{{ securedrop_app_code_version }}-amd64.deb" - "securedrop-ossec-server-3.0.0+{{ securedrop_app_code_version }}-amd64.deb" - ossec-server-3.0.0-amd64.deb diff --git a/install_files/ansible-base/roles/common/files/bashrc_securedrop_additions b/install_files/ansible-base/roles/common/files/bashrc_securedrop_additions deleted file mode 100644 index a0797bb764..0000000000 --- a/install_files/ansible-base/roles/common/files/bashrc_securedrop_additions +++ /dev/null @@ -1,9 +0,0 @@ -# If not running interactively, do not do anything -[[ $- != *i* ]] && return - -# Auto-launch tmux on login -# https://wiki.archlinux.org/index.php/Tmux#Start_tmux_on_every_shell_login -if which tmux >/dev/null 2>&1; then - #if not inside a tmux session, and if no session is started, start a new session - test -z "$TMUX" && (tmux attach || tmux new-session) -fi \ No newline at end of file diff --git a/install_files/ansible-base/roles/common/tasks/create_users.yml b/install_files/ansible-base/roles/common/tasks/create_users.yml index f3382c7b25..56b5bd414f 100644 --- a/install_files/ansible-base/roles/common/tasks/create_users.yml +++ b/install_files/ansible-base/roles/common/tasks/create_users.yml @@ -23,17 +23,6 @@ - users - sudoers -- name: Set SecureDrop bash profile additions. - copy: - src: bashrc_securedrop_additions - dest: /etc/profile.d/securedrop_additions.sh - owner: root - group: root - mode: "0644" - tags: - - users - - environment - # Backwards-compatibility. Previously, the SecureDrop bashrc additions # for forcing a terminal multiplexer during interactive login sessions were # added to ~/.bashrc for each admin user account. It's cleaner to add the diff --git a/install_files/securedrop-config/DEBIAN/control b/install_files/securedrop-config/DEBIAN/control index abee3880f1..a46e87002c 100644 --- a/install_files/securedrop-config/DEBIAN/control +++ b/install_files/securedrop-config/DEBIAN/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: SecureDrop Team Homepage: https://securedrop.org Package: securedrop-config -Version: 0.1.2+0.13.0~rc1 +Version: 0.1.3+0.13.0~rc1 Architecture: all Description: Establishes baseline system state for running SecureDrop. Configures apt repositories. diff --git a/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh b/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh new file mode 100644 index 0000000000..e6358c03fd --- /dev/null +++ b/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh @@ -0,0 +1,17 @@ +[[ $- != *i* ]] && return + +which tmux >/dev/null 2>&1 || return + +function tmux_attach_via_proc() { + pid=$(pgrep --newest tmux) + if test -n "$pid" + then + /proc/$pid/exe attach + fi + return 1 +} + +if test -z "$TMUX" +then + (tmux attach || tmux_attach_via_proc || tmux new-session) +fi diff --git a/molecule/testinfra/staging/common/test_user_config.py b/molecule/testinfra/staging/common/test_user_config.py index 3dc6051d3a..2e67f2eb64 100644 --- a/molecule/testinfra/staging/common/test_user_config.py +++ b/molecule/testinfra/staging/common/test_user_config.py @@ -1,3 +1,5 @@ +import hashlib +import os import re @@ -38,16 +40,19 @@ def test_sudoers_tmux_env(host): the corresponding settings there. """ - f = host.file('/etc/profile.d/securedrop_additions.sh') - non_interactive_str = re.escape('[[ $- != *i* ]] && return') - tmux_check = re.escape('test -z "$TMUX" && (tmux attach ||' - ' tmux new-session)') + host_file = host.file('/etc/profile.d/securedrop_additions.sh') + source_file = os.path.abspath( + os.path.join( + os.path.dirname(__file__), + '../../../../install_files/securedrop-config/etc/profile.d', + 'securedrop_additions.sh' + ) + ) + expected_content = open(source_file).read() + h = hashlib.sha256() + h.update(expected_content) - assert f.contains("^{}$".format(non_interactive_str)) - assert f.contains("^if which tmux >\/dev\/null 2>&1; then$") - - assert 'test -z "$TMUX" && (tmux attach || tmux new-session)' in f.content - assert f.contains(tmux_check) + assert host_file.sha256sum == h.hexdigest() def test_tmux_installed(host): From 1e7772472998f179f11c8156493f13e6d930598e Mon Sep 17 00:00:00 2001 From: John Hensley Date: Wed, 13 Mar 2019 15:34:07 -0400 Subject: [PATCH 2/3] Better documentation and tests Comment the tmux_attach_via_proc function in securedrop_additions.sh. Fix version check in builder-trusty/tests/vars.yml. Fix test_sudoers_config so that it requires explicit content in securedrop_additions.sh, instead of just checking that the installed file exactly matches whatever's in the current revision. --- .../etc/profile.d/securedrop_additions.sh | 7 +++- molecule/builder-trusty/tests/vars.yml | 2 +- .../staging/common/test_user_config.py | 39 ++++++++++++------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh b/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh index e6358c03fd..4bab3c8ea3 100644 --- a/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh +++ b/install_files/securedrop-config/etc/profile.d/securedrop_additions.sh @@ -2,7 +2,12 @@ which tmux >/dev/null 2>&1 || return -function tmux_attach_via_proc() { +tmux_attach_via_proc() { + # If the tmux package is upgraded during the lifetime of a + # session, attaching with the new binary can fail due to different + # protocol versions. This function attaches using the reference to + # the old executable found in the /proc tree of an existing + # session. pid=$(pgrep --newest tmux) if test -n "$pid" then diff --git a/molecule/builder-trusty/tests/vars.yml b/molecule/builder-trusty/tests/vars.yml index 66c403a8d5..090bf5aa37 100644 --- a/molecule/builder-trusty/tests/vars.yml +++ b/molecule/builder-trusty/tests/vars.yml @@ -2,7 +2,7 @@ securedrop_version: "0.13.0~rc1" ossec_version: "3.0.0" keyring_version: "0.1.2" -config_version: "0.1.2" +config_version: "0.1.3" grsec_version: "4.4.167" # These values will be interpolated with values populated above diff --git a/molecule/testinfra/staging/common/test_user_config.py b/molecule/testinfra/staging/common/test_user_config.py index 2e67f2eb64..dc509432e1 100644 --- a/molecule/testinfra/staging/common/test_user_config.py +++ b/molecule/testinfra/staging/common/test_user_config.py @@ -1,6 +1,5 @@ -import hashlib -import os import re +import textwrap def test_sudoers_config(host): @@ -41,18 +40,32 @@ def test_sudoers_tmux_env(host): """ host_file = host.file('/etc/profile.d/securedrop_additions.sh') - source_file = os.path.abspath( - os.path.join( - os.path.dirname(__file__), - '../../../../install_files/securedrop-config/etc/profile.d', - 'securedrop_additions.sh' - ) - ) - expected_content = open(source_file).read() - h = hashlib.sha256() - h.update(expected_content) + expected_content = textwrap.dedent( + """\ + [[ $- != *i* ]] && return + + which tmux >/dev/null 2>&1 || return - assert host_file.sha256sum == h.hexdigest() + tmux_attach_via_proc() { + # If the tmux package is upgraded during the lifetime of a + # session, attaching with the new binary can fail due to different + # protocol versions. This function attaches using the reference to + # the old executable found in the /proc tree of an existing + # session. + pid=$(pgrep --newest tmux) + if test -n "$pid" + then + /proc/$pid/exe attach + fi + return 1 + } + + if test -z "$TMUX" + then + (tmux attach || tmux_attach_via_proc || tmux new-session) + fi""" + ) + assert host_file.content_string == expected_content def test_tmux_installed(host): From 690f0e35d8dc931335d6c5c42f058350d1e3cffa Mon Sep 17 00:00:00 2001 From: mickael e Date: Wed, 13 Mar 2019 17:52:21 -0400 Subject: [PATCH 3/3] Add builder tests for securedrop-config At build time, let's ensure: - no conffiles are present so that files in /etc are properly squashed - securedrop-config contains the expected files --- .../tests/test_securedrop_deb_package.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/molecule/builder-trusty/tests/test_securedrop_deb_package.py b/molecule/builder-trusty/tests/test_securedrop_deb_package.py index 472f90e458..f28a896839 100644 --- a/molecule/builder-trusty/tests/test_securedrop_deb_package.py +++ b/molecule/builder-trusty/tests/test_securedrop_deb_package.py @@ -241,7 +241,7 @@ def test_deb_package_contains_expected_conffiles(host, deb): deb_package = host.file(deb.format( securedrop_test_vars.securedrop_version)) - # Only relevant for the securedrop-app-code package: + # For the securedrop-app-code package: if "securedrop-app-code" in deb_package.path: tmpdir = tempfile.mkdtemp() # The `--raw-extract` flag includes `DEBIAN/` dir with control files @@ -255,6 +255,12 @@ def test_deb_package_contains_expected_conffiles(host, deb): conffiles = f.content_string.rstrip() assert conffiles == "/var/www/securedrop/static/i/logo.png" + # For the securedrop-config package, we want to ensure there are no + # conffiles so securedrop_additions.sh is squashed every time + if "securedrop-config" in deb_package.path: + c = host.run("dpkg-deb -I {}".format(deb)) + assert "conffiles" not in c.stdout + @pytest.mark.parametrize("deb", deb_packages) def test_deb_package_contains_css(host, deb): @@ -449,3 +455,21 @@ def test_ossec_binaries_are_present_server(host, deb): c = host.run("dpkg-deb --contents {}".format(deb_package.path)) for wanted_file in wanted_files: assert wanted_file in c.stdout + + +@pytest.mark.parametrize("deb", deb_packages) +def test_config_package_contains_expected_files(host, deb): + """ + Inspect the package contents to ensure all config files are included in + the package. + """ + deb_package = host.file(deb.format( + securedrop_test_vars.securedrop_version)) + if "securedrop-config" in deb_package.path: + wanted_files = [ + "/etc/cron-apt/action.d/9-remove", + "/etc/profile.d/securedrop_additions.sh", + ] + c = host.run("dpkg-deb --contents {}".format(deb_package.path)) + for wanted_file in wanted_files: + assert wanted_file in c.stdout