test_module.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import unittest, os, sys, tempfile
  2. from subprocess import Popen, PIPE
  3. try:
  4. from StringIO import StringIO # Python 2
  5. except ImportError:
  6. from io import StringIO # Python 3
  7. import acme_tiny
  8. from .monkey import gen_keys
  9. KEYS = gen_keys()
  10. class TestModule(unittest.TestCase):
  11. "Tests for acme_tiny.get_crt()"
  12. def setUp(self):
  13. self.CA = "https://acme-staging-v02.api.letsencrypt.org"
  14. self.tempdir = tempfile.mkdtemp()
  15. self.fuse_proc = Popen(["python", "tests/monkey.py", self.tempdir])
  16. def tearDown(self):
  17. self.fuse_proc.terminate()
  18. self.fuse_proc.wait()
  19. os.rmdir(self.tempdir)
  20. def test_success_cn(self):
  21. """ Successfully issue a certificate via common name """
  22. old_stdout = sys.stdout
  23. sys.stdout = StringIO()
  24. result = acme_tiny.main([
  25. "--account-key", KEYS['account_key'].name,
  26. "--csr", KEYS['domain_csr'].name,
  27. "--acme-dir", self.tempdir,
  28. "--ca", self.CA,
  29. ])
  30. sys.stdout.seek(0)
  31. crt = sys.stdout.read().encode("utf8")
  32. sys.stdout = old_stdout
  33. out, err = Popen(["openssl", "x509", "-text", "-noout"], stdin=PIPE,
  34. stdout=PIPE, stderr=PIPE).communicate(crt)
  35. self.assertIn("Issuer: CN=Fake LE Intermediate", out.decode("utf8"))
  36. def test_success_san(self):
  37. """ Successfully issue a certificate via subject alt name """
  38. old_stdout = sys.stdout
  39. sys.stdout = StringIO()
  40. result = acme_tiny.main([
  41. "--account-key", KEYS['account_key'].name,
  42. "--csr", KEYS['san_csr'].name,
  43. "--acme-dir", self.tempdir,
  44. "--ca", self.CA,
  45. ])
  46. sys.stdout.seek(0)
  47. crt = sys.stdout.read().encode("utf8")
  48. sys.stdout = old_stdout
  49. out, err = Popen(["openssl", "x509", "-text", "-noout"], stdin=PIPE,
  50. stdout=PIPE, stderr=PIPE).communicate(crt)
  51. self.assertIn("Issuer: CN=Fake LE Intermediate", out.decode("utf8"))
  52. def test_success_cli(self):
  53. """ Successfully issue a certificate via command line interface """
  54. crt, err = Popen([
  55. "python", "acme_tiny.py",
  56. "--account-key", KEYS['account_key'].name,
  57. "--csr", KEYS['domain_csr'].name,
  58. "--acme-dir", self.tempdir,
  59. "--ca", self.CA,
  60. ], stdout=PIPE, stderr=PIPE).communicate()
  61. out, err = Popen(["openssl", "x509", "-text", "-noout"], stdin=PIPE,
  62. stdout=PIPE, stderr=PIPE).communicate(crt)
  63. self.assertIn("Issuer: CN=Fake LE Intermediate", out.decode("utf8"))
  64. def test_missing_account_key(self):
  65. """ OpenSSL throws an error when the account key is missing """
  66. try:
  67. result = acme_tiny.main([
  68. "--account-key", "/foo/bar",
  69. "--csr", KEYS['domain_csr'].name,
  70. "--acme-dir", self.tempdir,
  71. "--ca", self.CA,
  72. ])
  73. except Exception as e:
  74. result = e
  75. self.assertIsInstance(result, IOError)
  76. self.assertIn("Error opening Private Key", result.args[0])
  77. def test_missing_csr(self):
  78. """ OpenSSL throws an error when the CSR is missing """
  79. try:
  80. result = acme_tiny.main([
  81. "--account-key", KEYS['account_key'].name,
  82. "--csr", "/foo/bar",
  83. "--acme-dir", self.tempdir,
  84. "--ca", self.CA,
  85. ])
  86. except Exception as e:
  87. result = e
  88. self.assertIsInstance(result, IOError)
  89. self.assertIn("Error loading /foo/bar", result.args[0])
  90. def test_weak_key(self):
  91. """ Let's Encrypt rejects weak keys """
  92. try:
  93. result = acme_tiny.main([
  94. "--account-key", KEYS['weak_key'].name,
  95. "--csr", KEYS['domain_csr'].name,
  96. "--acme-dir", self.tempdir,
  97. "--ca", self.CA,
  98. ])
  99. except Exception as e:
  100. result = e
  101. self.assertIsInstance(result, ValueError)
  102. self.assertIn("key too small", result.args[0])
  103. def test_invalid_domain(self):
  104. """ Let's Encrypt rejects invalid domains """
  105. try:
  106. result = acme_tiny.main([
  107. "--account-key", KEYS['account_key'].name,
  108. "--csr", KEYS['invalid_csr'].name,
  109. "--acme-dir", self.tempdir,
  110. "--ca", self.CA,
  111. ])
  112. except Exception as e:
  113. result = e
  114. self.assertIsInstance(result, ValueError)
  115. self.assertIn("Invalid character in DNS name", result.args[0])
  116. def test_nonexistant_domain(self):
  117. """ Should be unable verify a nonexistent domain """
  118. try:
  119. result = acme_tiny.main([
  120. "--account-key", KEYS['account_key'].name,
  121. "--csr", KEYS['nonexistent_csr'].name,
  122. "--acme-dir", self.tempdir,
  123. "--ca", self.CA,
  124. ])
  125. except Exception as e:
  126. result = e
  127. self.assertIsInstance(result, ValueError)
  128. self.assertIn("but couldn't download", result.args[0])
  129. def test_account_key_domain(self):
  130. """ Can't use the account key for the CSR """
  131. try:
  132. result = acme_tiny.main([
  133. "--account-key", KEYS['account_key'].name,
  134. "--csr", KEYS['account_csr'].name,
  135. "--acme-dir", self.tempdir,
  136. "--ca", self.CA,
  137. ])
  138. except Exception as e:
  139. result = e
  140. self.assertIsInstance(result, ValueError)
  141. self.assertIn("certificate public key must be different than account key", result.args[0])