import json from pathlib import Path import shutil import sys import tempfile import unittest from renew_local_tls import identity, openssl, renew class IdentityTests(unittest.TestCase): def test_ip_and_dns_names(self): self.assertEqual(identity("192.168.188.45"), ("192.168.188.45", "IP", "-verify_ip")) self.assertEqual(identity("Inventory.Example.org")[0], "inventory.example.org") def test_invalid_names_are_rejected(self): for name in ("https://example.org", "example.org:443", "", "a\nsubjectAltName=DNS:evil", "*.example.org"): with self.subTest(name=name), self.assertRaises(ValueError): identity(name) @unittest.skipUnless(sys.platform != "win32" and shutil.which("openssl"), "Linux/OpenSSL required") class CertificateTests(unittest.TestCase): def test_issue_reuse_and_renew_preserve_ca(self): with tempfile.TemporaryDirectory() as directory: project = Path(directory) renew(project, "192.168.188.45") ca = (project / "tls/ca/root.crt").read_bytes() state = project / "tls/certs/current.json" first = json.loads(state.read_text()) renew(project, "192.168.188.45") self.assertEqual(first, json.loads(state.read_text())) renew(project, "192.168.188.45", force=True) second = json.loads(state.read_text()) self.assertNotEqual(first["serial"], second["serial"]) self.assertEqual(ca, (project / "tls/ca/root.crt").read_bytes()) self.assertIn(second["serial"], (project / "traefik/dynamic/tls.yml").read_text()) self.assertEqual((project / "tls/certs" / (second["serial"] + ".key")).stat().st_mode & 0o777, 0o600) openssl("verify", "-CAfile", project / "tls/ca/root.crt", "-verify_ip", "192.168.188.45", project / "tls/certs" / (second["serial"] + ".crt")) def test_incomplete_ca_is_not_overwritten(self): with tempfile.TemporaryDirectory() as directory: project = Path(directory) ca = project / "tls/ca" ca.mkdir(parents=True) (ca / "root.key").write_text("existing key") with self.assertRaises(RuntimeError): renew(project, "192.168.188.45") self.assertEqual((ca / "root.key").read_text(), "existing key") if __name__ == "__main__": unittest.main()