diff --git a/letsencrypt/client/renewer.py b/letsencrypt/client/renewer.py index de9537b4a..619be206f 100644 --- a/letsencrypt/client/renewer.py +++ b/letsencrypt/client/renewer.py @@ -84,12 +84,13 @@ def renew(cert, old_version): # best is to have obtain_certificate return None for # new_key if the old key is to be used (since save_successor # already understands this distinction!) - cert.save_successor(old_version, new_cert, new_key, new_chain) + return cert.save_successor(old_version, new_cert, new_key, new_chain) # TODO: Notify results else: # TODO: Notify negative results - pass + return False # TODO: Consider the case where the renewal was partially successful + # (where fewer than all names were renewed) def main(config=DEFAULTS): """main function for autorenewer script.""" @@ -98,8 +99,8 @@ def main(config=DEFAULTS): if not i.endswith(".conf"): continue try: - cert = storage.RenewableCert( - os.path.join(config["renewal_configs_dir"], i)) + cert = storage.RenewableCert(configobj.ConfigObj( + os.path.join(config["renewal_configs_dir"], i))) except ValueError: # This indicates an invalid renewal configuration file, such # as one missing a required parameter (in the future, perhaps diff --git a/letsencrypt/client/tests/renewer_test.py b/letsencrypt/client/tests/renewer_test.py index 44681f4e5..1df1bec5c 100644 --- a/letsencrypt/client/tests/renewer_test.py +++ b/letsencrypt/client/tests/renewer_test.py @@ -660,6 +660,56 @@ class RenewableCertTests(unittest.TestCase): self.assertEqual(storage.parse_time_interval("4 years"), datetime.timedelta(1461)) + @mock.patch("letsencrypt.client.renewer.plugins_disco") + @mock.patch("letsencrypt.client.client.determine_account") + @mock.patch("letsencrypt.client.client.Client") + def test_renew(self, mock_c, mock_da, mock_pd): + """Tests for renew().""" + from letsencrypt.client import renewer + + test_cert = pkg_resources.resource_string( + "letsencrypt.client.tests", "testdata/cert-san.pem") + os.symlink(os.path.join("..", "..", "archive", "example.org", + "cert1.pem"), self.test_rc.cert) + os.symlink(os.path.join("..", "..", "archive", "example.org", + "privkey1.pem"), self.test_rc.privkey) + os.symlink(os.path.join("..", "..", "archive", "example.org", + "chain1.pem"), self.test_rc.chain) + os.symlink(os.path.join("..", "..", "archive", "example.org", + "fullchain1.pem"), self.test_rc.fullchain) + with open(self.test_rc.cert, "w") as f: + f.write(test_cert) + with open(self.test_rc.privkey, "w") as f: + f.write("privkey") + with open(self.test_rc.chain, "w") as f: + f.write("chain") + with open(self.test_rc.fullchain, "w") as f: + f.write("fullchain") + + # Fails because renewalparams are missing + self.assertFalse(renewer.renew(self.test_rc, 1)) + self.test_rc.configfile["renewalparams"] = {"some": "stuff"} + # Fails because there's no authenticator specified + self.assertFalse(renewer.renew(self.test_rc, 1)) + self.test_rc.configfile["renewalparams"]["rsa_key_size"] = "2048" + self.test_rc.configfile["renewalparams"]["server"] = "acme.example.com" + self.test_rc.configfile["renewalparams"]["authenticator"] = "fake" + mock_auth = mock.MagicMock() + mock_pd.PluginsRegistry.find_all.return_value = {"apache": mock_auth} + # Fails because "fake" != "apache" + self.assertFalse(renewer.renew(self.test_rc, 1)) + self.test_rc.configfile["renewalparams"]["authenticator"] = "apache" + mock_client = mock.MagicMock() + mock_client.obtain_certificate.return_value = ("cert", "key", "chain") + mock_c.return_value = mock_client + self.assertEqual(2, renewer.renew(self.test_rc, 1)) + # TODO: We could also make several assertions about calls that should + # have been made to the mock functions here. + mock_client.obtain_certificate.return_value = (None, None, None) + # This should fail because the renewal itself appears to fail + self.assertEqual(False, renewer.renew(self.test_rc, 1)) + + @mock.patch("letsencrypt.client.renewer.notify") @mock.patch("letsencrypt.client.storage.RenewableCert") @mock.patch("letsencrypt.client.renewer.renew") @@ -705,5 +755,13 @@ class RenewableCertTests(unittest.TestCase): self.assertEqual(mock_notify.notify.call_count, 4) self.assertEqual(mock_renew.call_count, 2) + def test_bad_config_file(self): + from letsencrypt.client import renewer + with open(os.path.join(self.defaults["renewal_configs_dir"], + "bad.conf"), "w") as f: + f.write("incomplete = configfile\n") + renewer.main(self.defaults) + # The ValueError is caught inside and nothing happens. + if __name__ == "__main__": unittest.main()