Browse Source

add service module to manage generic services

Helmut Pozimski 7 years ago
parent
commit
330fab876e
1 changed files with 97 additions and 0 deletions
  1. 97 0
      amulib/service.py

+ 97 - 0
amulib/service.py

@@ -0,0 +1,97 @@
+#   This file is part of acme-updater, written by Helmut Pozimski 2016-2017.
+#
+#   stov is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, version 2 of the License.
+#
+#   stov is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with stov.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# -*- coding: utf8 -*-
+
+""" Contains the service module which manages certificates for generic
+services that don't need any special configuration. The configuration
+needs to at least contain the keys "certificate_path", "key_path",
+"tlsa"and "tlsa_ports".
+"""
+
+import logging
+import socket
+import os
+import subprocess
+
+from amulib import helpers
+import OpenSSL
+
+LOGGER = logging.getLogger("acme_tlsa_mail")
+
+
+def run(service_name, config, acme_dir="/var/lib/acme",
+        named_key_path="/run/named/session.key"):
+    """
+
+    :param service_name: name of the service
+    :type service_name: str
+    :param config: configuration for the service
+    :type config: dict
+    :param acme_dir: path to the acme state dir
+    :type acme_dir: str
+    :param named_key_path: path to the named session.key
+    :type named_key_path: str
+    """
+    fqdn = socket.getfqdn()
+    certificate_path = config["certificate_path"]
+    key_path = config["key_path"]
+    tlsa = config["tlsa"]
+    tlsa_ports = config["tlsa_ports"]
+    try:
+        with open(certificate_path, "r") as cert_file:
+            cert_text = cert_file.read()
+    except IOError:
+        LOGGER.error("Error while opening the %s certificate", service_name)
+    else:
+        current_cert = OpenSSL.crypto.load_certificate(
+            OpenSSL.crypto.FILETYPE_PEM, cert_text
+        )
+        acme_cert_path = os.path.join(acme_dir, "live", fqdn,
+                                      "cert")
+        acme_fullchain_path = os.path.join(acme_dir, "live", fqdn,
+                                           "fullchain")
+        if helpers.check_renewal(current_cert, acme_cert_path):
+            try:
+                with open(acme_cert_path, "r") as acme_cert_file:
+                    acme_cert_text = acme_cert_file.read()
+            except IOError:
+                LOGGER.error("Error while opening new %s "
+                             "certificate file", service_name)
+            else:
+                acme_cert = OpenSSL.crypto.load_certificate(
+                    OpenSSL.crypto.FILETYPE_PEM, acme_cert_text
+                )
+                if tlsa:
+                    for port in tlsa_ports:
+                        helpers.create_tlsa_records(fqdn, port, acme_cert,
+                                                    named_key_path)
+                if helpers.copy_file(acme_fullchain_path, certificate_path):
+                    newkey_path = os.path.join(acme_dir, "live",
+                                               fqdn, "privkey")
+                    if helpers.copy_file(newkey_path, key_path):
+                        LOGGER.info("Certificate for %s successfully "
+                                    "renewed, restarting service.",
+                                    service_name)
+                        subprocess.call(["/etc/init.d/%s" % service_name,
+                                         "restart"])
+                    else:
+                        LOGGER.error("Renewal of cert for %s failed, "
+                                     "please clean up manually and "
+                                     "check the backup files!", service_name)
+                else:
+                    LOGGER.error("Renewal of cert for %s failed, "
+                                 "please clean up manually and "
+                                 "check the backup files!", service_name)