From bc87a692dba5b0eb966236394bb4617d766d6a76 Mon Sep 17 00:00:00 2001 From: Erik Moeller Date: Wed, 5 May 2021 16:24:44 -0700 Subject: [PATCH] Remove v2 onion service support; fix Whonix repo list filename --- README.md | 4 +++- config.json.example | 4 ++-- scripts/validate_config.py | 29 ++++------------------------- tests/test_proxy_vm.py | 2 ++ tests/test_sd_whonix.py | 15 +-------------- 5 files changed, 12 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index c0ae38d1..fddac6fb 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,9 @@ Clone this repo to your preferred location on that VM. Next we need to do some SecureDrop-specific configuration: -- Create a `config.json` file based on `config.json.example` and include your values for the hidserv fields: `hostname` (the Journalist Interface Onion URL) and `key` (the fingerprint for the SecureDrop Submission key). To find the Journalist Interface Onion URL, you can run `sudo cat /var/lib/tor/services/journalist/hostname` on your server. The values for `hostname` and `key` in `config.json.example` are set to the default values for the SecureDrop staging instance. +- Create a `config.json` file based on `config.json.example` and include your values for the hidserv fields: `hostname` (the Journalist Interface Onion URL) and `key` (the private key for client authentication). Set `submission_key_fpr` to the submission key fingerprint. + + - On your Admin Workstation, you can find the Journalist Interface onion address and private key in `~/Persistent/securedrop/install_files/ansible-base/app-journalist.auth_private`, and the submission key fingerprint in `~/Persistent/securedrop/install_files/ansible-base/group_vars/all/site-specific` (`securedrop_app_gpg_fingerprint`). - Create an `sd-journalist.sec` file in the root directory with the ASCII-armored GPG private key used to encrypt submissions in your test SecureDrop instance. The included key `sd-journalist.sec` is the one used by default in the SecureDrop staging instance. diff --git a/config.json.example b/config.json.example index 577f0c4c..5b8e81be 100644 --- a/config.json.example +++ b/config.json.example @@ -1,8 +1,8 @@ { "submission_key_fpr": "65A1B5FF195B56353CC63DFFCC40EF1228271441", "hidserv": { - "hostname": "avgfxawdn6c3coe3.onion", - "key": "Il8Xas7uf6rjtc0LxYwhrx" + "hostname": "sdolvtfhatvsysc6l34d65ymdwxcujausv7k5jk4cy5ttzhjoi6fzvyd.onion", + "key": "5U4JPYSZ34N2ZDSOUAL2YLEX2NPI5BLL2Y66QJW24KLSH7R3FEPQ" }, "environment": "prod", "vmsizes": { diff --git a/scripts/validate_config.py b/scripts/validate_config.py index 56130560..4f129df5 100755 --- a/scripts/validate_config.py +++ b/scripts/validate_config.py @@ -13,9 +13,6 @@ TOR_V3_HOSTNAME_REGEX = r"^[a-z2-7]{56}\.onion$" TOR_V3_AUTH_REGEX = r"^[A-Z2-7]{52}$" -TOR_V2_HOSTNAME_REGEX = r"^[a-z2-7]{16}\.onion$" -TOR_V2_AUTH_COOKIE_REGEX = r"^[a-zA-z0-9+/]{22}$" - # CONFIG_FILEPATH = "/srv/salt/sd/config.json" CONFIG_FILEPATH = "config.json" SECRET_KEY_FILEPATH = "sd-journalist.sec" @@ -59,25 +56,17 @@ def confirm_environment_valid(self): def confirm_onion_config_valid(self): """ - We support both v2 and v3 onion services, so if the values - in the config file match either format, the configuration is considered - valid. A deprecation warning is shown if v2 services are in use. + Only v3 onion services are supported. """ - v2_config = False try: self.confirm_onion_v3_url() self.confirm_onion_v3_auth() except AssertionError: - self.confirm_onion_v2_url() - self.confirm_onion_v2_auth() - v2_config = True - - if v2_config: print( - "WARNING: v2 onion service configuration found.\n" - "Support for v2 onion services will be removed from SecureDrop in February 2021.\n" - "Migration guide: https://securedrop.org/v2-onion-eol/" + "ERROR: Onion service configuration missing or does not match expected format.\n" + "Please note that only v3 onion services are supported.\n" ) + raise def confirm_onion_v3_url(self): assert "hidserv" in self.config @@ -89,16 +78,6 @@ def confirm_onion_v3_auth(self): assert "key" in self.config["hidserv"] assert re.match(TOR_V3_AUTH_REGEX, self.config["hidserv"]["key"]) - def confirm_onion_v2_url(self): - assert "hidserv" in self.config - assert "hostname" in self.config["hidserv"] - assert re.match(TOR_V2_HOSTNAME_REGEX, self.config["hidserv"]["hostname"]) - - def confirm_onion_v2_auth(self): - assert "hidserv" in self.config - assert "key" in self.config["hidserv"] - assert re.match(TOR_V2_AUTH_COOKIE_REGEX, self.config["hidserv"]["key"]) - def confirm_submission_privkey_file(self): assert os.path.exists(self.secret_key_filepath) gpg_cmd = ["gpg", self.secret_key_filepath] diff --git a/tests/test_proxy_vm.py b/tests/test_proxy_vm.py index 37e84c87..989c620f 100644 --- a/tests/test_proxy_vm.py +++ b/tests/test_proxy_vm.py @@ -63,7 +63,9 @@ def test_whonix_ws_repo_absent(self): Guard against regressions by ensuring the old Whonix apt list is missing. """ + # Whonix project changed the repo filename ~2021-05, so check both. assert not self._fileExists("/etc/apt/sources.list.d/whonix.list") + assert not self._fileExists("/etc/apt/sources.list.d/derivative.list") def test_logging_configured(self): self.logging_configured() diff --git a/tests/test_sd_whonix.py b/tests/test_sd_whonix.py index 111d7c96..a8a07837 100644 --- a/tests/test_sd_whonix.py +++ b/tests/test_sd_whonix.py @@ -6,22 +6,10 @@ from base import SD_VM_Local_Test -def v2_onion_services(): - """ - Returns True if v3 address is not setup - """ - with open("config.json") as c: - config = json.load(c) - if len(config["hidserv"]["hostname"]) == 22: - return True - else: - return False - - class SD_Whonix_Tests(SD_VM_Local_Test): def setUp(self): self.vm_name = "sd-whonix" - self.whonix_apt_list = "/etc/apt/sources.list.d/whonix.list" + self.whonix_apt_list = "/etc/apt/sources.list.d/derivative.list" super(SD_Whonix_Tests, self).setUp() def test_accept_sd_xfer_extracted_file(self): @@ -36,7 +24,6 @@ def test_accept_sd_xfer_extracted_file(self): self.assertFileHasLine("/usr/local/etc/torrc.d/50_user.conf", line) - @unittest.skipIf(v2_onion_services(), "Onion v3 address is not setup") def test_v3_auth_private_file(self): with open("config.json") as c: config = json.load(c)