mirror of
https://github.com/certbot/certbot.git
synced 2026-06-03 13:59:02 -04:00
Merge pull request #205 from letsencrypt/gen_dvsni_chall
gen_dvsni_chall remove filepath
This commit is contained in:
commit
5a46a1e32e
4 changed files with 83 additions and 66 deletions
|
|
@ -87,11 +87,7 @@ class ApacheDvsni(object):
|
|||
|
||||
# Create all of the challenge certs
|
||||
for chall in self.dvsni_chall:
|
||||
cert_path = self.get_cert_file(chall.nonce)
|
||||
self.config.reverter.register_file_creation(True, cert_path)
|
||||
s_b64 = challenge_util.dvsni_gen_cert(
|
||||
cert_path, chall.domain, chall.r_b64, chall.nonce, chall.key)
|
||||
|
||||
s_b64 = self._setup_challenge_cert(chall)
|
||||
responses.append({"type": "dvsni", "s": s_b64})
|
||||
|
||||
# Setup the configuration
|
||||
|
|
@ -102,6 +98,21 @@ class ApacheDvsni(object):
|
|||
|
||||
return responses
|
||||
|
||||
def _setup_challenge_cert(self, chall):
|
||||
"""Generate and write out challenge certificate."""
|
||||
cert_path = self.get_cert_file(chall.nonce)
|
||||
# Register the path before you write out the file
|
||||
self.config.reverter.register_file_creation(True, cert_path)
|
||||
|
||||
cert_pem, s_b64 = challenge_util.dvsni_gen_cert(
|
||||
chall.domain, chall.r_b64, chall.nonce, chall.key)
|
||||
|
||||
# Write out challenge cert
|
||||
with open(cert_path, 'w') as cert_chall_fd:
|
||||
cert_chall_fd.write(cert_pem)
|
||||
|
||||
return s_b64
|
||||
|
||||
def _mod_config(self, ll_addrs):
|
||||
"""Modifies Apache config files to include challenge vhosts.
|
||||
|
||||
|
|
|
|||
|
|
@ -27,11 +27,9 @@ IndexedChall = collections.namedtuple("IndexedChall", "chall, index")
|
|||
|
||||
|
||||
# DVSNI Challenge functions
|
||||
def dvsni_gen_cert(filepath, name, r_b64, nonce, key):
|
||||
def dvsni_gen_cert(name, r_b64, nonce, key):
|
||||
"""Generate a DVSNI cert and save it to filepath.
|
||||
|
||||
:param str filepath: destination to save certificate. This will overwrite
|
||||
any file that is currently at the location.
|
||||
:param str name: domain to validate
|
||||
:param str r_b64: jose base64 encoded dvsni r value
|
||||
:param str nonce: hex value of nonce
|
||||
|
|
@ -39,8 +37,10 @@ def dvsni_gen_cert(filepath, name, r_b64, nonce, key):
|
|||
:param key: Key to perform challenge
|
||||
:type key: :class:`letsencrypt.client.client.Client.Key`
|
||||
|
||||
:returns: dvsni s value jose base64 encoded
|
||||
:rtype: str
|
||||
:returns: tuple of (cert_pem, s) where
|
||||
cert_pem is the certificate in pem form
|
||||
s is the dvsni s value, jose base64 encoded
|
||||
:rtype: tuple
|
||||
|
||||
"""
|
||||
# Generate S
|
||||
|
|
@ -53,10 +53,7 @@ def dvsni_gen_cert(filepath, name, r_b64, nonce, key):
|
|||
cert_pem = crypto_util.make_ss_cert(
|
||||
key.pem, [nonce + CONFIG.INVALID_EXT, name, ext])
|
||||
|
||||
with open(filepath, 'w') as chall_cert_file:
|
||||
chall_cert_file.write(cert_pem)
|
||||
|
||||
return le_util.jose_b64encode(dvsni_s)
|
||||
return cert_pem, le_util.jose_b64encode(dvsni_s)
|
||||
|
||||
|
||||
def _dvsni_gen_ext(dvsni_r, dvsni_s):
|
||||
|
|
|
|||
|
|
@ -56,23 +56,49 @@ class DvsniPerformTest(util.ApacheTest):
|
|||
self.assertTrue(resp is None)
|
||||
|
||||
@mock.patch("letsencrypt.client.challenge_util.dvsni_gen_cert")
|
||||
def test_perform1(self, mock_dvsni_gen_cert):
|
||||
def test_setup_challenge_cert(self, mock_dvsni_gen_cert):
|
||||
# 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
|
||||
chall = self.challs[0]
|
||||
self.sni.add_chall(chall)
|
||||
mock_dvsni_gen_cert.return_value = "randomS1"
|
||||
responses = self.sni.perform()
|
||||
m_open = mock.mock_open()
|
||||
mock_dvsni_gen_cert.return_value = ("pem", "randomS1")
|
||||
|
||||
with mock.patch("letsencrypt.client.apache.dvsni.open",
|
||||
m_open, create=True):
|
||||
# pylint: disable=protected-access
|
||||
s_b64 = self.sni._setup_challenge_cert(chall)
|
||||
|
||||
self.assertEqual(s_b64, "randomS1")
|
||||
|
||||
self.assertTrue(m_open.called)
|
||||
self.assertEqual(
|
||||
m_open.call_args[0], (self.sni.get_cert_file(chall.nonce), 'w'))
|
||||
self.assertEqual(m_open().write.call_args[0][0], "pem")
|
||||
|
||||
self.assertEqual(mock_dvsni_gen_cert.call_count, 1)
|
||||
calls = mock_dvsni_gen_cert.call_args_list
|
||||
expected_call_list = [
|
||||
(self.sni.get_cert_file(chall.nonce), chall.domain,
|
||||
chall.r_b64, chall.nonce, chall.key)
|
||||
(chall.domain, chall.r_b64, chall.nonce, chall.key)
|
||||
]
|
||||
|
||||
for i in range(len(expected_call_list)):
|
||||
for j in range(len(expected_call_list[0])):
|
||||
for i in xrange(len(expected_call_list)):
|
||||
for j in xrange(len(expected_call_list[0])):
|
||||
self.assertEqual(calls[i][0][j], expected_call_list[i][j])
|
||||
|
||||
def test_perform1(self):
|
||||
chall = self.challs[0]
|
||||
self.sni.add_chall(chall)
|
||||
mock_setup_cert = mock.MagicMock(return_value="randomS1")
|
||||
# pylint: disable=protected-access
|
||||
self.sni._setup_challenge_cert = mock_setup_cert
|
||||
|
||||
responses = self.sni.perform()
|
||||
|
||||
mock_setup_cert.assert_called_once_with(chall)
|
||||
|
||||
# Check to make sure challenge config path is included in apache config.
|
||||
self.assertEqual(
|
||||
len(self.sni.config.parser.find_dir(
|
||||
"Include", self.sni.challenge_conf)),
|
||||
|
|
@ -80,33 +106,30 @@ class DvsniPerformTest(util.ApacheTest):
|
|||
self.assertEqual(len(responses), 1)
|
||||
self.assertEqual(responses[0]["s"], "randomS1")
|
||||
|
||||
@mock.patch("letsencrypt.client.challenge_util.dvsni_gen_cert")
|
||||
def test_perform2(self, mock_dvsni_gen_cert):
|
||||
def test_perform2(self):
|
||||
for chall in self.challs:
|
||||
self.sni.add_chall(chall)
|
||||
|
||||
mock_dvsni_gen_cert.side_effect = ["randomS0", "randomS1"]
|
||||
mock_setup_cert = mock.MagicMock(side_effect=["randomS0", "randomS1"])
|
||||
# pylint: disable=protected-access
|
||||
self.sni._setup_challenge_cert = mock_setup_cert
|
||||
|
||||
responses = self.sni.perform()
|
||||
|
||||
self.assertEqual(mock_dvsni_gen_cert.call_count, 2)
|
||||
calls = mock_dvsni_gen_cert.call_args_list
|
||||
expected_call_list = []
|
||||
self.assertEqual(mock_setup_cert.call_count, 2)
|
||||
|
||||
for chall in self.challs:
|
||||
expected_call_list.append(
|
||||
(self.sni.get_cert_file(chall.nonce), chall.domain,
|
||||
chall.r_b64, chall.nonce, chall.key))
|
||||
|
||||
for i in range(len(expected_call_list)):
|
||||
for j in range(len(expected_call_list[0])):
|
||||
self.assertEqual(calls[i][0][j], expected_call_list[i][j])
|
||||
# Make sure calls made to mocked function were correct
|
||||
self.assertEqual(
|
||||
mock_setup_cert.call_args_list[0], mock.call(self.challs[0]))
|
||||
self.assertEqual(
|
||||
mock_setup_cert.call_args_list[1], mock.call(self.challs[1]))
|
||||
|
||||
self.assertEqual(
|
||||
len(self.sni.config.parser.find_dir(
|
||||
"Include", self.sni.challenge_conf)),
|
||||
1)
|
||||
self.assertEqual(len(responses), 2)
|
||||
for i in range(2):
|
||||
for i in xrange(2):
|
||||
self.assertEqual(responses[i]["s"], "randomS%d" % i)
|
||||
|
||||
def test_mod_config(self):
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import re
|
|||
import unittest
|
||||
|
||||
import M2Crypto
|
||||
import mock
|
||||
|
||||
from letsencrypt.client import challenge_util
|
||||
from letsencrypt.client import client
|
||||
|
|
@ -19,32 +18,19 @@ class DvsniGenCertTest(unittest.TestCase):
|
|||
|
||||
def test_standard(self):
|
||||
"""Basic test for straightline code."""
|
||||
# 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
|
||||
m_open = mock.mock_open()
|
||||
with mock.patch("letsencrypt.client.challenge_util.open",
|
||||
m_open, create=True):
|
||||
domain = "example.com"
|
||||
dvsni_r = "r_value"
|
||||
r_b64 = le_util.jose_b64encode(dvsni_r)
|
||||
pem = pkg_resources.resource_string(
|
||||
__name__, os.path.join("testdata", "rsa256_key.pem"))
|
||||
key = client.Client.Key("path", pem)
|
||||
nonce = "12345ABCDE"
|
||||
cert_pem, s_b64 = self._call(domain, r_b64, nonce, key)
|
||||
|
||||
domain = "example.com"
|
||||
dvsni_r = "r_value"
|
||||
r_b64 = le_util.jose_b64encode(dvsni_r)
|
||||
pem = pkg_resources.resource_string(
|
||||
__name__, os.path.join("testdata", "rsa256_key.pem"))
|
||||
key = client.Client.Key("path", pem)
|
||||
nonce = "12345ABCDE"
|
||||
s_b64 = self._call("tmp.crt", domain, r_b64, nonce, key)
|
||||
|
||||
self.assertTrue(m_open.called)
|
||||
self.assertEqual(m_open.call_args[0], ("tmp.crt", 'w'))
|
||||
self.assertEqual(m_open().write.call_count, 1)
|
||||
|
||||
# pylint: disable=protected-access
|
||||
ext = challenge_util._dvsni_gen_ext(
|
||||
dvsni_r, le_util.jose_b64decode(s_b64))
|
||||
self._standard_check_cert(
|
||||
m_open().write.call_args[0][0], domain, nonce, ext)
|
||||
# pylint: disable=protected-access
|
||||
ext = challenge_util._dvsni_gen_ext(
|
||||
dvsni_r, le_util.jose_b64decode(s_b64))
|
||||
self._standard_check_cert(cert_pem, domain, nonce, ext)
|
||||
|
||||
def _standard_check_cert(self, pem, domain, nonce, ext):
|
||||
"""Check the certificate fields."""
|
||||
|
|
@ -60,7 +46,7 @@ class DvsniGenCertTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual(exp_sans, act_sans)
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
def _call(self, filepath, name, r_b64, nonce, key):
|
||||
@classmethod
|
||||
def _call(cls, name, r_b64, nonce, key):
|
||||
from letsencrypt.client.challenge_util import dvsni_gen_cert
|
||||
return dvsni_gen_cert(filepath, name, r_b64, nonce, key)
|
||||
return dvsni_gen_cert(name, r_b64, nonce, key)
|
||||
|
|
|
|||
Loading…
Reference in a new issue