certbot/certbot/plugins/dns_common_test.py
Adrien Ferrand d5de24d9fc [Windows] Security model for files permissions - STEP 2 (#6895)
This PR is the second part of #6497 to ease the integration, following the new plan propose by @bmw here: #6497 (comment)

This PR creates the module certbot.compat.os, that delegates everything to os, and that will be the safeguard against problematic methods of the standard module. On top of that, a quality check wrapper is called in the lint tox environment. This wrapper calls pylint and ensures that standard os module is no used directly in the certbot codebase.

Finally local oldest requirements are updated to ensure that tests will take the new logic when running.

* Add executable permissions

* Add the delegate certbot.compat.os module, add check coding style to enforce usage of certbot.compat.os instead of standard os

* Load certbot.compat.os instead of os

* Move existing compat test

* Update local oldest requirements

* Import sys

* Update account_test.py

* Update os.py

* Update os.py

* Update local oldest requirements

* Implement the new linter_plugin

* Fix local oldest for nginx

* Remove check coding style

* Update linter_plugin.py

* Add several comments

* Update the setup.py

* Add documentation

* Update acme dependencies

* Update certbot/compat/os.py

* Update docs/contributing.rst

* Update linter_plugin.py

* Handle os.path. Simplify checker.

* Add a comment to a reference implementation

* Update changelog

* Fix module registering

* Update docs/contributing.rst

* Update config and changelog
2019-04-12 13:32:51 -07:00

229 lines
8.1 KiB
Python

"""Tests for certbot.plugins.dns_common."""
import collections
import logging
import unittest
import mock
from certbot import errors
from certbot.compat import os
from certbot.display import util as display_util
from certbot.plugins import dns_common
from certbot.plugins import dns_test_common
from certbot.tests import util
class DNSAuthenticatorTest(util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest):
# pylint: disable=protected-access
class _FakeDNSAuthenticator(dns_common.DNSAuthenticator):
_setup_credentials = mock.MagicMock()
_perform = mock.MagicMock()
_cleanup = mock.MagicMock()
def more_info(self): # pylint: disable=missing-docstring,no-self-use
return 'A fake authenticator for testing.'
class _FakeConfig(object):
fake_propagation_seconds = 0
fake_config_key = 1
fake_other_key = None
fake_file_path = None
def setUp(self):
super(DNSAuthenticatorTest, self).setUp()
self.config = DNSAuthenticatorTest._FakeConfig()
self.auth = DNSAuthenticatorTest._FakeDNSAuthenticator(self.config, "fake")
def test_perform(self):
self.auth.perform([self.achall])
self.auth._perform.assert_called_once_with(dns_test_common.DOMAIN, mock.ANY, mock.ANY)
def test_cleanup(self):
self.auth._attempt_cleanup = True
self.auth.cleanup([self.achall])
self.auth._cleanup.assert_called_once_with(dns_test_common.DOMAIN, mock.ANY, mock.ANY)
@util.patch_get_utility()
def test_prompt(self, mock_get_utility):
mock_display = mock_get_utility()
mock_display.input.side_effect = ((display_util.OK, "",),
(display_util.OK, "value",))
self.auth._configure("other_key", "")
self.assertEqual(self.auth.config.fake_other_key, "value")
@util.patch_get_utility()
def test_prompt_canceled(self, mock_get_utility):
mock_display = mock_get_utility()
mock_display.input.side_effect = ((display_util.CANCEL, "c",),)
self.assertRaises(errors.PluginError, self.auth._configure, "other_key", "")
@util.patch_get_utility()
def test_prompt_file(self, mock_get_utility):
path = os.path.join(self.tempdir, 'file.ini')
open(path, "wb").close()
mock_display = mock_get_utility()
mock_display.directory_select.side_effect = ((display_util.OK, "",),
(display_util.OK, "not-a-file.ini",),
(display_util.OK, self.tempdir),
(display_util.OK, path,))
self.auth._configure_file("file_path", "")
self.assertEqual(self.auth.config.fake_file_path, path)
@util.patch_get_utility()
def test_prompt_file_canceled(self, mock_get_utility):
mock_display = mock_get_utility()
mock_display.directory_select.side_effect = ((display_util.CANCEL, "c",),)
self.assertRaises(errors.PluginError, self.auth._configure_file, "file_path", "")
def test_configure_credentials(self):
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"fake_test": "value"}, path)
setattr(self.config, "fake_credentials", path)
credentials = self.auth._configure_credentials("credentials", "", {"test": ""})
self.assertEqual(credentials.conf("test"), "value")
@util.patch_get_utility()
def test_prompt_credentials(self, mock_get_utility):
bad_path = os.path.join(self.tempdir, 'bad-file.ini')
dns_test_common.write({"fake_other": "other_value"}, bad_path)
path = os.path.join(self.tempdir, 'file.ini')
dns_test_common.write({"fake_test": "value"}, path)
setattr(self.config, "fake_credentials", "")
mock_display = mock_get_utility()
mock_display.directory_select.side_effect = ((display_util.OK, "",),
(display_util.OK, "not-a-file.ini",),
(display_util.OK, self.tempdir),
(display_util.OK, bad_path),
(display_util.OK, path,))
credentials = self.auth._configure_credentials("credentials", "", {"test": ""})
self.assertEqual(credentials.conf("test"), "value")
class CredentialsConfigurationTest(util.TempDirTestCase):
class _MockLoggingHandler(logging.Handler):
messages = None
def __init__(self, *args, **kwargs):
self.reset()
logging.Handler.__init__(self, *args, **kwargs)
def emit(self, record):
self.messages[record.levelname.lower()].append(record.getMessage())
def reset(self):
"""Allows the handler to be reset between tests."""
self.messages = collections.defaultdict(list)
def test_valid_file(self):
path = os.path.join(self.tempdir, 'too-permissive-file.ini')
dns_test_common.write({"test": "value", "other": 1}, path)
credentials_configuration = dns_common.CredentialsConfiguration(path)
self.assertEqual("value", credentials_configuration.conf("test"))
self.assertEqual("1", credentials_configuration.conf("other"))
def test_nonexistent_file(self):
path = os.path.join(self.tempdir, 'not-a-file.ini')
self.assertRaises(errors.PluginError, dns_common.CredentialsConfiguration, path)
def test_valid_file_with_unsafe_permissions(self):
log = self._MockLoggingHandler()
dns_common.logger.addHandler(log)
path = os.path.join(self.tempdir, 'too-permissive-file.ini')
open(path, "wb").close()
dns_common.CredentialsConfiguration(path)
self.assertEqual(1, len([_ for _ in log.messages['warning'] if _.startswith("Unsafe")]))
class CredentialsConfigurationRequireTest(util.TempDirTestCase):
def setUp(self):
super(CredentialsConfigurationRequireTest, self).setUp()
self.path = os.path.join(self.tempdir, 'file.ini')
def _write(self, values):
dns_test_common.write(values, self.path)
def test_valid(self):
self._write({"test": "value", "other": 1})
credentials_configuration = dns_common.CredentialsConfiguration(self.path)
credentials_configuration.require({"test": "", "other": ""})
def test_valid_but_extra(self):
self._write({"test": "value", "other": 1})
credentials_configuration = dns_common.CredentialsConfiguration(self.path)
credentials_configuration.require({"test": ""})
def test_valid_empty(self):
self._write({})
credentials_configuration = dns_common.CredentialsConfiguration(self.path)
credentials_configuration.require({})
def test_missing(self):
self._write({})
credentials_configuration = dns_common.CredentialsConfiguration(self.path)
self.assertRaises(errors.PluginError, credentials_configuration.require, {"test": ""})
def test_blank(self):
self._write({"test": ""})
credentials_configuration = dns_common.CredentialsConfiguration(self.path)
self.assertRaises(errors.PluginError, credentials_configuration.require, {"test": ""})
def test_typo(self):
self._write({"tets": "typo!"})
credentials_configuration = dns_common.CredentialsConfiguration(self.path)
self.assertRaises(errors.PluginError, credentials_configuration.require, {"test": ""})
class DomainNameGuessTest(unittest.TestCase):
def test_simple_case(self):
self.assertTrue(
'example.com' in
dns_common.base_domain_name_guesses("example.com")
)
def test_sub_domain(self):
self.assertTrue(
'example.com' in
dns_common.base_domain_name_guesses("foo.bar.baz.example.com")
)
def test_second_level_domain(self):
self.assertTrue(
'example.co.uk' in
dns_common.base_domain_name_guesses("foo.bar.baz.example.co.uk")
)
if __name__ == "__main__":
unittest.main() # pragma: no cover