mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 19:02:52 +02:00
Fix test cases; along the way, have --csr save fullchain.pem
This commit is contained in:
+20
-12
@@ -267,21 +267,29 @@ def _treat_as_renewal(config, domains):
|
|||||||
return None
|
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.
|
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)
|
reporter_util = zope.component.getUtility(interfaces.IReporter)
|
||||||
# Tell the user about fullchain.pem because that's what modern webservers
|
if fullchain_path:
|
||||||
# (Nginx and Apache2.4) will want.
|
# 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
|
# XXX Perhaps one day we could detect the presence of known old webservers
|
||||||
# and say something more informative here.
|
# and say something more informative here.
|
||||||
msg = ("Congratulations! Your certificate and chain have been saved at {0}."
|
msg = ("Congratulations! Your certificate {0} been saved at {1}."
|
||||||
" Your cert will expire on {1}. To obtain a new version of the "
|
" Your cert will expire on {2}. To obtain a new version of the "
|
||||||
"certificate in the future, simply run Let's Encrypt again."
|
"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)
|
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:
|
if not lineage:
|
||||||
raise Error("Certificate could not be obtained")
|
raise Error("Certificate could not be obtained")
|
||||||
|
|
||||||
_report_new_cert(lineage)
|
_report_new_cert(lineage.cert, lineage.fullchain)
|
||||||
|
|
||||||
return lineage
|
return lineage
|
||||||
|
|
||||||
@@ -461,9 +469,9 @@ def auth(args, config, plugins):
|
|||||||
if args.csr is not None:
|
if args.csr is not None:
|
||||||
certr, chain = le_client.obtain_certificate_from_csr(le_util.CSR(
|
certr, chain = le_client.obtain_certificate_from_csr(le_util.CSR(
|
||||||
file=args.csr[0], data=args.csr[1], form="der"))
|
file=args.csr[0], data=args.csr[1], form="der"))
|
||||||
cert_path, _ = le_client.save_certificate(
|
cert_path, _, cert_fullchain = le_client.save_certificate(
|
||||||
certr, chain, args.cert_path, args.chain_path)
|
certr, chain, args.cert_path, args.chain_path, args.fullchain_path)
|
||||||
_report_new_cert(cert_path)
|
_report_new_cert(cert_path, cert_fullchain)
|
||||||
else:
|
else:
|
||||||
domains = _find_domains(args, installer)
|
domains = _find_domains(args, installer)
|
||||||
_auth_from_domains(le_client, config, domains, plugins)
|
_auth_from_domains(le_client, config, domains, plugins)
|
||||||
|
|||||||
+17
-6
@@ -258,7 +258,7 @@ class Client(object):
|
|||||||
params, config, cli_config)
|
params, config, cli_config)
|
||||||
return lineage
|
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
|
# pylint: disable=no-self-use
|
||||||
"""Saves the certificate received from the ACME server.
|
"""Saves the certificate received from the ACME server.
|
||||||
|
|
||||||
@@ -268,20 +268,22 @@ class Client(object):
|
|||||||
:param list chain_cert:
|
:param list chain_cert:
|
||||||
:param str cert_path: Candidate path to a certificate.
|
:param str cert_path: Candidate path to a certificate.
|
||||||
:param str chain_path: Candidate path to a certificate chain.
|
: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`
|
:rtype: `tuple` of `str`
|
||||||
|
|
||||||
:raises IOError: If unable to find room to write the cert files
|
: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(
|
le_util.make_or_verify_dir(
|
||||||
os.path.dirname(path), 0o755, os.geteuid(),
|
os.path.dirname(path), 0o755, os.geteuid(),
|
||||||
self.config.strict_permissions)
|
self.config.strict_permissions)
|
||||||
|
|
||||||
# try finally close
|
# try finally close
|
||||||
cert_chain_abspath = None
|
cert_chain_abspath = None
|
||||||
|
fullchain_abspath = None
|
||||||
cert_file, act_cert_path = le_util.unique_file(cert_path, 0o644)
|
cert_file, act_cert_path = le_util.unique_file(cert_path, 0o644)
|
||||||
# TODO: Except
|
# TODO: Except
|
||||||
cert_pem = OpenSSL.crypto.dump_certificate(
|
cert_pem = OpenSSL.crypto.dump_certificate(
|
||||||
@@ -294,8 +296,7 @@ class Client(object):
|
|||||||
act_cert_path)
|
act_cert_path)
|
||||||
|
|
||||||
if chain_cert:
|
if chain_cert:
|
||||||
chain_file, act_chain_path = le_util.unique_file(
|
chain_file, act_chain_path = le_util.unique_file(chain_path, 0o644)
|
||||||
chain_path, 0o644)
|
|
||||||
# TODO: Except
|
# TODO: Except
|
||||||
chain_pem = crypto_util.dump_pyopenssl_chain(chain_cert)
|
chain_pem = crypto_util.dump_pyopenssl_chain(chain_cert)
|
||||||
try:
|
try:
|
||||||
@@ -308,7 +309,17 @@ class Client(object):
|
|||||||
# This expects a valid chain file
|
# This expects a valid chain file
|
||||||
cert_chain_abspath = os.path.abspath(act_chain_path)
|
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,
|
def deploy_certificate(self, domains, privkey_path,
|
||||||
cert_path, chain_path, fullchain_path):
|
cert_path, chain_path, fullchain_path):
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class CLITest(unittest.TestCase):
|
|||||||
date = '1970-01-01'
|
date = '1970-01-01'
|
||||||
mock_notAfter().date.return_value = date
|
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 = mock.MagicMock()
|
||||||
mock_client.obtain_and_enroll_certificate.return_value = mock_lineage
|
mock_client.obtain_and_enroll_certificate.return_value = mock_lineage
|
||||||
self._auth_new_request_common(mock_client)
|
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._treat_as_renewal')
|
||||||
@mock.patch('letsencrypt.cli._init_le_client')
|
@mock.patch('letsencrypt.cli._init_le_client')
|
||||||
def test_auth_renewal(self, mock_init, mock_renewal, mock_get_utility):
|
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_cert = mock.MagicMock(body='body')
|
||||||
mock_key = mock.MagicMock(pem='pem_key')
|
mock_key = mock.MagicMock(pem='pem_key')
|
||||||
mock_renewal.return_value = mock_lineage
|
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.update_all_links_to.assert_called_once_with(
|
||||||
mock_lineage.latest_common_version())
|
mock_lineage.latest_common_version())
|
||||||
self.assertTrue(
|
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.crypto_util.notAfter')
|
||||||
@mock.patch('letsencrypt.cli.display_ops.pick_installer')
|
@mock.patch('letsencrypt.cli.display_ops.pick_installer')
|
||||||
@@ -203,23 +204,24 @@ class CLITest(unittest.TestCase):
|
|||||||
@mock.patch('letsencrypt.cli._init_le_client')
|
@mock.patch('letsencrypt.cli._init_le_client')
|
||||||
def test_auth_csr(self, mock_init, mock_get_utility,
|
def test_auth_csr(self, mock_init, mock_get_utility,
|
||||||
mock_pick_installer, mock_notAfter):
|
mock_pick_installer, mock_notAfter):
|
||||||
cert_path = '/etc/letsencrypt/live/foo.bar'
|
cert_path = '/etc/letsencrypt/live/blahcert.pem'
|
||||||
date = '1970-01-01'
|
date = '1970-01-01'
|
||||||
mock_notAfter().date.return_value = date
|
mock_notAfter().date.return_value = date
|
||||||
|
|
||||||
mock_client = mock.MagicMock()
|
mock_client = mock.MagicMock()
|
||||||
mock_client.obtain_certificate_from_csr.return_value = ('certr',
|
mock_client.obtain_certificate_from_csr.return_value = ('certr',
|
||||||
'chain')
|
'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
|
mock_init.return_value = mock_client
|
||||||
|
|
||||||
installer = 'installer'
|
installer = 'installer'
|
||||||
self._call(
|
self._call(
|
||||||
['-a', 'standalone', '-i', installer, 'auth', '--csr', CSR,
|
['-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)
|
self.assertEqual(mock_pick_installer.call_args[0][1], installer)
|
||||||
mock_client.save_certificate.assert_called_once_with(
|
mock_client.save_certificate.assert_called_once_with(
|
||||||
'certr', 'chain', cert_path, '/')
|
'certr', 'chain', cert_path, '/', '/')
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
cert_path in mock_get_utility().add_message.call_args[0][0])
|
cert_path in mock_get_utility().add_message.call_args[0][0])
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
|
|||||||
@@ -124,14 +124,18 @@ class ClientTest(unittest.TestCase):
|
|||||||
cert2 = test_util.load_cert(certs[2])
|
cert2 = test_util.load_cert(certs[2])
|
||||||
candidate_cert_path = os.path.join(tmp_path, "certs", "cert.pem")
|
candidate_cert_path = os.path.join(tmp_path, "certs", "cert.pem")
|
||||||
candidate_chain_path = os.path.join(tmp_path, "chains", "chain.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(
|
cert_path, chain_path, fullchain_path = self.client.save_certificate(
|
||||||
certr, [cert1, cert2], candidate_cert_path, candidate_chain_path)
|
certr, [cert1, cert2], candidate_cert_path, candidate_chain_path,
|
||||||
|
candidate_fullchain_path)
|
||||||
|
|
||||||
self.assertEqual(os.path.dirname(cert_path),
|
self.assertEqual(os.path.dirname(cert_path),
|
||||||
os.path.dirname(candidate_cert_path))
|
os.path.dirname(candidate_cert_path))
|
||||||
self.assertEqual(os.path.dirname(chain_path),
|
self.assertEqual(os.path.dirname(chain_path),
|
||||||
os.path.dirname(candidate_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:
|
with open(cert_path, "r") as cert_file:
|
||||||
cert_contents = cert_file.read()
|
cert_contents = cert_file.read()
|
||||||
|
|||||||
Reference in New Issue
Block a user