diff --git a/letsencrypt/storage.py b/letsencrypt/storage.py index 08b48ff5e..e41805459 100644 --- a/letsencrypt/storage.py +++ b/letsencrypt/storage.py @@ -128,6 +128,17 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes self.fullchain = self.configuration["fullchain"] self._fix_symlinks() + self._check_symlinks() + + def _check_symlinks(self): + """Raises an exception if a symlink doesn't exist""" + def check(link): + """Checks if symlink points to a file that exists""" + return os.path.exists(os.path.realpath(link)) + for kind in ALL_FOUR: + if not check(getattr(self, kind)): + raise errors.CertStorageError( + "link: {0} does not exist".format(getattr(self, kind))) def _consistent(self): """Are the files associated with this lineage self-consistent? diff --git a/letsencrypt/tests/renewer_test.py b/letsencrypt/tests/renewer_test.py index 7030e4998..3c8e3cb95 100644 --- a/letsencrypt/tests/renewer_test.py +++ b/letsencrypt/tests/renewer_test.py @@ -76,7 +76,10 @@ class BaseRenewableCertTest(unittest.TestCase): junk.close() self.defaults = configobj.ConfigObj() - self.test_rc = storage.RenewableCert(config.filename, self.cli_config) + + with mock.patch("letsencrypt.storage.RenewableCert._check_symlinks") as check: + check.return_value = True + self.test_rc = storage.RenewableCert(config.filename, self.cli_config) def tearDown(self): shutil.rmtree(self.tempdir) @@ -786,6 +789,12 @@ class RenewableCertTests(BaseRenewableCertTest): renewer.main(cli_args=self._common_cli_args()) # The errors.CertStorageError is caught inside and nothing happens. + def test_missing_cert(self): + from letsencrypt import storage + self.assertRaises(errors.CertStorageError, + storage.RenewableCert, + self.config.filename, self.cli_config) + if __name__ == "__main__": unittest.main() # pragma: no cover