service.py 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # This file is part of acme-updater, written by Helmut Pozimski 2016-2017.
  2. #
  3. # stov is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, version 2 of the License.
  6. #
  7. # stov is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License
  13. # along with stov. If not, see <http://www.gnu.org/licenses/>.
  14. # -*- coding: utf8 -*-
  15. """ Contains the service module which manages certificates for generic
  16. services that don't need any special configuration. The configuration
  17. needs to at least contain the keys "certificate_path", "key_path",
  18. "tlsa"and "tlsa_ports".
  19. """
  20. import logging
  21. import socket
  22. import os
  23. import subprocess
  24. from amulib import helpers
  25. import OpenSSL
  26. LOGGER = logging.getLogger("acme_tlsa_mail")
  27. def run(service_name, config, acme_dir="/var/lib/acme",
  28. named_key_path="/run/named/session.key"):
  29. """
  30. :param service_name: name of the service
  31. :type service_name: str
  32. :param config: configuration for the service
  33. :type config: dict
  34. :param acme_dir: path to the acme state dir
  35. :type acme_dir: str
  36. :param named_key_path: path to the named session.key
  37. :type named_key_path: str
  38. """
  39. fqdn = socket.getfqdn()
  40. certificate_path = config["certificate_path"]
  41. key_path = config["key_path"]
  42. tlsa = config["tlsa"]
  43. tlsa_ports = config["tlsa_ports"]
  44. try:
  45. with open(certificate_path, "r") as cert_file:
  46. cert_text = cert_file.read()
  47. except IOError:
  48. LOGGER.error("Error while opening the %s certificate", service_name)
  49. else:
  50. current_cert = OpenSSL.crypto.load_certificate(
  51. OpenSSL.crypto.FILETYPE_PEM, cert_text
  52. )
  53. acme_cert_path = os.path.join(acme_dir, "live", fqdn,
  54. "cert")
  55. acme_fullchain_path = os.path.join(acme_dir, "live", fqdn,
  56. "fullchain")
  57. if helpers.check_renewal(current_cert, acme_cert_path):
  58. try:
  59. with open(acme_cert_path, "r") as acme_cert_file:
  60. acme_cert_text = acme_cert_file.read()
  61. except IOError:
  62. LOGGER.error("Error while opening new %s "
  63. "certificate file", service_name)
  64. else:
  65. acme_cert = OpenSSL.crypto.load_certificate(
  66. OpenSSL.crypto.FILETYPE_PEM, acme_cert_text
  67. )
  68. if tlsa:
  69. for port in tlsa_ports:
  70. helpers.create_tlsa_records(fqdn, port, acme_cert,
  71. named_key_path)
  72. if helpers.copy_file(acme_fullchain_path, certificate_path):
  73. newkey_path = os.path.join(acme_dir, "live",
  74. fqdn, "privkey")
  75. if helpers.copy_file(newkey_path, key_path):
  76. LOGGER.info("Certificate for %s successfully "
  77. "renewed, restarting service.",
  78. service_name)
  79. subprocess.call(["/etc/init.d/%s" % service_name,
  80. "restart"])
  81. else:
  82. LOGGER.error("Renewal of cert for %s failed, "
  83. "please clean up manually and "
  84. "check the backup files!", service_name)
  85. else:
  86. LOGGER.error("Renewal of cert for %s failed, "
  87. "please clean up manually and "
  88. "check the backup files!", service_name)