Hello community, here is the log from the commit of package python-certbot-nginx for openSUSE:Factory checked in at 2019-06-03 18:50:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-certbot-nginx (Old) and /work/SRC/openSUSE:Factory/.python-certbot-nginx.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-certbot-nginx" Mon Jun 3 18:50:49 2019 rev:6 rq:705634 version:0.34.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-certbot-nginx/python-certbot-nginx.changes 2019-03-19 10:01:03.279912118 +0100 +++ /work/SRC/openSUSE:Factory/.python-certbot-nginx.new.5148/python-certbot-nginx.changes 2019-06-03 18:50:50.876527332 +0200 @@ -1,0 +2,6 @@ +Sat May 18 23:11:25 UTC 2019 - Dirk Mueller <dmuel...@suse.com> + +- update to 0.34.0 + * update for main certbot package + +------------------------------------------------------------------- Old: ---- certbot-nginx-0.32.0.tar.gz New: ---- certbot-nginx-0.34.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-certbot-nginx.spec ++++++ --- /var/tmp/diff_new_pack.AazCNU/_old 2019-06-03 18:50:52.348526827 +0200 +++ /var/tmp/diff_new_pack.AazCNU/_new 2019-06-03 18:50:52.352526825 +0200 @@ -18,14 +18,14 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-certbot-nginx -Version: 0.32.0 +Version: 0.34.2 Release: 0 Summary: Nginx plugin for Certbot License: Apache-2.0 Group: Development/Languages/Python URL: https://github.com/letsencrypt/letsencrypt Source: https://files.pythonhosted.org/packages/source/c/certbot-nginx/certbot-nginx-%{version}.tar.gz -BuildRequires: %{python_module certbot >= 0.22.0} +BuildRequires: %{python_module certbot >= 0.34.0} BuildRequires: %{python_module mock} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools} @@ -33,8 +33,8 @@ BuildRequires: nginx BuildRequires: python-rpm-macros Requires: nginx -Requires: python-acme >= 0.26.0 -Requires: python-certbot >= 0.22.0 +Requires: python-acme >= 0.29.0 +Requires: python-certbot >= 0.34.0 Requires: python-pyOpenSSL Requires: python-pyparsing >= 1.5.5 Requires: python-zope.interface ++++++ certbot-nginx-0.32.0.tar.gz -> certbot-nginx-0.34.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/PKG-INFO new/certbot-nginx-0.34.2/PKG-INFO --- old/certbot-nginx-0.32.0/PKG-INFO 2019-03-06 21:18:24.000000000 +0100 +++ new/certbot-nginx-0.34.2/PKG-INFO 2019-05-07 21:17:43.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: certbot-nginx -Version: 0.32.0 +Version: 0.34.2 Summary: Nginx plugin for Certbot Home-page: https://github.com/letsencrypt/letsencrypt Author: Certbot Project diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/configurator.py new/certbot-nginx-0.34.2/certbot_nginx/configurator.py --- old/certbot-nginx-0.32.0/certbot_nginx/configurator.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/configurator.py 2019-05-07 21:17:32.000000000 +0200 @@ -1,6 +1,5 @@ """Nginx Configuration""" import logging -import os import re import socket import subprocess @@ -12,25 +11,23 @@ from acme import challenges from acme import crypto_util as acme_crypto_util +from acme.magic_typing import List, Dict, Set # pylint: disable=unused-import, no-name-in-module -from certbot import compat from certbot import constants as core_constants from certbot import crypto_util from certbot import errors from certbot import interfaces from certbot import util - +from certbot.compat import misc +from certbot.compat import os from certbot.plugins import common from certbot_nginx import constants from certbot_nginx import display_ops +from certbot_nginx import http_01 from certbot_nginx import nginxparser +from certbot_nginx import obj # pylint: disable=unused-import from certbot_nginx import parser -from certbot_nginx import tls_sni_01 -from certbot_nginx import http_01 -from certbot_nginx import obj # pylint: disable=unused-import -from acme.magic_typing import List, Dict, Set # pylint: disable=unused-import, no-name-in-module - NAME_RANK = 0 START_WILDCARD_RANK = 1 @@ -149,7 +146,6 @@ # Make sure configuration is valid self.config_test() - self.parser = parser.NginxParser(self.conf('server-root')) install_ssl_options_conf(self.mod_ssl_conf, self.updated_mod_ssl_conf_digest) @@ -170,7 +166,6 @@ # Entry point in main.py for installing cert def deploy_cert(self, domain, cert_path, key_path, chain_path=None, fullchain_path=None): - # pylint: disable=unused-argument """Deploys certificate to specified virtual host. .. note:: Aborts if the vhost is missing ssl_certificate or @@ -191,8 +186,7 @@ for vhost in vhosts: self._deploy_cert(vhost, cert_path, key_path, chain_path, fullchain_path) - def _deploy_cert(self, vhost, cert_path, key_path, chain_path, fullchain_path): - # pylint: disable=unused-argument + def _deploy_cert(self, vhost, cert_path, key_path, chain_path, fullchain_path): # pylint: disable=unused-argument """ Helper function for deploy_cert() that handles the actual deployment this exists because we might want to do multiple deployments per @@ -297,7 +291,7 @@ if create_if_no_match: # result will not be [None] because it errors on failure vhosts = [self._vhost_from_duplicated_default(target_name, True, - str(self.config.tls_sni_01_port))] + str(self.config.https_port))] else: # No matches. Raise a misconfiguration error. raise errors.MisconfigurationError( @@ -415,9 +409,8 @@ rank = matches[0]['rank'] wildcards = [x for x in matches if x['rank'] == rank] return max(wildcards, key=lambda x: len(x['name']))['vhost'] - else: - # Exact or regex match - return matches[0]['vhost'] + # Exact or regex match + return matches[0]['vhost'] def _rank_matches_by_name(self, vhost_list, target_name): """Returns a ranked list of vhosts from vhost_list that match target_name. @@ -511,25 +504,23 @@ if matching_port == "" or matching_port is None: # if no port is specified, Nginx defaults to listening on port 80. return test_port == self.DEFAULT_LISTEN_PORT - else: - return test_port == matching_port + return test_port == matching_port def _vhost_listening_on_port_no_ssl(self, vhost, port): found_matching_port = False - if len(vhost.addrs) == 0: + if not vhost.addrs: # if there are no listen directives at all, Nginx defaults to # listening on port 80. found_matching_port = (port == self.DEFAULT_LISTEN_PORT) else: for addr in vhost.addrs: - if self._port_matches(port, addr.get_port()) and addr.ssl == False: + if self._port_matches(port, addr.get_port()) and not addr.ssl: found_matching_port = True if found_matching_port: # make sure we don't have an 'ssl on' directive return not self.parser.has_ssl_on_directive(vhost) - else: - return False + return False def _get_redirect_ranked_matches(self, target_name, port): """Gets a ranked list of plaintextish port-listening vhosts matching target_name @@ -561,7 +552,7 @@ :rtype: set """ - all_names = set() # type: Set[str] + all_names = set() # type: Set[str] for vhost in self.parser.get_vhosts(): all_names.update(vhost.names) @@ -611,13 +602,14 @@ :type vhost: :class:`~certbot_nginx.obj.VirtualHost` """ - ipv6info = self.ipv6_info(self.config.tls_sni_01_port) + https_port = self.config.https_port + ipv6info = self.ipv6_info(https_port) ipv6_block = [''] ipv4_block = [''] # If the vhost was implicitly listening on the default Nginx port, # have it continue to do so. - if len(vhost.addrs) == 0: + if not vhost.addrs: listen_block = [['\n ', 'listen', ' ', self.DEFAULT_LISTEN_PORT]] self.parser.add_server_directives(vhost, listen_block) @@ -625,7 +617,7 @@ ipv6_block = ['\n ', 'listen', ' ', - '[::]:{0}'.format(self.config.tls_sni_01_port), + '[::]:{0}'.format(https_port), ' ', 'ssl'] if not ipv6info[1]: @@ -637,7 +629,7 @@ ipv4_block = ['\n ', 'listen', ' ', - '{0}'.format(self.config.tls_sni_01_port), + '{0}'.format(https_port), ' ', 'ssl'] @@ -799,8 +791,6 @@ :param str domain: domain to enable redirect for :param `~obj.Vhost` vhost: vhost to enable redirect for """ - - http_vhost = None if vhost.ssl: http_vhost, _ = self._split_block(vhost, ['listen', 'server_name']) @@ -898,7 +888,7 @@ have permissions of root. """ - uid = compat.os_geteuid() + uid = misc.os_geteuid() util.make_or_verify_dir( self.config.work_dir, core_constants.CONFIG_DIRS_MODE, uid) util.make_or_verify_dir( @@ -1051,19 +1041,14 @@ """ self._chall_out += len(achalls) responses = [None] * len(achalls) - sni_doer = tls_sni_01.NginxTlsSni01(self) http_doer = http_01.NginxHttp01(self) for i, achall in enumerate(achalls): # Currently also have chall_doer hold associated index of the # challenge. This helps to put all of the responses back together # when they are all complete. - if isinstance(achall.chall, challenges.HTTP01): - http_doer.add_chall(achall, i) - else: # tls-sni-01 - sni_doer.add_chall(achall, i) + http_doer.add_chall(achall, i) - sni_response = sni_doer.perform() http_response = http_doer.perform() # Must restart in order to activate the challenges. # Handled here because we may be able to load up other challenge types @@ -1072,9 +1057,8 @@ # Go through all of the challenges and assign them to the proper place # in the responses return value. All responses must be in the same order # as the original challenges. - for chall_response, chall_doer in ((sni_response, sni_doer), (http_response, http_doer)): - for i, resp in enumerate(chall_response): - responses[chall_doer.indices[i]] = resp + for i, resp in enumerate(http_response): + responses[http_doer.indices[i]] = resp return responses @@ -1152,6 +1136,7 @@ return common.install_version_controlled_file(options_ssl, options_ssl_digest, constants.MOD_SSL_CONF_SRC, constants.ALL_SSL_OPTIONS_HASHES) + def _determine_default_server_root(): if os.environ.get("CERTBOT_DOCS") == "1": default_server_root = "%s or %s" % (constants.LINUX_SERVER_ROOT, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/constants.py new/certbot-nginx-0.34.2/certbot_nginx/constants.py --- old/certbot-nginx-0.32.0/certbot_nginx/constants.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/constants.py 2019-05-07 21:17:32.000000000 +0200 @@ -1,7 +1,8 @@ """nginx plugin constants.""" -import pkg_resources import platform +import pkg_resources + FREEBSD_DARWIN_SERVER_ROOT = "/usr/local/etc/nginx" LINUX_SERVER_ROOT = "/etc/nginx" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/display_ops.py new/certbot-nginx-0.34.2/certbot_nginx/display_ops.py --- old/certbot-nginx-0.32.0/certbot_nginx/display_ops.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/display_ops.py 2019-05-07 21:17:32.000000000 +0200 @@ -22,7 +22,7 @@ return list() tags_list = [vhost.display_repr()+"\n" for vhost in vhosts] # Remove the extra newline from the last entry - if len(tags_list): + if tags_list: tags_list[-1] = tags_list[-1][:-1] code, names = zope.component.getUtility(interfaces.IDisplay).checklist( "Which server blocks would you like to modify?", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/http_01.py new/certbot-nginx-0.34.2/certbot_nginx/http_01.py --- old/certbot-nginx-0.32.0/certbot_nginx/http_01.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/http_01.py 2019-05-07 21:17:32.000000000 +0200 @@ -1,16 +1,16 @@ """A class that performs HTTP-01 challenges for Nginx""" import logging -import os from acme import challenges +from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module from certbot import errors +from certbot.compat import os from certbot.plugins import common from certbot_nginx import obj from certbot_nginx import nginxparser -from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module logger = logging.getLogger(__name__) @@ -204,3 +204,4 @@ ' ', '$1', ' ', 'break']] self.configurator.parser.add_server_directives(vhost, rewrite_directive, insert_at_top=True) + return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/obj.py new/certbot-nginx-0.34.2/certbot_nginx/obj.py --- old/certbot-nginx-0.32.0/certbot_nginx/obj.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/obj.py 2019-05-07 21:17:32.000000000 +0200 @@ -84,7 +84,7 @@ port = tup[2] # The rest of the parts are options; we only care about ssl and default - while len(parts) > 0: + while parts: nextpart = parts.pop() if nextpart == 'ssl': ssl = True @@ -120,7 +120,7 @@ def __repr__(self): return "Addr(" + self.__str__() + ")" - def __hash__(self): + def __hash__(self): # pylint: disable=useless-super-delegation # Python 3 requires explicit overridden for __hash__ # See certbot-apache/certbot_apache/obj.py for more information return super(Addr, self).__hash__() @@ -224,15 +224,17 @@ for a in self.addrs: if a.ipv6: return True + return False def ipv4_enabled(self): """Return true if one or more of the listen directives in vhost are IPv4 only""" - if self.addrs is None or len(self.addrs) == 0: + if not self.addrs: return True for a in self.addrs: if not a.ipv6: return True + return False def display_repr(self): """Return a representation of VHost to be used in dialog""" @@ -250,7 +252,7 @@ """Find a directive of type directive_name in directives. If match_content is given, Searches for `match_content` in the directive arguments. """ - if not directives or isinstance(directives, six.string_types) or len(directives) == 0: + if not directives or isinstance(directives, six.string_types): return None # If match_content is None, just match on directive type. Otherwise, match on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/parser.py new/certbot-nginx-0.34.2/certbot_nginx/parser.py --- old/certbot-nginx-0.32.0/certbot_nginx/parser.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/parser.py 2019-05-07 21:17:32.000000000 +0200 @@ -3,13 +3,13 @@ import functools import glob import logging -import os -import pyparsing import re +import pyparsing import six from certbot import errors +from certbot.compat import os from certbot_nginx import obj from certbot_nginx import nginxparser @@ -52,6 +52,7 @@ :param str filepath: The path to the files to parse, as a glob """ + # pylint: disable=too-many-nested-blocks filepath = self.abs_path(filepath) trees = self._parse_files(filepath) for tree in trees: @@ -82,8 +83,7 @@ """ if not os.path.isabs(path): return os.path.normpath(os.path.join(self.root, path)) - else: - return os.path.normpath(path) + return os.path.normpath(path) def _build_addr_to_ssl(self): """Builds a map from address to whether it listens on ssl in any server block @@ -381,7 +381,7 @@ if only_directives is not None: new_directives = nginxparser.UnspacedList([]) for directive in raw_in_parsed[1]: - if len(directive) > 0 and directive[0] in only_directives: + if directive and directive[0] in only_directives: new_directives.append(directive) raw_in_parsed[1] = new_directives @@ -394,7 +394,7 @@ addr.default = False addr.ipv6only = False for directive in enclosing_block[new_vhost.path[-1]][1]: - if len(directive) > 0 and directive[0] == 'listen': + if directive and directive[0] == 'listen': # Exclude one-time use parameters which will cause an error if repeated. # https://nginx.org/en/docs/http/ngx_http_core_module.html#listen exclude = set(('default_server', 'default', 'setfib', 'fastopen', 'backlog', @@ -465,19 +465,19 @@ elif _regex_match(target_name, name): regex.append(name) - if len(exact) > 0: + if exact: # There can be more than one exact match; e.g. eff.org, .eff.org match = min(exact, key=len) return ('exact', match) - if len(wildcard_start) > 0: + if wildcard_start: # Return the longest wildcard match = max(wildcard_start, key=len) return ('wildcard_start', match) - if len(wildcard_end) > 0: + if wildcard_end: # Return the longest wildcard match = max(wildcard_end, key=len) return ('wildcard_end', match) - if len(regex) > 0: + if regex: # Just return the first one for now match = regex[0] return ('regex', match) @@ -522,10 +522,7 @@ # After tilde is a perl-compatible regex try: regex = re.compile(name[1:]) - if re.match(regex, target_name): - return True - else: - return False + return re.match(regex, target_name) except re.error: # pragma: no cover # perl-compatible regexes are sometimes not recognized by python return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/parser_obj.py new/certbot-nginx-0.34.2/certbot_nginx/parser_obj.py --- old/certbot-nginx-0.32.0/certbot_nginx/parser_obj.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/parser_obj.py 2019-05-07 21:17:32.000000000 +0200 @@ -13,6 +13,7 @@ COMMENT = " managed by Certbot" COMMENT_BLOCK = ["#", COMMENT] + class Parsable(object): """ Abstract base class for "Parsable" objects whose underlying representation is a tree of lists. @@ -112,6 +113,7 @@ """ return [elem.dump(include_spaces) for elem in self._data] + class Statements(Parsable): """ A group or list of "Statements". A Statement is either a Block or a Sentence. @@ -142,24 +144,23 @@ if self.parent is not None: self._trailing_whitespace = "\n" + self.parent.get_tabs() - def parse(self, parse_this, add_spaces=False): + def parse(self, raw_list, add_spaces=False): """ Parses a list of statements. - Expects all elements in `parse_this` to be parseable by `type(self).parsing_hooks`, - with an optional whitespace string at the last index of `parse_this`. + Expects all elements in `raw_list` to be parseable by `type(self).parsing_hooks`, + with an optional whitespace string at the last index of `raw_list`. """ - if not isinstance(parse_this, list): + if not isinstance(raw_list, list): raise errors.MisconfigurationError("Statements parsing expects a list!") # If there's a trailing whitespace in the list of statements, keep track of it. - if len(parse_this) > 0 and isinstance(parse_this[-1], six.string_types) \ - and parse_this[-1].isspace(): - self._trailing_whitespace = parse_this[-1] - parse_this = parse_this[:-1] - self._data = [parse_raw(elem, self, add_spaces) for elem in parse_this] + if raw_list and isinstance(raw_list[-1], six.string_types) and raw_list[-1].isspace(): + self._trailing_whitespace = raw_list[-1] + raw_list = raw_list[:-1] + self._data = [parse_raw(elem, self, add_spaces) for elem in raw_list] def get_tabs(self): """ Takes a guess at the tabbing of all contained Statements by retrieving the tabbing of the first Statement.""" - if len(self._data) > 0: + if self._data: return self._data[0].get_tabs() return "" @@ -179,6 +180,7 @@ # ======== End overridden functions + def _space_list(list_): """ Inserts whitespace between adjacent non-whitespace tokens. """ spaced_statement = [] # type: List[str] @@ -188,6 +190,7 @@ spaced_statement.insert(0, " ") return spaced_statement + class Sentence(Parsable): """ A list of words. Non-whitespace words are typically separated with whitespace tokens. """ @@ -205,15 +208,15 @@ return isinstance(lists, list) and len(lists) > 0 and \ all([isinstance(elem, six.string_types) for elem in lists]) - def parse(self, parse_this, add_spaces=False): + def parse(self, raw_list, add_spaces=False): """ Parses a list of string types into this object. If add_spaces is set, adds whitespace tokens between adjacent non-whitespace tokens.""" if add_spaces: - parse_this = _space_list(parse_this) - if not isinstance(parse_this, list) or \ - any([not isinstance(elem, six.string_types) for elem in parse_this]): + raw_list = _space_list(raw_list) + if not isinstance(raw_list, list) or \ + any([not isinstance(elem, six.string_types) for elem in raw_list]): raise errors.MisconfigurationError("Sentence parsing expects a list of string types.") - self._data = parse_this + self._data = raw_list def iterate(self, expanded=False, match=None): """ Simply yields itself. """ @@ -255,6 +258,7 @@ def __contains__(self, word): return word in self.words + class Block(Parsable): """ Any sort of bloc, denoted by a block name and curly braces, like so: The parsed block: @@ -297,26 +301,26 @@ for elem in self.contents.iterate(expanded, match): yield elem - def parse(self, parse_this, add_spaces=False): + def parse(self, raw_list, add_spaces=False): """ Parses a list that resembles a block. The assumptions that this routine makes are: - 1. the first element of `parse_this` is a valid Sentence. - 2. the second element of `parse_this` is a valid Statement. + 1. the first element of `raw_list` is a valid Sentence. + 2. the second element of `raw_list` is a valid Statement. If add_spaces is set, we call it recursively on `names` and `contents`, and add an extra trailing space to `names` (to separate the block's opening bracket and the block name). """ - if not Block.should_parse(parse_this): + if not Block.should_parse(raw_list): raise errors.MisconfigurationError("Block parsing expects a list of length 2. " "First element should be a list of string types (the bloc names), " "and second should be another list of statements (the bloc content).") self.names = Sentence(self) if add_spaces: - parse_this[0].append(" ") - self.names.parse(parse_this[0], add_spaces) + raw_list[0].append(" ") + self.names.parse(raw_list[0], add_spaces) self.contents = Statements(self) - self.contents.parse(parse_this[1], add_spaces) + self.contents.parse(raw_list[1], add_spaces) self._data = [self.names, self.contents] def get_tabs(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/tests/configurator_test.py new/certbot-nginx-0.34.2/certbot_nginx/tests/configurator_test.py --- old/certbot-nginx-0.32.0/certbot_nginx/tests/configurator_test.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/tests/configurator_test.py 2019-05-07 21:17:32.000000000 +0200 @@ -1,17 +1,16 @@ # pylint: disable=too-many-public-methods """Test for certbot_nginx.configurator.""" -import os import unittest -import mock import OpenSSL - +import mock from acme import challenges from acme import messages from certbot import achallenges from certbot import crypto_util from certbot import errors +from certbot.compat import os from certbot.tests import util as certbot_test_util from certbot_nginx import constants @@ -318,21 +317,13 @@ ]], parsed_migration_conf[0]) - @mock.patch("certbot_nginx.configurator.tls_sni_01.NginxTlsSni01.perform") @mock.patch("certbot_nginx.configurator.http_01.NginxHttp01.perform") @mock.patch("certbot_nginx.configurator.NginxConfigurator.restart") @mock.patch("certbot_nginx.configurator.NginxConfigurator.revert_challenge_config") - def test_perform_and_cleanup(self, mock_revert, mock_restart, mock_http_perform, - mock_tls_perform): + def test_perform_and_cleanup(self, mock_revert, mock_restart, mock_http_perform): # Only tests functionality specific to configurator.perform # Note: As more challenges are offered this will have to be expanded - achall1 = achallenges.KeyAuthorizationAnnotatedChallenge( - challb=messages.ChallengeBody( - chall=challenges.TLSSNI01(token=b"kNdwjwOeX0I_A8DXt9Msmg"), - uri="https://ca.org/chall0_uri", - status=messages.Status("pending"), - ), domain="localhost", account_key=self.rsa512jwk) - achall2 = achallenges.KeyAuthorizationAnnotatedChallenge( + achall = achallenges.KeyAuthorizationAnnotatedChallenge( challb=messages.ChallengeBody( chall=challenges.HTTP01(token=b"m8TdO1qik4JVFtgPPurJmg"), uri="https://ca.org/chall1_uri", @@ -340,19 +331,16 @@ ), domain="example.com", account_key=self.rsa512jwk) expected = [ - achall1.response(self.rsa512jwk), - achall2.response(self.rsa512jwk), + achall.response(self.rsa512jwk), ] - mock_tls_perform.return_value = expected[:1] - mock_http_perform.return_value = expected[1:] - responses = self.config.perform([achall1, achall2]) + mock_http_perform.return_value = expected[:] + responses = self.config.perform([achall]) - self.assertEqual(mock_tls_perform.call_count, 1) self.assertEqual(mock_http_perform.call_count, 1) self.assertEqual(responses, expected) - self.config.cleanup([achall1, achall2]) + self.config.cleanup([achall]) self.assertEqual(0, self.config._chall_out) # pylint: disable=protected-access self.assertEqual(mock_revert.call_count, 1) self.assertEqual(mock_restart.call_count, 2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/tests/parser_test.py new/certbot-nginx-0.34.2/certbot_nginx/tests/parser_test.py --- old/certbot-nginx-0.32.0/certbot_nginx/tests/parser_test.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/tests/parser_test.py 2019-05-07 21:17:32.000000000 +0200 @@ -1,25 +1,23 @@ """Tests for certbot_nginx.parser.""" import glob -import os import re import shutil import unittest +from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module + from certbot import errors +from certbot.compat import os from certbot_nginx import nginxparser from certbot_nginx import obj from certbot_nginx import parser from certbot_nginx.tests import util -from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module class NginxParserTest(util.NginxTest): #pylint: disable=too-many-public-methods """Nginx Parser Test.""" - def setUp(self): - super(NginxParserTest, self).setUp() - def tearDown(self): shutil.rmtree(self.temp_dir) shutil.rmtree(self.config_dir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/tests/tls_sni_01_test.py new/certbot-nginx-0.34.2/certbot_nginx/tests/tls_sni_01_test.py --- old/certbot-nginx-0.32.0/certbot_nginx/tests/tls_sni_01_test.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/tests/tls_sni_01_test.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,158 +0,0 @@ -"""Tests for certbot_nginx.tls_sni_01""" -import unittest - -import mock -import six - -from acme import challenges - -from certbot import achallenges -from certbot import errors - -from certbot.plugins import common_test -from certbot.tests import acme_util - -from certbot_nginx import obj -from certbot_nginx.tests import util - - -class TlsSniPerformTest(util.NginxTest): - """Test the NginxTlsSni01 challenge.""" - - account_key = common_test.AUTH_KEY - achalls = [ - achallenges.KeyAuthorizationAnnotatedChallenge( - challb=acme_util.chall_to_challb( - challenges.TLSSNI01(token=b"kNdwjwOeX0I_A8DXt9Msmg"), "pending"), - domain="www.example.com", account_key=account_key), - achallenges.KeyAuthorizationAnnotatedChallenge( - challb=acme_util.chall_to_challb( - challenges.TLSSNI01( - token=b"\xba\xa9\xda?<m\xaewmx\xea\xad\xadv\xf4\x02\xc9y" - b"\x80\xe2_X\t\xe7\xc7\xa4\t\xca\xf7&\x945" - ), "pending"), - domain="another.alias", account_key=account_key), - achallenges.KeyAuthorizationAnnotatedChallenge( - challb=acme_util.chall_to_challb( - challenges.TLSSNI01( - token=b"\x8c\x8a\xbf_-f\\cw\xee\xd6\xf8/\xa5\xe3\xfd" - b"\xeb9\xf1\xf5\xb9\xefVM\xc9w\xa4u\x9c\xe1\x87\xb4" - ), "pending"), - domain="www.example.org", account_key=account_key), - achallenges.KeyAuthorizationAnnotatedChallenge( - challb=acme_util.chall_to_challb( - challenges.TLSSNI01(token=b"kNdwjxOeX0I_A8DXt9Msmg"), "pending"), - domain="sslon.com", account_key=account_key), - ] - - def setUp(self): - super(TlsSniPerformTest, self).setUp() - - config = util.get_nginx_configurator( - self.config_path, self.config_dir, self.work_dir, self.logs_dir) - - from certbot_nginx import tls_sni_01 - self.sni = tls_sni_01.NginxTlsSni01(config) - - @mock.patch("certbot_nginx.configurator" - ".NginxConfigurator.choose_vhosts") - def test_perform(self, mock_choose): - self.sni.add_chall(self.achalls[1]) - mock_choose.return_value = [] - result = self.sni.perform() - self.assertFalse(result is None) - - def test_perform0(self): - responses = self.sni.perform() - self.assertEqual([], responses) - - @mock.patch("certbot_nginx.configurator.NginxConfigurator.save") - def test_perform1(self, mock_save): - self.sni.add_chall(self.achalls[0]) - response = self.achalls[0].response(self.account_key) - mock_setup_cert = mock.MagicMock(return_value=response) - - # pylint: disable=protected-access - self.sni._setup_challenge_cert = mock_setup_cert - - responses = self.sni.perform() - - mock_setup_cert.assert_called_once_with(self.achalls[0]) - self.assertEqual([response], responses) - self.assertEqual(mock_save.call_count, 1) - - # Make sure challenge config is included in main config - http = self.sni.configurator.parser.parsed[ - self.sni.configurator.parser.config_root][-1] - self.assertTrue( - util.contains_at_depth(http, ['include', self.sni.challenge_conf], 1)) - - def test_perform2(self): - acme_responses = [] - for achall in self.achalls: - self.sni.add_chall(achall) - acme_responses.append(achall.response(self.account_key)) - - mock_setup_cert = mock.MagicMock(side_effect=acme_responses) - # pylint: disable=protected-access - self.sni._setup_challenge_cert = mock_setup_cert - - sni_responses = self.sni.perform() - - self.assertEqual(mock_setup_cert.call_count, 4) - - for index, achall in enumerate(self.achalls): - self.assertEqual( - mock_setup_cert.call_args_list[index], mock.call(achall)) - - http = self.sni.configurator.parser.parsed[ - self.sni.configurator.parser.config_root][-1] - self.assertTrue(['include', self.sni.challenge_conf] in http[1]) - self.assertFalse( - util.contains_at_depth(http, ['server_name', 'another.alias'], 3)) - - self.assertEqual(len(sni_responses), 4) - for i in six.moves.range(4): - self.assertEqual(sni_responses[i], acme_responses[i]) - - def test_mod_config(self): - self.sni.add_chall(self.achalls[0]) - self.sni.add_chall(self.achalls[2]) - - v_addr1 = [obj.Addr("69.50.225.155", "9000", True, False, False, False), - obj.Addr("127.0.0.1", "", False, False, False, False)] - v_addr2 = [obj.Addr("myhost", "", False, True, False, False)] - v_addr2_print = [obj.Addr("myhost", "", False, False, False, False)] - ll_addr = [v_addr1, v_addr2] - self.sni._mod_config(ll_addr) # pylint: disable=protected-access - - self.sni.configurator.save() - - self.sni.configurator.parser.load() - - http = self.sni.configurator.parser.parsed[ - self.sni.configurator.parser.config_root][-1] - self.assertTrue(['include', self.sni.challenge_conf] in http[1]) - - vhosts = self.sni.configurator.parser.get_vhosts() - vhs = [vh for vh in vhosts if vh.filep == self.sni.challenge_conf] - - for vhost in vhs: - if vhost.addrs == set(v_addr1): - response = self.achalls[0].response(self.account_key) - else: - response = self.achalls[2].response(self.account_key) - self.assertEqual(vhost.addrs, set(v_addr2_print)) - self.assertEqual(vhost.names, set([response.z_domain.decode('ascii')])) - - self.assertEqual(len(vhs), 2) - - def test_mod_config_fail(self): - root = self.sni.configurator.parser.config_root - self.sni.configurator.parser.parsed[root] = [['include', 'foo.conf']] - # pylint: disable=protected-access - self.assertRaises( - errors.MisconfigurationError, self.sni._mod_config, []) - -if __name__ == "__main__": - unittest.main() # pragma: no cover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/tests/util.py new/certbot-nginx-0.34.2/certbot_nginx/tests/util.py --- old/certbot-nginx-0.32.0/certbot_nginx/tests/util.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/tests/util.py 2019-05-07 21:17:32.000000000 +0200 @@ -1,21 +1,19 @@ """Common utilities for certbot_nginx.""" import copy -import os -import pkg_resources +import shutil import tempfile import unittest -import shutil import warnings import josepy as jose import mock +import pkg_resources import zope.component from certbot import configuration - -from certbot.tests import util as test_util - +from certbot.compat import os from certbot.plugins import common +from certbot.tests import util as test_util from certbot_nginx import configurator from certbot_nginx import nginxparser @@ -81,8 +79,8 @@ temp_checkpoint_dir=os.path.join(work_dir, "temp_checkpoints"), in_progress_dir=os.path.join(backups, "IN_PROGRESS"), server="https://acme-server.org:443/new", - tls_sni_01_port=5001, - http01_port=80 + http01_port=80, + https_port=5001, ), name="nginx", version=version) @@ -131,8 +129,7 @@ return False if n == 0: return needle in haystack - else: - for item in haystack: - if contains_at_depth(item, needle, n - 1): - return True - return False + for item in haystack: + if contains_at_depth(item, needle, n - 1): + return True + return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx/tls_sni_01.py new/certbot-nginx-0.34.2/certbot_nginx/tls_sni_01.py --- old/certbot-nginx-0.32.0/certbot_nginx/tls_sni_01.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx/tls_sni_01.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,177 +0,0 @@ -"""A class that performs TLS-SNI-01 challenges for Nginx""" - -import logging -import os - -import six - -from certbot import errors -from certbot.plugins import common - -from certbot_nginx import obj -from certbot_nginx import nginxparser - - -logger = logging.getLogger(__name__) - - -class NginxTlsSni01(common.TLSSNI01): - """TLS-SNI-01 authenticator for Nginx - - :ivar configurator: NginxConfigurator object - :type configurator: :class:`~nginx.configurator.NginxConfigurator` - - :ivar list achalls: Annotated - class:`~certbot.achallenges.KeyAuthorizationAnnotatedChallenge` - challenges - - :param list indices: Meant to hold indices of challenges in a - larger array. NginxTlsSni01 is capable of solving many challenges - at once which causes an indexing issue within NginxConfigurator - who must return all responses in order. Imagine NginxConfigurator - maintaining state about where all of the http-01 Challenges, - TLS-SNI-01 Challenges belong in the response array. This is an - optional utility. - - :param str challenge_conf: location of the challenge config file - - """ - - def perform(self): - """Perform a challenge on Nginx. - - :returns: list of :class:`certbot.acme.challenges.TLSSNI01Response` - :rtype: list - - """ - if not self.achalls: - return [] - - addresses = [] - default_addr = "{0} ssl".format( - self.configurator.config.tls_sni_01_port) - - for achall in self.achalls: - vhosts = self.configurator.choose_vhosts(achall.domain, create_if_no_match=True) - - # len is max 1 because Nginx doesn't authenticate wildcards - if vhosts and vhosts[0].addrs: - addresses.append(list(vhosts[0].addrs)) - else: - # choose_vhosts might have modified vhosts, so put this after - ipv6, ipv6only = self.configurator.ipv6_info( - self.configurator.config.tls_sni_01_port) - if ipv6: - # If IPv6 is active in Nginx configuration - ipv6_addr = "[::]:{0} ssl".format( - self.configurator.config.tls_sni_01_port) - if not ipv6only: - # If ipv6only=on is not already present in the config - ipv6_addr = ipv6_addr + " ipv6only=on" - addresses.append([obj.Addr.fromstring(default_addr), - obj.Addr.fromstring(ipv6_addr)]) - logger.info(("Using default addresses %s and %s for " + - "TLSSNI01 authentication."), - default_addr, - ipv6_addr) - else: - addresses.append([obj.Addr.fromstring(default_addr)]) - logger.info("Using default address %s for TLSSNI01 authentication.", - default_addr) - - # Create challenge certs - responses = [self._setup_challenge_cert(x) for x in self.achalls] - - # Set up the configuration - self._mod_config(addresses) - - # Save reversible changes - self.configurator.save("SNI Challenge", True) - - return responses - - def _mod_config(self, ll_addrs): - """Modifies Nginx config to include challenge server blocks. - - :param list ll_addrs: list of lists of - :class:`certbot_nginx.obj.Addr` to apply - - :raises .MisconfigurationError: - Unable to find a suitable HTTP block in which to include - authenticator hosts. - - """ - # Add the 'include' statement for the challenges if it doesn't exist - # already in the main config - included = False - include_directive = ['\n', 'include', ' ', self.challenge_conf] - root = self.configurator.parser.config_root - - bucket_directive = ['\n', 'server_names_hash_bucket_size', ' ', '128'] - - main = self.configurator.parser.parsed[root] - for line in main: - if line[0] == ['http']: - body = line[1] - found_bucket = False - posn = 0 - for inner_line in body: - if inner_line[0] == bucket_directive[1]: - if int(inner_line[1]) < int(bucket_directive[3]): - body[posn] = bucket_directive - found_bucket = True - posn += 1 - if not found_bucket: - body.insert(0, bucket_directive) - if include_directive not in body: - body.insert(0, include_directive) - included = True - break - if not included: - raise errors.MisconfigurationError( - 'Certbot could not find an HTTP block to include ' - 'TLS-SNI-01 challenges in %s.' % root) - config = [self._make_server_block(pair[0], pair[1]) - for pair in six.moves.zip(self.achalls, ll_addrs)] - config = nginxparser.UnspacedList(config) - - self.configurator.reverter.register_file_creation( - True, self.challenge_conf) - - with open(self.challenge_conf, "w") as new_conf: - nginxparser.dump(config, new_conf) - - logger.debug("Generated server block:\n%s", str(config)) - - def _make_server_block(self, achall, addrs): - """Creates a server block for a challenge. - - :param achall: Annotated TLS-SNI-01 challenge - :type achall: - :class:`certbot.achallenges.KeyAuthorizationAnnotatedChallenge` - - :param list addrs: addresses of challenged domain - :class:`list` of type :class:`~nginx.obj.Addr` - - :returns: server block for the challenge host - :rtype: list - - """ - document_root = os.path.join( - self.configurator.config.work_dir, "tls_sni_01_page") - - block = [['listen', ' ', addr.to_string(include_default=False)] for addr in addrs] - - block.extend([['server_name', ' ', - achall.response(achall.account_key).z_domain.decode('ascii')], - # access and error logs necessary for - # integration testing (non-root) - ['access_log', ' ', os.path.join( - self.configurator.config.work_dir, 'access.log')], - ['error_log', ' ', os.path.join( - self.configurator.config.work_dir, 'error.log')], - ['ssl_certificate', ' ', self.get_cert_path(achall)], - ['ssl_certificate_key', ' ', self.get_key_path(achall)], - ['include', ' ', self.configurator.mod_ssl_conf], - [['location', ' ', '/'], [['root', ' ', document_root]]]]) - return [['server'], block] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx.egg-info/PKG-INFO new/certbot-nginx-0.34.2/certbot_nginx.egg-info/PKG-INFO --- old/certbot-nginx-0.32.0/certbot_nginx.egg-info/PKG-INFO 2019-03-06 21:18:24.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx.egg-info/PKG-INFO 2019-05-07 21:17:43.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: certbot-nginx -Version: 0.32.0 +Version: 0.34.2 Summary: Nginx plugin for Certbot Home-page: https://github.com/letsencrypt/letsencrypt Author: Certbot Project diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx.egg-info/SOURCES.txt new/certbot-nginx-0.34.2/certbot_nginx.egg-info/SOURCES.txt --- old/certbot-nginx-0.32.0/certbot_nginx.egg-info/SOURCES.txt 2019-03-06 21:18:24.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx.egg-info/SOURCES.txt 2019-05-07 21:17:43.000000000 +0200 @@ -13,7 +13,6 @@ certbot_nginx/options-ssl-nginx.conf certbot_nginx/parser.py certbot_nginx/parser_obj.py -certbot_nginx/tls_sni_01.py certbot_nginx.egg-info/PKG-INFO certbot_nginx.egg-info/SOURCES.txt certbot_nginx.egg-info/dependency_links.txt @@ -28,7 +27,6 @@ certbot_nginx/tests/obj_test.py certbot_nginx/tests/parser_obj_test.py certbot_nginx/tests/parser_test.py -certbot_nginx/tests/tls_sni_01_test.py certbot_nginx/tests/util.py certbot_nginx/tests/testdata/etc_nginx/broken.conf certbot_nginx/tests/testdata/etc_nginx/comment_in_file.conf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/certbot_nginx.egg-info/requires.txt new/certbot-nginx-0.34.2/certbot_nginx.egg-info/requires.txt --- old/certbot-nginx-0.32.0/certbot_nginx.egg-info/requires.txt 2019-03-06 21:18:24.000000000 +0100 +++ new/certbot-nginx-0.34.2/certbot_nginx.egg-info/requires.txt 2019-05-07 21:17:43.000000000 +0200 @@ -1,5 +1,5 @@ -acme>=0.26.0 -certbot>=0.22.0 +acme>=0.29.0 +certbot>=0.34.0 mock PyOpenSSL pyparsing>=1.5.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/docs/conf.py new/certbot-nginx-0.34.2/docs/conf.py --- old/certbot-nginx-0.32.0/docs/conf.py 2019-03-06 21:18:08.000000000 +0100 +++ new/certbot-nginx-0.34.2/docs/conf.py 2019-05-07 21:17:32.000000000 +0200 @@ -13,7 +13,7 @@ # serve to show the default. import sys -import os +from certbot.compat import os import shlex diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-0.32.0/setup.py new/certbot-nginx-0.34.2/setup.py --- old/certbot-nginx-0.32.0/setup.py 2019-03-06 21:18:09.000000000 +0100 +++ new/certbot-nginx-0.34.2/setup.py 2019-05-07 21:17:33.000000000 +0200 @@ -4,13 +4,13 @@ import sys -version = '0.32.0' +version = '0.34.2' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ - 'acme>=0.26.0', - 'certbot>=0.22.0', + 'acme>=0.29.0', + 'certbot>=0.34.0', 'mock', 'PyOpenSSL', 'pyparsing>=1.5.5', # Python3 support; perhaps unnecessary?