1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-21 19:01:07 +03:00

Fix test cases; along the way, have --csr save fullchain.pem

This commit is contained in:
Peter Eckersley
2015-10-21 21:00:30 -07:00
parent c2db967a93
commit ccfeeb9fe5
4 changed files with 53 additions and 28 deletions

View File

@@ -267,21 +267,29 @@ def _treat_as_renewal(config, domains):
return None
def _report_new_cert(lineage):
def _report_new_cert(cert_path, fullchain_path):
"""
Reports the creation of a new certificate to the user.
:param RenewableCert lineage: the lineage of the new cert
:param string cert_path: path to cert
:param string fullchain_path: path to full chain
"""
expiry = crypto_util.notAfter(lineage.cert).date()
expiry = crypto_util.notAfter(cert_path).date()
reporter_util = zope.component.getUtility(interfaces.IReporter)
# Tell the user about fullchain.pem because that's what modern webservers
# (Nginx and Apache2.4) will want.
if fullchain_path:
# Print the path to fullchain.pem because that's what modern webservers
# (Nginx and Apache2.4) will want.
and_chain = "and chain have"
path = fullchain_path
else:
# Unless we're in .csr mode and there really isn't one
and_chain = "has "
path = cert_path
# XXX Perhaps one day we could detect the presence of known old webservers
# and say something more informative here.
msg = ("Congratulations! Your certificate and chain have been saved at {0}."
" Your cert will expire on {1}. To obtain a new version of the "
msg = ("Congratulations! Your certificate {0} been saved at {1}."
" Your cert will expire on {2}. To obtain a new version of the "
"certificate in the future, simply run Let's Encrypt again."
.format(lineage.fullchain, expiry))
.format(and_chain, path, expiry))
reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
@@ -310,7 +318,7 @@ def _auth_from_domains(le_client, config, domains, plugins):
if not lineage:
raise Error("Certificate could not be obtained")
_report_new_cert(lineage)
_report_new_cert(lineage.cert, lineage.fullchain)
return lineage
@@ -461,9 +469,9 @@ def auth(args, config, plugins):
if args.csr is not None:
certr, chain = le_client.obtain_certificate_from_csr(le_util.CSR(
file=args.csr[0], data=args.csr[1], form="der"))
cert_path, _ = le_client.save_certificate(
certr, chain, args.cert_path, args.chain_path)
_report_new_cert(cert_path)
cert_path, _, cert_fullchain = le_client.save_certificate(
certr, chain, args.cert_path, args.chain_path, args.fullchain_path)
_report_new_cert(cert_path, cert_fullchain)
else:
domains = _find_domains(args, installer)
_auth_from_domains(le_client, config, domains, plugins)

View File

@@ -258,7 +258,7 @@ class Client(object):
params, config, cli_config)
return lineage
def save_certificate(self, certr, chain_cert, cert_path, chain_path):
def save_certificate(self, certr, chain_cert, cert_path, chain_path, fullchain_path):
# pylint: disable=no-self-use
"""Saves the certificate received from the ACME server.
@@ -268,20 +268,22 @@ class Client(object):
:param list chain_cert:
:param str cert_path: Candidate path to a certificate.
:param str chain_path: Candidate path to a certificate chain.
:param str fullchain_path: Candidate path to a full cert chain.
:returns: cert_path, chain_path (absolute paths to the actual files)
:returns: cert_path, chain_path, fullchain_path (absolute paths to the actual files)
:rtype: `tuple` of `str`
:raises IOError: If unable to find room to write the cert files
"""
for path in cert_path, chain_path:
for path in cert_path, chain_path, fullchain_path:
le_util.make_or_verify_dir(
os.path.dirname(path), 0o755, os.geteuid(),
self.config.strict_permissions)
# try finally close
cert_chain_abspath = None
fullchain_abspath = None
cert_file, act_cert_path = le_util.unique_file(cert_path, 0o644)
# TODO: Except
cert_pem = OpenSSL.crypto.dump_certificate(
@@ -294,8 +296,7 @@ class Client(object):
act_cert_path)
if chain_cert:
chain_file, act_chain_path = le_util.unique_file(
chain_path, 0o644)
chain_file, act_chain_path = le_util.unique_file(chain_path, 0o644)
# TODO: Except
chain_pem = crypto_util.dump_pyopenssl_chain(chain_cert)
try:
@@ -308,7 +309,17 @@ class Client(object):
# This expects a valid chain file
cert_chain_abspath = os.path.abspath(act_chain_path)
return os.path.abspath(act_cert_path), cert_chain_abspath
# fullchain is cert + chain
fullchain_file, act_fullchain_path = le_util.unique_file(
fullchain_path, 0o644)
try:
fullchain_file.write(cert_pem + chain_pem)
finally:
fullchain_file.close()
logger.info("Cert chain written to %s", act_fullchain_path)
fullchain_abspath = os.path.abspath(act_fullchain_path)
return os.path.abspath(act_cert_path), cert_chain_abspath, fullchain_abspath
def deploy_certificate(self, domains, privkey_path,
cert_path, chain_path, fullchain_path):

