Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Use qubesdb-read instead of gethostname #18

Merged
merged 3 commits into from
Oct 9, 2020
Merged

Conversation

eloquence
Copy link
Member

@eloquence eloquence commented Oct 2, 2020

Description

Switches to the use of qubesdb-read to identify the source VM. This prevents misidentification of Whonix VMs, which always use host as the hostname, and should generally be a bit more qubesy.

Preserves the localvm option mainly for testing outside Qubes; if not set, sd-rsyslog will fail on non-Qubes systems.

Fixes freedomofpress/securedrop-workstation#583

Status

Ready for review.

Test plan

Prerequisites

  • A working, up-to-date SecureDrop Workstation development or staging install.
  • Observe that the file /etc/rsyslog.d/sdlog.conf exists on whonix-gw-15. If not, abort (we'll have to debug why).

Instructions

  1. Build a package from this branch by following the standard securedrop-debian-packaging procedure. You don't have to bump version numbers as long as you don't run the updater during this test. In a nutshell (assuming build prereqs are installed in your dev VM), run python3 setup.py sdist in the securedrop-log checkout and then PKG_VERSION=0.1.1 PKG_PATH=/path/to/package.tgz make securedrop-log in the securedrop-debian-packaging checkout.

  2. Install the package in sd-log-buster-template, sd-app-buster-template, and whonix-gw-15 by copying it there and then running dpkg -i /path/to/package.deb. I took the intermediate step of copying it from my dev VM to dom0 to avoid updating RPC policies.

    Why these three TemplateVMs? Updating the package in sd-log-buster-template ensures that we've not broken the logging package itself. Updating the package in whonix-gw-15 ensures we're actually fixing sd-log sometimes ingests logs as host securedrop-workstation#583. Updating the package in sd-app-buster-template ensures that we've not broken logging from other AppVMs.

  3. Boot up sd-whonix and remove the entire block ### BEGIN securedrop-workstation ###...### END securedrop-workstation ### from /rw/config/rc.local.

    Why this edit? This ensures that the localvm parameter is no longer set late in the boot process (too late, which causes the sorting of early logs into host), and we instead rely on autodetection of the VM name using qubesdb-read, with the version of sd-rsyslog that ships in this package. The related Salt change freedomofpress/securedrop-workstation@ce3a921 will do this automatically.

  4. Shut down all running SD Workstation VMs except sd-log (including templates), then remove or archive all log subdirectories in ~/QubesIncomingLogs on sd-log. We want a clean slate for verifying log behavior.

  5. Reboot the Qubes machine (we want to verify a production-like VM boot sequence). After reboot, do not run the updater to ensure your package change is presreved.

  6. After reboot, examine the contents of ~/QubesIncomingLogs of sd-log.

  • Observe that there is no host directory.
  1. Run a command like logger foo in sd-app and sd-whonix.
  • Observe that the log lines are added in the correct subdirectories of ~/QubesIncomingLogs.
  1. For good measure, run make test in your dom0 SecureDrop Workstation checkout directory. The sd-log test should no longer fail, and there should be no new test failures.

  2. In dom0, run make clean to remove your SecureDrop Workstation setup completely, or run sdw-admin --apply and the updater to restore the previous state.

This prevents misidentification of Whonix VMs, which always use
'host' as the hostname.
@eloquence eloquence marked this pull request as ready for review October 5, 2020 23:42
@eloquence
Copy link
Member Author

eloquence commented Oct 5, 2020

I've tested this extensively and am no longer able to reproduce the host issue with this change in place, while observing no regressions. The test plan is structured so this can be reviewed independently of the related cleanup change in freedomofpress/securedrop-workstation#618, but if the reviewer is feeling ambitious, it would also be easy to review both changes alongside each other by applying the Salt state from freedomofpress/securedrop-workstation#618 instead of editing /rw/config/rc.local by hand.

Copy link
Contributor

@conorsch conorsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works beautifully. Followed the test plan, and am extremely pleased to report the problem appears to be knocked flat! Left some comments about print-vs-logging (which is a bit confusing because this package handles logging).

Regarding the test plan, the only failure I encountered was this:

For good measure, run make test in your dom0 SecureDrop Workstation checkout directory. The sd-log test should no longer fail, and there should be no new test failures.

But that's because the tests had special handling for the sd-whonix case, which we can finally clean up now. I'll tack that on as a comment to freedomofpress/securedrop-workstation#618

sd-rsyslog Outdated
vm_name_output, vm_name_error = get_vm_name_process.communicate()
if vm_name_error != b"":
print("Error obtaining VM name via qubesdb-read:")
print(vm_name_error.decode("utf-8").strip())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The print() statements here should really be logging.error() calls instead, no? Elsewhere in the file there's some inconsistency, but where print() is used it includes file=sys.stderr. In both cases, we should prefer logging.error() AFAICT.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes more sense for sure. Will switch to logging.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 3afc03f, not tested yet.

print(vm_name_error.decode("utf-8").strip())
sys.exit(1)
localvmname = vm_name_output.decode("utf-8").strip()
except FileNotFoundError: # not on Qubes?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed that FileNotFoundError is the proper exception here (same as subprocess.check_output would raise):

>>> from subprocess import Popen
>>> p = Popen(["/bin/echo2", "hello"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/subprocess.py", line 775, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.7/subprocess.py", line 1522, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/bin/echo2': '/bin/echo2'
>>> 

# fails, we exit, to avoid falsely identified logs.
if localvmname is None:
try:
get_vm_name_process = Popen(["/usr/bin/qubesdb-read", "/name"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than Popen, we could use subprocess.check_output() and catch CalledProcessError along with FileNotFoundError below, which would avoid the need to inspect the stderr. Not blocking, though, both are easy enough to read.

sd-rsyslog Outdated
@@ -76,7 +76,8 @@ def onInit():

global process
if not os.path.exists("/etc/sd-rsyslog.conf"):
print("Please create the configuration file at /etc/sd-rsyslog.conf", file=sys.stderr)
logging.exception("Please create the configuration file at /etc/sd-rsyslog.conf",
file=sys.stderr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>>> logging.exception("oops")
ERROR:root:oops
NoneType: None
>>> logging.exception("oops", file=sys.stderr)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/logging/__init__.py", line 1969, in exception
    error(msg, *args, exc_info=exc_info, **kwargs)
  File "/usr/lib/python3.7/logging/__init__.py", line 1961, in error
    root.error(msg, *args, **kwargs)
  File "/usr/lib/python3.7/logging/__init__.py", line 1412, in error
    self._log(ERROR, msg, args, **kwargs)
TypeError: _log() got an unexpected keyword argument 'file'

The file=sys.stderr is leftover from the print() invocation, I'll clean up and proceed with re-review.

Holdover from the previous refactor from 'print' to 'logging.exception'.
@conorsch conorsch self-requested a review October 9, 2020 22:19
Copy link
Contributor

@conorsch conorsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great. Re-tested after changes from previous review, confirmed the "host" dir is no longer showing up. No further asks, looks great. Will wait for freedomofpress/securedrop-workstation#618 to be marked ready-for-review, then tackle that, then we can work on a version bump and packaging PR.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sd-log sometimes ingests logs as host
2 participants