Skip to content

Commit

Permalink
Merge pull request #5915 from freedomofpress/remove-v2-services
Browse files Browse the repository at this point in the history
Removes v2 service configuration and setup support
  • Loading branch information
emkll committed Apr 29, 2021
2 parents 14c9d3a + 0e74ac2 commit a1953db
Show file tree
Hide file tree
Showing 34 changed files with 37 additions and 837 deletions.
79 changes: 2 additions & 77 deletions admin/securedrop_admin/__init__.py
Expand Up @@ -64,7 +64,7 @@
sdlog = logging.getLogger(__name__)
RELEASE_KEY = '22245C81E3BAEB4138B36061310F561200F4AD77'
DEFAULT_KEYSERVER = 'hkps://keys.openpgp.org'
SUPPORT_ONION_URL = 'http://support6kv2242qx.onion'
SUPPORT_ONION_URL = 'http://sup6h5iyiyenvjkfxbgrjynm5wsgijjoatvnvdgyyi7je3xqm4kh6uqd.onion'
SUPPORT_URL = 'https://support.freedom.press'
EXIT_SUCCESS = 0
EXIT_SUBPROCESS_ERROR = 1
Expand Down Expand Up @@ -193,23 +193,6 @@ def validate(self, document: Document) -> bool:
return True
raise ValidationError(message="Must be either yes or no")

class ValidateYesNoForV3(Validator):

def __init__(self, *args: Any, **kwargs: Any) -> None:
Validator.__init__(*args, **kwargs)
self.caller = args[0]

def validate(self, document: Document) -> bool:
text = document.text.lower()
# Raise error if admin tries to disable v3 when v2
# is already disabled.
if text == 'no' and \
not self.caller._config_in_progress.get("v2_onion_services"): # noqa: E501
raise ValidationError(message="Since you disabled v2 onion services, you must enable v3 onion services.") # noqa: E501
if text == 'yes' or text == 'no':
return True
raise ValidationError(message="Must be either yes or no")

class ValidateFingerprint(Validator):
def validate(self, document: Document) -> bool:
text = document.text.replace(' ', '')
Expand Down Expand Up @@ -457,17 +440,6 @@ def __init__(self, args: argparse.Namespace) -> None:
SiteConfig.ValidateLocales(self.args.app_path),
str.split,
lambda config: True),
('v2_onion_services', self.check_for_v2_onion(), bool,
'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),
('v3_onion_services', self.check_for_v3_onion, bool,
'Do you want to enable v3 onion services (recommended)?',
SiteConfig.ValidateYesNoForV3(self),
lambda x: x.lower() == 'yes',
lambda config: True),
] # type: List[_DescEntryType]

def load_and_update_config(self, validate: bool = True, prompt: bool = True) -> bool:
Expand All @@ -485,52 +457,8 @@ def update_config(self, prompt: bool = True) -> bool:
self.save()
self.validate_gpg_keys()
self.validate_journalist_alert_email()
self.validate_https_and_v3()
return True

def validate_https_and_v3(self) -> bool:
"""
Checks if https is enabled with v3 onion service.
:returns: False if both v3 and https enabled, True otherwise.
"""
warning_msg = ("You have configured HTTPS on your source interface "
"and v3 onion services. "
"IMPORTANT: Ensure that you update your certificate "
"to include your v3 source URL before advertising "
"it to sources! ")

if self.config.get("v3_onion_services", False) and \
self.config.get("securedrop_app_https_certificate_cert_src"):
print(warning_msg)
return False
return True

def check_for_v2_onion(self) -> bool:
"""
Check if v2 onion services are already enabled or not.
"""
source_ths = os.path.join(self.args.ansible_path, "app-source-ths")
if os.path.exists(source_ths): # Means old installation
data = ""
with open(source_ths) as fobj:
data = fobj.read()

data = data.strip()
if len(data) < 56: # Old v2 onion address
return True
return False

def check_for_v3_onion(self) -> bool:
"""
Check if v3 onion services should be enabled by default or not.
"""
v2_value = self._config_in_progress.get("v2_onion_services", False)
# We need to see the value in the configuration file
# for v3_onion_services
v3_value = self.config.get("v3_onion_services", True)
return v3_value or not v2_value

