Repository: freedomofpress/securedrop

Issue:
dead (and non-functional) code in securedrop-admin
## Description

`ValidateDNS`, `ValidateDNSServer`, `ValidateFQDN` appear to be unused in `securedrop_admin.__init__.py`. They also rely on logic that does not currently work with Python 3 (e.g. the `is_tails` method). We should remove these classes.


Discussion:

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,45 +89,6 @@ def validate(self, document):
             raise ValidationError(
                 message="An IP address must be something like 10.240.20.83")
 
-    class ValidateDNS(Validator):
-        def validate(self):
-            raise Exception()  # pragma: no cover
-
-        def is_tails(self):
-            try:
-                id = subprocess.check_output('lsb_release --id --short',
-                                             shell=True).strip()
-            except subprocess.CalledProcessError:
-                id = None
-            return id == 'Tails'
-
-        def lookup_fqdn(self, fqdn, dns=None):
-            cmd = 'host -W=10 -T -4 ' + fqdn
-            if self.is_tails():
-                cmd = 'torify ' + cmd
-            cmd += ' ' + (dns and dns or '8.8.8.8')
-            try:
-                result = subprocess.check_output(cmd.split(' '),
-                                                 stderr=subprocess.STDOUT)
-            except subprocess.CalledProcessError as e:
-                result = e.output
-            sdlog.debug(cmd + ' => ' + result)
-            return 'has address' in result
-
-    class ValidateDNSServer(ValidateDNS):
-        def validate(self, document):
-            if self.lookup_fqdn('gnu.org', document.text):
-                return True
-            raise ValidationError(
-                message='Unable to resolve gnu.org using this DNS')
-
-    class ValidateFQDN(ValidateDNS):
-        def validate(self, document):
-            if self.lookup_fqdn(document.text):
-                return True
-            raise ValidationError(
-                message='Unable to resolve ' + document.text)
-
     class ValidatePath(Validator):
         def __init__(self, basedir):
             self.basedir = basedir


Test patch:
diff --git a/admin/tests/test_securedrop-admin.py b/admin/tests/test_securedrop-admin.py
--- a/admin/tests/test_securedrop-admin.py
+++ b/admin/tests/test_securedrop-admin.py
@@ -445,63 +445,6 @@ def test_validate_optional_email(self):
         assert validator.validate(Document('good@mail.com'))
         assert validator.validate(Document(''))
 
-    def test_is_tails(self):
-        validator = securedrop_admin.SiteConfig.ValidateDNS()
-        with mock.patch('subprocess.check_output', return_value='Tails'):
-            assert validator.is_tails()
-        with mock.patch('subprocess.check_output', return_value='Debian'):
-            assert validator.is_tails() is False
-        with mock.patch('subprocess.check_output',
-                        side_effect=subprocess.CalledProcessError(
-                            1, 'cmd', 'BANG')):
-            assert validator.is_tails() is False
-
-    def test_lookup_dns(self, caplog):
-        validator = securedrop_admin.SiteConfig.ValidateDNS()
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.is_tails',
-                        return_value=True):
-            with mock.patch('subprocess.check_output',
-                            return_value='has address') as check_output:
-                assert validator.lookup_fqdn('gnu.org', '8.8.8.8')
-                assert check_output.call_args[0][0][0] == 'torify'
-                assert check_output.call_args[0][0][6] == '8.8.8.8'
-
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.is_tails',
-                        return_value=False):
-            with mock.patch('subprocess.check_output',
-                            return_value='failed') as check_output:
-                assert validator.lookup_fqdn('gnu.org') is False
-                assert not check_output.call_args[0][0][0] == 'torify'
-                assert 'failed' in caplog.text
-
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.is_tails',
-                        return_value=False):
-            with mock.patch('subprocess.check_output',
-                            side_effect=subprocess.CalledProcessError(
-                                1, 'cmd', 'BANG')):
-                assert validator.lookup_fqdn('gnu.org') is False
-                assert 'BANG' in caplog.text
-
-    def test_validate_dns_server(self, caplog):
-        validator = securedrop_admin.SiteConfig.ValidateDNSServer()
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.lookup_fqdn',
-                        return_value=True):
-            assert validator.validate(Document('8.8.8.8'))
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.lookup_fqdn',
-                        return_value=False):
-            with pytest.raises(ValidationError):
-                validator.validate(Document('8.8.8.8'))
-
-    def test_lookup_fqdn(self, caplog):
-        validator = securedrop_admin.SiteConfig.ValidateFQDN()
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.lookup_fqdn',
-                        return_value=True):
-            assert validator.validate(Document('gnu.org'))
-        with mock.patch('securedrop_admin.SiteConfig.ValidateDNS.lookup_fqdn',
-                        return_value=False):
-            with pytest.raises(ValidationError):
-                assert validator.validate(Document('gnu.org'))
-
     def test_validate_user(self):
         validator = securedrop_admin.SiteConfig.ValidateUser()
         with pytest.raises(ValidationError):