Repository: freedomofpress/securedrop

Issue:
[xenial] Verify Trusty backup -> Xenial recovery story
We should ensure that a SecureDrop backup completed on 14.04 can successfully be recovered on 16.04. Whether we ask admins to perform this step manually, or whether we automate it, it may be a required part of the Xenial migration and will certainly be highly recommended.

If clean upgrades to Xenial are not yet implemented one should complete this ticket by following these steps instead:

1. Create a backup on 14.04 server
2. Create fresh install on 16.04 and then attempt to run the restore

Part of #3204, may result in follow-up issues.


Discussion:
As of today with commit `10359094085e6c1839490e74e827c3cac1151b8d` from develop, this just works :+1: 
This failed for me while reviewing PR #4080 for `3961-separate-subdir-per-distro-for-deb-pkg-builds`on prod VMs

- did a clean 14.04 install
- took a backup
- did a fresh install on 16.04
- ran `./securedrop-admin restore <filename here>`
- backup completed successfully

After backup, `ssh app` fails, as /var/lib/tor/services is overwritten. Copying `var/lib/tor/services/ssh/hostname` from the tarball to `install_files/ansible-base/app-ssh-aths` and rerunning `./securedrop-admin tailsconfig` didn't restore access, and now ssh to app or mon fails immediately.
Thanks for the report, @zenmonkeykstop . To clarify, you say:

> Copying `var/lib/tor/services/ssh/hostname` from the tarball to `install_files/ansible-base/app-ssh-aths`

Did you run a literal `cp` on that file? Recall that the contents of `app-ssh-aths` must be prefixed with the `HidServAuth` declaration, as handled by this tiny template: https://github.com/freedomofpress/securedrop/blob/003b01721de8b711869d06af7ec4477456a06e79/install_files/ansible-base/roles/restrict-direct-access/templates/ths_config.j2 

Other things to try:

* confirm Tails torrc has the correct HidServAuth line for the SSH services (according to tarball contents)
* `rm -rf ~/.ansible/` on Tails; it's possible ControlPersist files still exist there, but point to a dead socket on the remote host
* console into the app/prod VMs and inspect tor service status, as well as tor/ssh logs
D'oh, didn't add HidServAuth, working fine with that addition. 

Resolving patch:
diff --git a/install_files/ansible-base/roles/restore/files/restore.py b/install_files/ansible-base/roles/restore/files/restore.py
--- a/install_files/ansible-base/roles/restore/files/restore.py
+++ b/install_files/ansible-base/roles/restore/files/restore.py
@@ -8,6 +8,7 @@
 """
 
 import os
+import shutil
 import subprocess
 import sys
 import tarfile
@@ -35,18 +36,29 @@ def verify_args():
 def main():
     verify_args()
 
+    # Remove the /var/lib/tor/services directories to purge values that may have been
+    # generated by running the ansible playbooks
+    for d in ['journalist', 'source']:
+        full_path = os.path.join('/var/lib/tor/services', d)
+        if os.path.exists(full_path):
+            shutil.rmtree(full_path)
+
     with tarfile.open(sys.argv[1], 'r:*') as backup:
         # This assumes that both the old installation (source of the backup)
         # and the new installation (destination of the restore) used the
         # default paths for various locations.
         backup.extractall(path='/')
 
+    # Apply database migrations (if backed-up version < version to restore)
+    subprocess.check_call(['dpkg-reconfigure', 'securedrop-app-code'])
+
+    # Update the configs
+    subprocess.check_call(['dpkg-reconfigure', 'securedrop-config'])
+
     # Reload Tor and the web server so they pick up the new configuration
     # If the process exits with a non-zero return code, raises an exception.
     subprocess.check_call(['service', 'apache2', 'restart'])
     subprocess.check_call(['service', 'tor', 'reload'])
-    # Apply database migrations (if backed-up version < version to restore)
-    subprocess.check_call(['dpkg-reconfigure', 'securedrop-app-code'])
 
 
 if __name__ == "__main__":


Test patch: