Repository: freedomofpress/securedrop

Issue:
Disable v2 support for Focal installs
(Part of #5731)

Per our [roadmap](https://github.com/freedomofpress/securedrop/wiki/Development-Roadmap), support for v2 onion services will be removed for fresh installs starting with SecureDrop 1.8.0 (tentative release date: 2021-02-23). Accordingly, in addition to disabling v2 onion services during restores (#5677), we should ensure that v2 onion services cannot be configured during a fresh install of SecureDrop 1.8.0 or later.

Currently, during the installation, the user is prompted whether they want to enable v2 and/or v3 onion services, with a deprecation warning for v2:
https://github.com/freedomofpress/securedrop/blob/develop/admin/securedrop_admin/__init__.py#L435-L447

Instead, starting with SecureDrop 1.8.0, we can simply enforce v3 onion services. This should _not_ preclude a v2 onion service from being restored on _Xenial_.

This is consistent with the language in our previous deprecation warning ("support for v2 onion services will be removed in February 2021").


Discussion:
One open question: Do we want to preserve the existing behavior of `./securedrop-admin sdconfig` as-is for previously configured Xenial installs, or do we want to modify it in any way? I think we need to preserve it, so admins can still go through the documented process of v2 -> v2+v3 -> v3 to make the switch.

In that case, we need to detect on an `./securedrop-admin sdconfig` invocation whether this is a fresh install, and only in that case, the onion service configuration options would be hidden.
This is not on the 1/21-2/4 sprint as we're currently still focused on completing and stabilizing Focal support. However, in the coming days, I suggest we finalize the acceptance criteria for this issue.
Discussed during standup and a bit more w/ @zenmonkeykstop later. I'll take a look at the `sdconfig` portion today/tomorrow; current plan of record is to suppress the v2 option if no existing configuration value for it is present. Additionally, we may want to bail early in the install playbook if the server target is running Focal and the user is attempting to enable v2 onion services.
Retitled for clarity. As further discussed in standup today, there are two parts to resolving this issue:

1) Modifying the language in `sdconfig` to make it clear that v2 onion services can only be enabled for Ubuntu 16.04 installs, which is supported for a limited time;

2) Bailing early in the install playbook if a server is running Ubuntu 20.04 and v2 is enabled (IMO regardless of v3 state).

I'll make a tiny string change PR for 1) later and will close the more complex #5811 which seems unduly risky at this late stage.

@zenmonkeykstop and @rmol have offered to look into 2) today or tomorrow.

Resolving patch:
diff --git a/admin/securedrop_admin/__init__.py b/admin/securedrop_admin/__init__.py
--- a/admin/securedrop_admin/__init__.py
+++ b/admin/securedrop_admin/__init__.py
@@ -89,7 +89,23 @@ class JournalistAlertEmailException(Exception):
 # https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators
 _FuncT = TypeVar('_FuncT', bound=Callable[..., Any])
 
-# (var, default, type, prompt, validator, transform, condition)
+# Configuration description tuples drive the CLI user experience and the
+# validation logic of the  securedrop-admin tool. A tuple is in the following
+# format.
+#
+# (var, default, type, prompt, validator, transform, condition):
+#
+# var         configuration variable name (will be stored in `site-specific`)
+# default     default value (can be a callable)
+# type        configuration variable type
+# prompt      text prompt presented to the user
+# validator   input validator based on `prompt_toolkit`'s Validator class
+# transform   transformation function to run on input
+# condition   condition under which this prompt is shown, receives the
+#             in-progress configuration object as input. Used for "if this
+#             then that" branching of prompts.
+#
+# The mypy type description of the format follows.
 _DescEntryType = Tuple[str, _T, Type[_T], str, Optional[Validator], Optional[Callable], Callable]
 
 
@@ -442,9 +458,8 @@ def __init__(self, args: argparse.Namespace) -> None:
              str.split,
              lambda config: True),
             ('v2_onion_services', self.check_for_v2_onion(), bool,
-             'WARNING: For security reasons, support for v2 onion services ' +
-             'will be removed in March 2021. ' +
-             'Do you want to enable v2 onion services?',
+             'WARNING: v2 onion services cannot be installed on servers ' +
+             'running Ubuntu 20.04. Do you want to enable v2 onion services?',
              SiteConfig.ValidateYesNo(),
              lambda x: x.lower() == 'yes',
              lambda config: True),


Test patch: