def test_get_os_info(self, m_distro): import certbot.util as cbutil with mock.patch("platform.system") as mock_platform: m_distro.linux_distribution.return_value = ("name", "version", 'x') mock_platform.return_value = "linux" self.assertEqual(cbutil.get_os_info(), ("name", "version")) m_distro.linux_distribution.return_value = ("something", "else") self.assertEqual(cbutil.get_os_info(), ("something", "else"))
def test_systemd_os_release(self): from certbot.util import (get_os_info, get_systemd_os_info, get_os_info_ua) with mock.patch('certbot.compat.os.path.isfile', return_value=True): self.assertEqual(get_os_info( test_util.vector_path("os-release"))[0], 'systemdos') self.assertEqual(get_os_info( test_util.vector_path("os-release"))[1], '42') self.assertEqual(get_systemd_os_info(os.devnull), ("", "")) self.assertEqual(get_os_info_ua( test_util.vector_path("os-release")), "SystemdOS") with mock.patch('certbot.compat.os.path.isfile', return_value=False): self.assertEqual(get_systemd_os_info(), ("", ""))
def test_systemd_os_release(self): from certbot.util import (get_os_info, get_systemd_os_info, get_os_info_ua) with mock.patch('os.path.isfile', return_value=True): self.assertEqual(get_os_info( test_util.vector_path("os-release"))[0], 'systemdos') self.assertEqual(get_os_info( test_util.vector_path("os-release"))[1], '42') self.assertEqual(get_systemd_os_info(os.devnull), ("", "")) self.assertEqual(get_os_info_ua( test_util.vector_path("os-release")), "SystemdOS") with mock.patch('os.path.isfile', return_value=False): self.assertEqual(get_systemd_os_info(), ("", ""))
def test_user_agent(self, afd, _obt, det, _client): # Normally the client is totally mocked out, but here we need more # arguments to automate it... args = [ "--standalone", "certonly", "-m", "*****@*****.**", "-d", "example.com", '--agree-tos' ] + self.standard_args det.return_value = mock.MagicMock(), None afd.return_value = mock.MagicMock(), "newcert" with mock.patch( 'certbot.main.client.acme_client.ClientNetwork') as acme_net: self._call_no_clientmock(args) os_ver = " ".join(util.get_os_info()) ua = acme_net.call_args[1]["user_agent"] self.assertTrue(os_ver in ua) import platform plat = platform.platform() if "linux" in plat.lower(): self.assertTrue(platform.linux_distribution()[0] in ua) with mock.patch( 'certbot.main.client.acme_client.ClientNetwork') as acme_net: ua = "bandersnatch" args += ["--user-agent", ua] self._call_no_clientmock(args) acme_net.assert_called_once_with(mock.ANY, verify_ssl=True, user_agent=ua)
def get_configurator(): """ Get correct configurator class based on the OS fingerprint """ logger = logging.getLogger(__name__) os_name, os_version = util.get_os_info() os_name = os_name.lower() override_class = None logger.info("OS identified and as: %s", os_name) # Special case for older Fedora versions if os_name == 'fedora' and LooseVersion(os_version) < LooseVersion('29'): os_name = 'fedora_old' try: override_class = OVERRIDE_CLASSES[os_name] logger.info("Configuration for the OS successfully identified") except KeyError: # OS not found in the list logger.warning( "OS not found in the list, beginning to try to find a similar OS") os_like = util.get_systemd_os_like() if os_like: for os_name in os_like: if os_name in OVERRIDE_CLASSES.keys(): override_class = OVERRIDE_CLASSES[os_name] logger.info( "OS Identified as: %s, configuration for the OS found", os_name) if not override_class: # No override class found, return the generic configurator override_class = configurator.ApacheConfigurator logger.warning( "Similar OS not found, default configurator returned." "You may need to inspect the defaults") return override_class
def os_analyse(): """ Returns tuple containing the OS distro and version corresponding with supported versions and caches the result. Output is cached. :returns: (distro, version_nr) :rtype: tuple """ os_info = util.get_os_info() distro = os_info[0].lower() version = os_info[1] if distro not in CLI_DEFAULTS: raise errors.NotSupportedError( "We're sorry, your OS %s %s is currently not supported :(" " you may be able to get this plugin working by defining a list of" " CLI_DEFAULTS in our `constants` module. Please consider making " " a pull-request if you do!") if version not in CLI_DEFAULTS[distro]: min_version = CLI_DEFAULTS[distro]['_min_version'] max_version = CLI_DEFAULTS[distro]['_max_version'] if LooseVersion(version) < LooseVersion(min_version): raise errors.NotSupportedError( "The OS you are using (%s %s) is not supported by this" " plugin, minimum supported version is %s %s", distro, version, distro, version) elif LooseVersion(version) > LooseVersion(max_version): logger.warn( "Your OS version \"%s %s\" is not officially supported by" " this plugin yet. Will try to run with the most recent" " set of constants (%s %s), your mileage may vary.", distro, version, distro, max_version) version = max_version else: # Version within range but not occurring in CLI_DEFAULTS versions = CLI_DEFAULTS[distro] # Only items whose contents stripped of "." are digits, e.g.: 16.04 versions = [v for v in versions if v.replace(".", "").isdigit()] compare = LooseVersion(version) for index, versionno in enumerate(sorted(versions)): # Find the highest supported version number _under_ the # detected version number. In other words: the detected version # number should be smaller than next one in the loop, but # bigger than the current one. # Next version number is? peek = versions[index + 1] if LooseVersion(peek) > compare > LooseVersion(versionno): logger.warn( "Your OS version \"%s %s\" is not officially supported" " by this plugin yet. Will try to run with the most" " recent set of constants of a version before your" " os's (%s %s), your mileage may vary.", distro, version, distro, versionno) version = versionno break return (distro, version)
def test_non_systemd_os_info(self, popen_mock): from certbot.util import (get_os_info, get_python_os_info, get_os_info_ua) with mock.patch('certbot.compat.os.path.isfile', return_value=False): with mock.patch('platform.system_alias', return_value=('NonSystemD', '42', '42')): self.assertEqual(get_os_info()[0], 'nonsystemd') self.assertEqual(get_os_info_ua(), " ".join(get_python_os_info())) with mock.patch('platform.system_alias', return_value=('darwin', '', '')): comm_mock = mock.Mock() comm_attrs = {'communicate.return_value': ('42.42.42', 'error')} comm_mock.configure_mock(**comm_attrs) popen_mock.return_value = comm_mock self.assertEqual(get_os_info()[0], 'darwin') self.assertEqual(get_os_info()[1], '42.42.42') with mock.patch('platform.system_alias', return_value=('linux', '', '')): with mock.patch('platform.linux_distribution', side_effect=AttributeError, create=True): with mock.patch('distro.linux_distribution', return_value=('', '', '')): self.assertEqual(get_python_os_info(), ("linux", "")) with mock.patch('distro.linux_distribution', return_value=('testdist', '42', '')): self.assertEqual(get_python_os_info(), ("testdist", "42")) with mock.patch('platform.system_alias', return_value=('freebsd', '9.3-RC3-p1', '')): self.assertEqual(get_python_os_info(), ("freebsd", "9")) with mock.patch('platform.system_alias', return_value=('windows', '', '')): with mock.patch('platform.win32_ver', return_value=('4242', '95', '2', '')): self.assertEqual(get_python_os_info(), ("windows", "95"))
def os_constant(key): """Get a constant value for operating system :param key: name of cli constant :return: value of constant for active os """ os_info = util.get_os_info() try: constants = CLI_DEFAULTS[os_info[0].lower()] except KeyError: constants = CLI_DEFAULTS["debian"] return constants[key]
def test_non_systemd_os_info(self, popen_mock): from certbot.util import (get_os_info, get_python_os_info, get_os_info_ua) with mock.patch('os.path.isfile', return_value=False): with mock.patch('platform.system_alias', return_value=('NonSystemD', '42', '42')): self.assertEqual(get_os_info()[0], 'nonsystemd') self.assertEqual(get_os_info_ua(), " ".join(get_python_os_info())) with mock.patch('platform.system_alias', return_value=('darwin', '', '')): comm_mock = mock.Mock() comm_attrs = {'communicate.return_value': ('42.42.42', 'error')} comm_mock.configure_mock(**comm_attrs) # pylint: disable=star-args popen_mock.return_value = comm_mock self.assertEqual(get_os_info()[0], 'darwin') self.assertEqual(get_os_info()[1], '42.42.42') with mock.patch('platform.system_alias', return_value=('linux', '', '')): with mock.patch('platform.linux_distribution', return_value=('', '', '')): self.assertEqual(get_python_os_info(), ("linux", "")) with mock.patch('platform.linux_distribution', return_value=('testdist', '42', '')): self.assertEqual(get_python_os_info(), ("testdist", "42")) with mock.patch('platform.system_alias', return_value=('freebsd', '9.3-RC3-p1', '')): self.assertEqual(get_python_os_info(), ("freebsd", "9")) with mock.patch('platform.system_alias', return_value=('windows', '', '')): with mock.patch('platform.win32_ver', return_value=('4242', '95', '2', '')): self.assertEqual(get_python_os_info(), ("windows", "95"))
def _determine_user_agent(config): """ Set a user_agent string in the config based on the choice of plugins. (this wasn't knowable at construction time) :returns: the client's User-Agent string :rtype: `str` """ if config.user_agent is None: ua = "CertbotACMEClient/{0} ({1}) Authenticator/{2} Installer/{3}" ua = ua.format(certbot.__version__, " ".join(util.get_os_info()), config.authenticator, config.installer) else: ua = config.user_agent return ua
def get_configurator(): """ Get correct configurator class based on the OS fingerprint """ os_info = util.get_os_info() override_class = None try: override_class = OVERRIDE_CLASSES[os_info[0].lower()] except KeyError: # OS not found in the list os_like = util.get_systemd_os_like() if os_like: for os_name in os_like: if os_name in OVERRIDE_CLASSES.keys(): override_class = OVERRIDE_CLASSES[os_name] if not override_class: # No override class found, return the generic configurator override_class = configurator.ApacheConfigurator return override_class
def config_test(self): """ Override config_test to mitigate configtest error in vanilla installation of mod_ssl in Fedora. The error is caused by non-existent self-signed certificates referenced by the configuration, that would be autogenerated during the first (re)start of httpd. """ os_info = util.get_os_info() fedora = os_info[0].lower() == "fedora" try: super().config_test() except errors.MisconfigurationError: if fedora: self._try_restart_fedora() else: raise
def get_configurator(): """ Get correct configurator class based on the OS fingerprint """ os_name, os_version = util.get_os_info() os_name = os_name.lower() override_class = None # Special case for older Fedora versions if os_name == 'fedora' and LooseVersion(os_version) < LooseVersion('29'): os_name = 'fedora_old' try: override_class = OVERRIDE_CLASSES[os_name] except KeyError: # OS not found in the list os_like = util.get_systemd_os_like() if os_like: for os_name in os_like: if os_name in OVERRIDE_CLASSES.keys(): override_class = OVERRIDE_CLASSES[os_name] if not override_class: # No override class found, return the generic configurator override_class = configurator.ApacheConfigurator return override_class
def test_user_agent(self, afd, _obt, det, _client): # Normally the client is totally mocked out, but here we need more # arguments to automate it... args = ["--standalone", "certonly", "-m", "*****@*****.**", "-d", "example.com", '--agree-tos'] + self.standard_args det.return_value = mock.MagicMock(), None afd.return_value = mock.MagicMock(), "newcert" with mock.patch('certbot.main.client.acme_client.ClientNetwork') as acme_net: self._call_no_clientmock(args) os_ver = " ".join(util.get_os_info()) ua = acme_net.call_args[1]["user_agent"] self.assertTrue(os_ver in ua) import platform plat = platform.platform() if "linux" in plat.lower(): self.assertTrue(platform.linux_distribution()[0] in ua) with mock.patch('certbot.main.client.acme_client.ClientNetwork') as acme_net: ua = "bandersnatch" args += ["--user-agent", ua] self._call_no_clientmock(args) acme_net.assert_called_once_with(mock.ANY, verify_ssl=True, user_agent=ua)