def user_prompt_config(self) -> Dict[str, Any]:
self._config_in_progress = {}
for desc in self.desc:
Expand All @@ -547,10 +475,7 @@ def user_prompt_config_one(
self, desc: _DescEntryType, from_config: Optional[Any]
) -> Any:
(var, default, type, prompt, validator, transform, condition) = desc
if from_config is not None and var != "v3_onion_services":
# v3_onion_services must be true if v2 is disabled by the admin
# otherwise, we may end up in a situation where both v2 and v3
# are disabled by the admin (by mistake).
if from_config is not None:
default = from_config
prompt += ': '

Expand Down
227 changes: 0 additions & 227 deletions admin/tests/test_integration.py
Expand Up @@ -47,76 +47,6 @@
smtp_relay: smtp.gmail.com
smtp_relay_port: 587
ssh_users: sd
v2_onion_services: false
v3_onion_services: true
'''

WHEN_BOTH_TRUE = '''app_hostname: app
app_ip: 10.20.2.2
daily_reboot_time: 5
dns_server:
- 8.8.8.8
- 8.8.4.4
enable_ssh_over_tor: true
journalist_alert_email: ''
journalist_alert_gpg_public_key: ''
journalist_gpg_fpr: ''
monitor_hostname: mon
monitor_ip: 10.20.3.2
ossec_alert_email: test@gmail.com
ossec_alert_gpg_public_key: sd_admin_test.pub
ossec_gpg_fpr: 1F544B31C845D698EB31F2FF364F1162D32E7E58
sasl_domain: gmail.com
sasl_password: testpassword
sasl_username: testuser
securedrop_app_gpg_fingerprint: 1F544B31C845D698EB31F2FF364F1162D32E7E58
securedrop_app_gpg_public_key: sd_admin_test.pub
securedrop_app_https_certificate_cert_src: ''
securedrop_app_https_certificate_chain_src: ''
securedrop_app_https_certificate_key_src: ''
securedrop_app_https_on_source_interface: false
securedrop_supported_locales:
- de_DE
- es_ES
smtp_relay: smtp.gmail.com
smtp_relay_port: 587
ssh_users: sd
v2_onion_services: true
v3_onion_services: true
'''

WHEN_ONLY_V2 = '''app_hostname: app
app_ip: 10.20.2.2
daily_reboot_time: 5
dns_server:
- 8.8.8.8
- 8.8.4.4
enable_ssh_over_tor: true
journalist_alert_email: ''
journalist_alert_gpg_public_key: ''
journalist_gpg_fpr: ''
monitor_hostname: mon
monitor_ip: 10.20.3.2
ossec_alert_email: test@gmail.com
ossec_alert_gpg_public_key: sd_admin_test.pub
ossec_gpg_fpr: 1F544B31C845D698EB31F2FF364F1162D32E7E58
sasl_domain: gmail.com
sasl_password: testpassword
sasl_username: testuser
securedrop_app_gpg_fingerprint: 1F544B31C845D698EB31F2FF364F1162D32E7E58
securedrop_app_gpg_public_key: sd_admin_test.pub
securedrop_app_https_certificate_cert_src: ''
securedrop_app_https_certificate_chain_src: ''
securedrop_app_https_certificate_key_src: ''
securedrop_app_https_on_source_interface: false
securedrop_supported_locales:
- de_DE
- es_ES
smtp_relay: smtp.gmail.com
smtp_relay_port: 587
ssh_users: sd
v2_onion_services: true
v3_onion_services: false
'''

JOURNALIST_ALERT_OUTPUT = '''app_hostname: app
Expand Down Expand Up @@ -149,8 +79,6 @@
smtp_relay: smtp.gmail.com
smtp_relay_port: 587
ssh_users: sd
v2_onion_services: false
v3_onion_services: true
'''

HTTPS_OUTPUT = '''app_hostname: app
Expand Down Expand Up @@ -183,8 +111,6 @@
smtp_relay: smtp.gmail.com
smtp_relay_port: 587
ssh_users: sd
v2_onion_services: false
v3_onion_services: true
'''


Expand Down Expand Up @@ -339,21 +265,6 @@ def verify_locales_prompt(child):
child.expect(rb'Space separated list of additional locales to support') # noqa: E501


def verify_v2_onion_for_first_time(child):
child.expect(rb'Do you want to enable v2 onion services\?\:', timeout=2) # noqa: E501
assert ANSI_ESCAPE.sub('', child.buffer.decode("utf-8")).strip() == 'no' # noqa: E501


def verify_v3_onion_for_first_time(child):
child.expect(rb'Do you want to enable v3 onion services \(recommended\)\?\:', timeout=2) # noqa: E501
assert ANSI_ESCAPE.sub('', child.buffer.decode("utf-8")).strip() == 'yes' # noqa: E501


def verify_v3_onion_when_v2_is_enabled(child):
child.expect(rb'Do you want to enable v3 onion services \(recommended\)\?\:', timeout=2) # noqa: E501
assert ANSI_ESCAPE.sub('', child.buffer.decode("utf-8")).strip() == 'yes' # noqa: E501


def verify_install_has_valid_config():
"""
Checks that securedrop-admin install validates the configuration.
Expand Down Expand Up @@ -424,9 +335,7 @@ def test_sdconfig_on_first_run():
child.sendline('')
verify_locales_prompt(child)
child.sendline('de_DE es_ES')
verify_v2_onion_for_first_time(child)
child.sendline('\b' * 3 + 'no')
verify_v3_onion_for_first_time(child)
child.sendline('\b' * 4 + 'yes')

child.expect(pexpect.EOF, timeout=10) # Wait for validation to occur
Expand All @@ -441,134 +350,6 @@ def test_sdconfig_on_first_run():
verify_install_has_valid_config()


def test_sdconfig_both_v2_v3_true():
cmd = os.path.join(os.path.dirname(CURRENT_DIR),
'securedrop_admin/__init__.py')
child = pexpect.spawn('python {0} --force --root {1} sdconfig'.format(cmd, SD_DIR))
verify_username_prompt(child)
child.sendline('')
verify_reboot_prompt(child)
child.sendline('\b5') # backspace and put 5
verify_ipv4_appserver_prompt(child)
child.sendline('')
verify_ipv4_monserver_prompt(child)
child.sendline('')
verify_hostname_app_prompt(child)
child.sendline('')
verify_hostname_mon_prompt(child)
child.sendline('')
verify_dns_prompt(child)
child.sendline('')
verify_app_gpg_key_prompt(child)
child.sendline('\b' * 14 + 'sd_admin_test.pub')
verify_https_prompt(child)
# Default answer is no
child.sendline('')
verify_app_gpg_fingerprint_prompt(child)
child.sendline('1F544B31C845D698EB31F2FF364F1162D32E7E58')
verify_ossec_gpg_key_prompt(child)
child.sendline('\b' * 9 + 'sd_admin_test.pub')
verify_ossec_gpg_fingerprint_prompt(child)
child.sendline('1F544B31C845D698EB31F2FF364F1162D32E7E58')
verify_admin_email_prompt(child)
child.sendline('test@gmail.com')
verify_journalist_gpg_key_prompt(child)
child.sendline('')
verify_smtp_relay_prompt(child)
child.sendline('')
verify_smtp_port_prompt(child)
child.sendline('')
verify_sasl_domain_prompt(child)
child.sendline('')
verify_sasl_username_prompt(child)
child.sendline('testuser')
verify_sasl_password_prompt(child)
child.sendline('testpassword')
verify_ssh_over_lan_prompt(child)
child.sendline('')
verify_locales_prompt(child)
child.sendline('de_DE es_ES')
verify_v2_onion_for_first_time(child)
child.sendline('\b' * 3 + 'yes')
verify_v3_onion_when_v2_is_enabled(child)
child.sendline('\b' * 3 + 'yes')

child.expect(pexpect.EOF, timeout=10) # Wait for validation to occur
child.close()
assert child.exitstatus == 0
assert child.signalstatus is None

with open(os.path.join(SD_DIR, 'install_files/ansible-base/group_vars/all/site-specific')) as fobj: # noqa: E501
data = fobj.read()
assert data == WHEN_BOTH_TRUE

verify_install_has_valid_config()


def test_sdconfig_only_v2_true():
cmd = os.path.join(os.path.dirname(CURRENT_DIR),
'securedrop_admin/__init__.py')
child = pexpect.spawn('python {0} --force --root {1} sdconfig'.format(cmd, SD_DIR))
verify_username_prompt(child)
child.sendline('')
verify_reboot_prompt(child)
child.sendline('\b5') # backspace and put 5
verify_ipv4_appserver_prompt(child)
child.sendline('')
verify_ipv4_monserver_prompt(child)
child.sendline('')
verify_hostname_app_prompt(child)
child.sendline('')
verify_hostname_mon_prompt(child)
child.sendline('')
verify_dns_prompt(child)
child.sendline('')
verify_app_gpg_key_prompt(child)
child.sendline('\b' * 14 + 'sd_admin_test.pub')
verify_https_prompt(child)
# Default answer is no
child.sendline('')
verify_app_gpg_fingerprint_prompt(child)
child.sendline('1F544B31C845D698EB31F2FF364F1162D32E7E58')
verify_ossec_gpg_key_prompt(child)
child.sendline('\b' * 9 + 'sd_admin_test.pub')
verify_ossec_gpg_fingerprint_prompt(child)
child.sendline('1F544B31C845D698EB31F2FF364F1162D32E7E58')
verify_admin_email_prompt(child)
child.sendline('test@gmail.com')
verify_journalist_gpg_key_prompt(child)
child.sendline('')
verify_smtp_relay_prompt(child)
child.sendline('')
verify_smtp_port_prompt(child)
child.sendline('')
verify_sasl_domain_prompt(child)
child.sendline('')
verify_sasl_username_prompt(child)
child.sendline('testuser')
verify_sasl_password_prompt(child)
child.sendline('testpassword')
verify_ssh_over_lan_prompt(child)
child.sendline('')
verify_locales_prompt(child)
child.sendline('de_DE es_ES')
verify_v2_onion_for_first_time(child)
child.sendline('\b' * 3 + 'yes')
verify_v3_onion_when_v2_is_enabled(child)
child.sendline('\b' * 3 + 'no')

child.expect(pexpect.EOF, timeout=10) # Wait for validation to occur
child.close()
assert child.exitstatus == 0
assert child.signalstatus is None

with open(os.path.join(SD_DIR, 'install_files/ansible-base/group_vars/all/site-specific')) as fobj: # noqa: E501
data = fobj.read()
assert data == WHEN_ONLY_V2

verify_install_has_valid_config()


def test_sdconfig_enable_journalist_alerts():
cmd = os.path.join(os.path.dirname(CURRENT_DIR),
'securedrop_admin/__init__.py')
Expand Down Expand Up @@ -621,10 +402,6 @@ def test_sdconfig_enable_journalist_alerts():
child.sendline('')
verify_locales_prompt(child)
child.sendline('de_DE es_ES')
verify_v2_onion_for_first_time(child)
child.sendline('\b' * 3 + 'no')
verify_v3_onion_for_first_time(child)
child.sendline('\b' * 4 + 'yes')

child.expect(pexpect.EOF, timeout=10) # Wait for validation to occur
child.close()
Expand Down Expand Up @@ -697,10 +474,6 @@ def test_sdconfig_enable_https_on_source_interface():
child.sendline('')
verify_locales_prompt(child)
child.sendline('de_DE es_ES')
verify_v2_onion_for_first_time(child)
child.sendline('\b' * 3 + 'no')
verify_v3_onion_for_first_time(child)
child.sendline('\b' * 4 + 'yes')

child.expect(pexpect.EOF, timeout=10) # Wait for validation to occur
child.close()
Expand Down

0 comments on commit a1953db

Please sign in to comment.