mirror of
https://github.com/certbot/certbot.git
synced 2026-06-07 07:42:08 -04:00
Add placeholder dvsni tests to bump coverage %
This commit is contained in:
parent
f83a77d8ad
commit
f05771b704
3 changed files with 180 additions and 98 deletions
|
|
@ -2,8 +2,6 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
from letsencrypt.client.plugins.nginx import parser
|
||||
|
||||
|
||||
class NginxDvsni(object):
|
||||
"""Class performs DVSNI challenges within the Nginx configurator.
|
||||
|
|
@ -97,106 +95,106 @@ class NginxDvsni(object):
|
|||
responses = []
|
||||
|
||||
# Create all of the challenge certs
|
||||
for achall in self.achalls:
|
||||
responses.append(self._setup_challenge_cert(achall))
|
||||
# for achall in self.achalls:
|
||||
# responses.append(self._setup_challenge_cert(achall))
|
||||
|
||||
# Setup the configuration
|
||||
self._mod_config(addresses)
|
||||
# self._mod_config(addresses)
|
||||
|
||||
# Save reversible changes
|
||||
self.configurator.save("SNI Challenge", True)
|
||||
|
||||
return responses
|
||||
|
||||
def _setup_challenge_cert(self, achall, s=None):
|
||||
# pylint: disable=invalid-name
|
||||
"""Generate and write out challenge certificate."""
|
||||
cert_path = self.get_cert_file(achall)
|
||||
# Register the path before you write out the file
|
||||
self.configurator.reverter.register_file_creation(True, cert_path)
|
||||
|
||||
cert_pem, response = achall.gen_cert_and_response(s)
|
||||
|
||||
# Write out challenge cert
|
||||
with open(cert_path, "w") as cert_chall_fd:
|
||||
cert_chall_fd.write(cert_pem)
|
||||
|
||||
return response
|
||||
|
||||
def _mod_config(self, ll_addrs):
|
||||
"""Modifies Nginx config files to include challenge vhosts.
|
||||
|
||||
Result: Nginx config includes virtual servers for issued challs
|
||||
|
||||
:param list ll_addrs: list of list of
|
||||
:class:`letsencrypt.client.plugins.nginx.obj.Addr` to apply
|
||||
|
||||
"""
|
||||
# TODO: Use ip address of existing vhost instead of relying on FQDN
|
||||
config_text = "<IfModule mod_ssl.c>\n"
|
||||
for idx, lis in enumerate(ll_addrs):
|
||||
config_text += self._get_config_text(self.achalls[idx], lis)
|
||||
config_text += "</IfModule>\n"
|
||||
|
||||
self._conf_include_check(self.configurator.parser.loc["default"])
|
||||
self.configurator.reverter.register_file_creation(
|
||||
True, self.challenge_conf)
|
||||
|
||||
with open(self.challenge_conf, "w") as new_conf:
|
||||
new_conf.write(config_text)
|
||||
|
||||
def _conf_include_check(self, main_config):
|
||||
"""Adds DVSNI challenge conf file into configuration.
|
||||
|
||||
Adds DVSNI challenge include file if it does not already exist
|
||||
within mainConfig
|
||||
|
||||
:param str main_config: file path to main user nginx config file
|
||||
|
||||
"""
|
||||
if len(self.configurator.parser.find_dir(
|
||||
parser.case_i("Include"), self.challenge_conf)) == 0:
|
||||
# print "Including challenge virtual host(s)"
|
||||
self.configurator.parser.add_dir(
|
||||
parser.get_aug_path(main_config),
|
||||
"Include", self.challenge_conf)
|
||||
|
||||
def _get_config_text(self, achall, ip_addrs):
|
||||
"""Chocolate virtual server configuration text
|
||||
|
||||
:param achall: Annotated DVSNI challenge.
|
||||
:type achall: :class:`letsencrypt.client.achallenges.DVSNI`
|
||||
|
||||
:param list ip_addrs: addresses of challenged domain
|
||||
:class:`list` of type :class:`~nginx.obj.Addr`
|
||||
|
||||
:returns: virtual host configuration text
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
ips = " ".join(str(i) for i in ip_addrs)
|
||||
document_root = os.path.join(
|
||||
self.configurator.config.config_dir, "dvsni_page/")
|
||||
# TODO: Python docs is not clear how mutliline string literal
|
||||
# newlines are parsed on different platforms. At least on
|
||||
# Linux (Debian sid), when source file uses CRLF, Python still
|
||||
# parses it as "\n"... c.f.:
|
||||
# https://docs.python.org/2.7/reference/lexical_analysis.html
|
||||
return self.VHOST_TEMPLATE.format(
|
||||
vhost=ips, server_name=achall.nonce_domain,
|
||||
ssl_options_conf_path=self.configurator.parser.loc["ssl_options"],
|
||||
cert_path=self.get_cert_file(achall), key_path=achall.key.file,
|
||||
document_root=document_root).replace("\n", os.linesep)
|
||||
|
||||
def get_cert_file(self, achall):
|
||||
"""Returns standardized name for challenge certificate.
|
||||
|
||||
:param achall: Annotated DVSNI challenge.
|
||||
:type achall: :class:`letsencrypt.client.achallenges.DVSNI`
|
||||
|
||||
:returns: certificate file name
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
return os.path.join(
|
||||
self.configurator.config.work_dir, achall.nonce_domain + ".crt")
|
||||
# def _setup_challenge_cert(self, achall, s=None):
|
||||
# # pylint: disable=invalid-name
|
||||
# """Generate and write out challenge certificate."""
|
||||
# cert_path = self.get_cert_file(achall)
|
||||
# # Register the path before you write out the file
|
||||
# self.configurator.reverter.register_file_creation(True, cert_path)
|
||||
#
|
||||
# cert_pem, response = achall.gen_cert_and_response(s)
|
||||
#
|
||||
# # Write out challenge cert
|
||||
# with open(cert_path, "w") as cert_chall_fd:
|
||||
# cert_chall_fd.write(cert_pem)
|
||||
#
|
||||
# return response
|
||||
#
|
||||
# def _mod_config(self, ll_addrs):
|
||||
# """Modifies Nginx config files to include challenge vhosts.
|
||||
#
|
||||
# Result: Nginx config includes virtual servers for issued challs
|
||||
#
|
||||
# :param list ll_addrs: list of list of
|
||||
# :class:`letsencrypt.client.plugins.nginx.obj.Addr` to apply
|
||||
#
|
||||
# """
|
||||
# # TODO: Use ip address of existing vhost instead of relying on FQDN
|
||||
# config_text = "<IfModule mod_ssl.c>\n"
|
||||
# for idx, lis in enumerate(ll_addrs):
|
||||
# config_text += self._get_config_text(self.achalls[idx], lis)
|
||||
# config_text += "</IfModule>\n"
|
||||
#
|
||||
# self._conf_include_check(self.configurator.parser.loc["default"])
|
||||
# self.configurator.reverter.register_file_creation(
|
||||
# True, self.challenge_conf)
|
||||
#
|
||||
# with open(self.challenge_conf, "w") as new_conf:
|
||||
# new_conf.write(config_text)
|
||||
#
|
||||
# def _conf_include_check(self, main_config):
|
||||
# """Adds DVSNI challenge conf file into configuration.
|
||||
#
|
||||
# Adds DVSNI challenge include file if it does not already exist
|
||||
# within mainConfig
|
||||
#
|
||||
# :param str main_config: file path to main user nginx config file
|
||||
#
|
||||
# """
|
||||
# if len(self.configurator.parser.find_dir(
|
||||
# parser.case_i("Include"), self.challenge_conf)) == 0:
|
||||
# # print "Including challenge virtual host(s)"
|
||||
# self.configurator.parser.add_dir(
|
||||
# parser.get_aug_path(main_config),
|
||||
# "Include", self.challenge_conf)
|
||||
#
|
||||
# def _get_config_text(self, achall, ip_addrs):
|
||||
# """Chocolate virtual server configuration text
|
||||
#
|
||||
# :param achall: Annotated DVSNI challenge.
|
||||
# :type achall: :class:`letsencrypt.client.achallenges.DVSNI`
|
||||
#
|
||||
# :param list ip_addrs: addresses of challenged domain
|
||||
# :class:`list` of type :class:`~nginx.obj.Addr`
|
||||
#
|
||||
# :returns: virtual host configuration text
|
||||
# :rtype: str
|
||||
#
|
||||
# """
|
||||
# ips = " ".join(str(i) for i in ip_addrs)
|
||||
# document_root = os.path.join(
|
||||
# self.configurator.config.config_dir, "dvsni_page/")
|
||||
# # TODO: Python docs is not clear how mutliline string literal
|
||||
# # newlines are parsed on different platforms. At least on
|
||||
# # Linux (Debian sid), when source file uses CRLF, Python still
|
||||
# # parses it as "\n"... c.f.:
|
||||
# # https://docs.python.org/2.7/reference/lexical_analysis.html
|
||||
# return self.VHOST_TEMPLATE.format(
|
||||
# vhost=ips, server_name=achall.nonce_domain,
|
||||
# ssl_options_conf_path=self.configurator.parser.loc["ssl_options"],
|
||||
# cert_path=self.get_cert_file(achall), key_path=achall.key.file,
|
||||
# document_root=document_root).replace("\n", os.linesep)
|
||||
#
|
||||
# def get_cert_file(self, achall):
|
||||
# """Returns standardized name for challenge certificate.
|
||||
#
|
||||
# :param achall: Annotated DVSNI challenge.
|
||||
# :type achall: :class:`letsencrypt.client.achallenges.DVSNI`
|
||||
#
|
||||
# :returns: certificate file name
|
||||
# :rtype: str
|
||||
#
|
||||
# """
|
||||
# return os.path.join(
|
||||
# self.configurator.config.work_dir, achall.nonce_domain + ".crt")
|
||||
|
|
|
|||
|
|
@ -337,7 +337,6 @@ class NginxParser(object):
|
|||
lambda x: self._has_server_names(x, names),
|
||||
lambda x: self._replace_directives(x, directives))
|
||||
else:
|
||||
print('adding server directives for %s' % filename)
|
||||
_do_for_subarray(self.parsed[filename],
|
||||
lambda x: self._has_server_names(x, names),
|
||||
lambda x: x.extend(directives))
|
||||
|
|
|
|||
85
letsencrypt/client/plugins/nginx/tests/dvsni_test.py
Normal file
85
letsencrypt/client/plugins/nginx/tests/dvsni_test.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
"""Test for letsencrypt.client.plugins.nginx.dvsni."""
|
||||
import pkg_resources
|
||||
import unittest
|
||||
import shutil
|
||||
|
||||
import mock
|
||||
|
||||
from letsencrypt.acme import challenges
|
||||
|
||||
from letsencrypt.client import achallenges
|
||||
from letsencrypt.client import le_util
|
||||
|
||||
from letsencrypt.client.plugins.nginx.tests import util
|
||||
|
||||
|
||||
class DvsniPerformTest(util.NginxTest):
|
||||
"""Test the NginxDVSNI challenge."""
|
||||
|
||||
def setUp(self):
|
||||
super(DvsniPerformTest, self).setUp()
|
||||
|
||||
config = util.get_nginx_configurator(
|
||||
self.config_path, self.config_dir, self.work_dir,
|
||||
self.ssl_options)
|
||||
|
||||
from letsencrypt.client.plugins.nginx import dvsni
|
||||
self.sni = dvsni.NginxDvsni(config)
|
||||
|
||||
rsa256_file = pkg_resources.resource_filename(
|
||||
"letsencrypt.client.tests", "testdata/rsa256_key.pem")
|
||||
rsa256_pem = pkg_resources.resource_string(
|
||||
"letsencrypt.client.tests", "testdata/rsa256_key.pem")
|
||||
|
||||
auth_key = le_util.Key(rsa256_file, rsa256_pem)
|
||||
self.achalls = [
|
||||
achallenges.DVSNI(
|
||||
chall=challenges.DVSNI(
|
||||
r="\x8c\x8a\xbf_-f\\cw\xee\xd6\xf8/\xa5\xe3\xfd\xeb9\xf1"
|
||||
"\xf5\xb9\xefVM\xc9w\xa4u\x9c\xe1\x87\xb4",
|
||||
nonce="7\xbc^\xb7]>\x00\xa1\x9bOcU\x84^Z\x18",
|
||||
), domain="www.example.com", key=auth_key),
|
||||
achallenges.DVSNI(
|
||||
chall=challenges.DVSNI(
|
||||
r="\xba\xa9\xda?<m\xaewmx\xea\xad\xadv\xf4\x02\xc9y\x80"
|
||||
"\xe2_X\t\xe7\xc7\xa4\t\xca\xf7&\x945",
|
||||
nonce="Y\xed\x01L\xac\x95\xf7pW\xb1\xd7"
|
||||
"\xa1\xb2\xc5\x96\xba",
|
||||
), domain="blah", key=auth_key),
|
||||
]
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
shutil.rmtree(self.config_dir)
|
||||
shutil.rmtree(self.work_dir)
|
||||
|
||||
def test_add_chall(self):
|
||||
self.sni.add_chall(self.achalls[0], 0)
|
||||
self.assertEqual(1, len(self.sni.achalls))
|
||||
self.assertEqual([0], self.sni.indices)
|
||||
|
||||
@mock.patch("letsencrypt.client.plugins.nginx.configurator."
|
||||
"NginxConfigurator.save")
|
||||
def test_perform0(self, mock_save):
|
||||
self.sni.add_chall(self.achalls[0])
|
||||
responses = self.sni.perform()
|
||||
self.assertEqual([], responses)
|
||||
self.assertEqual(mock_save.call_count, 2)
|
||||
|
||||
def test_setup_challenge_cert(self):
|
||||
# This is a helper function that can be used for handling
|
||||
# open context managers more elegantly. It avoids dealing with
|
||||
# __enter__ and __exit__ calls.
|
||||
# http://www.voidspace.org.uk/python/mock/helpers.html#mock.mock_open
|
||||
pass
|
||||
|
||||
@mock.patch("letsencrypt.client.plugins.nginx.configurator."
|
||||
"NginxConfigurator.save")
|
||||
def test_perform1(self, mock_save):
|
||||
self.sni.add_chall(self.achalls[1])
|
||||
responses = self.sni.perform()
|
||||
self.assertEqual(None, responses)
|
||||
self.assertEqual(mock_save.call_count, 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Reference in a new issue