View File

@@ -149,7 +149,7 @@ class CLITest(unittest.TestCase):
date = '1970-01-01'
mock_notAfter().date.return_value = date
mock_lineage = mock.MagicMock(cert=cert_path)
mock_lineage = mock.MagicMock(cert=cert_path, fullchain=cert_path)
mock_client = mock.MagicMock()
mock_client.obtain_and_enroll_certificate.return_value = mock_lineage
self._auth_new_request_common(mock_client)
@@ -177,9 +177,10 @@ class CLITest(unittest.TestCase):
@mock.patch('letsencrypt.cli._treat_as_renewal')
@mock.patch('letsencrypt.cli._init_le_client')
def test_auth_renewal(self, mock_init, mock_renewal, mock_get_utility):
cert_path = '/etc/letsencrypt/live/foo.bar'
cert_path = '/etc/letsencrypt/live/foo.bar/cert.pem'
chain_path = '/etc/letsencrypt/live/foo.bar/fullchain.pem'
mock_lineage = mock.MagicMock(cert=cert_path)
mock_lineage = mock.MagicMock(cert=cert_path,fullchain=chain_path)
mock_cert = mock.MagicMock(body='body')
mock_key = mock.MagicMock(pem='pem_key')
mock_renewal.return_value = mock_lineage
@@ -195,7 +196,7 @@ class CLITest(unittest.TestCase):
mock_lineage.update_all_links_to.assert_called_once_with(
mock_lineage.latest_common_version())
self.assertTrue(
cert_path in mock_get_utility().add_message.call_args[0][0])
chain_path in mock_get_utility().add_message.call_args[0][0])
@mock.patch('letsencrypt.crypto_util.notAfter')
@mock.patch('letsencrypt.cli.display_ops.pick_installer')
@@ -203,23 +204,24 @@ class CLITest(unittest.TestCase):
@mock.patch('letsencrypt.cli._init_le_client')
def test_auth_csr(self, mock_init, mock_get_utility,
mock_pick_installer, mock_notAfter):
cert_path = '/etc/letsencrypt/live/foo.bar'
cert_path = '/etc/letsencrypt/live/blahcert.pem'
date = '1970-01-01'
mock_notAfter().date.return_value = date
mock_client = mock.MagicMock()
mock_client.obtain_certificate_from_csr.return_value = ('certr',
'chain')
mock_client.save_certificate.return_value = cert_path, None
mock_client.save_certificate.return_value = cert_path, None, None
mock_init.return_value = mock_client
installer = 'installer'
self._call(
['-a', 'standalone', '-i', installer, 'auth', '--csr', CSR,
'--cert-path', cert_path, '--chain-path', '/'])
'--cert-path', cert_path, '--fullchain-path', '/',
'--chain-path', '/'])
self.assertEqual(mock_pick_installer.call_args[0][1], installer)
mock_client.save_certificate.assert_called_once_with(
'certr', 'chain', cert_path, '/')
'certr', 'chain', cert_path, '/', '/')
self.assertTrue(
cert_path in mock_get_utility().add_message.call_args[0][0])
self.assertTrue(

View File

@@ -124,14 +124,18 @@ class ClientTest(unittest.TestCase):
cert2 = test_util.load_cert(certs[2])
candidate_cert_path = os.path.join(tmp_path, "certs", "cert.pem")
candidate_chain_path = os.path.join(tmp_path, "chains", "chain.pem")
candidate_fullchain_path = os.path.join(tmp_path, "chains", "fullchain.pem")
cert_path, chain_path = self.client.save_certificate(
certr, [cert1, cert2], candidate_cert_path, candidate_chain_path)
cert_path, chain_path, fullchain_path = self.client.save_certificate(
certr, [cert1, cert2], candidate_cert_path, candidate_chain_path,
candidate_fullchain_path)
self.assertEqual(os.path.dirname(cert_path),
os.path.dirname(candidate_cert_path))
self.assertEqual(os.path.dirname(chain_path),
os.path.dirname(candidate_chain_path))
self.assertEqual(os.path.dirname(fullchain_path),
os.path.dirname(candidate_fullchain_path))
with open(cert_path, "r") as cert_file:
cert_contents = cert_file.read()