Repository: Mailu/Mailu

Issue:
certwatcher.py is not using TLS_CERT_FILENAME nor TLS_KEYPAIR_FILENAME
certwatcher.py is assuming that the certificate and the key are in /certs and named respectively cert.pem and key.pem

However, Mailu offer two environment variables to allow specific path & filename for the certificate and the key which are used in config.py:
TLS_CERT_FILENAME
TLS_KEYPAIR_FILENAME

I would add that in my use case (https-portal as a reverse proxy), those files are not directly in /certs. My environment variables look like:
TLS_CERT_FILENAME=mail.example.net/production/signed.crt
TLS_KEYPAIR_FILENAME=mail.example.net/production/domain.key
Currently, certwatcher.py is monitoring `/certs`, whereas I would need to monitor 
`/certs/mail.example.net/production`


Discussion:

Resolving patch:
diff --git a/core/nginx/certwatcher.py b/core/nginx/certwatcher.py
--- a/core/nginx/certwatcher.py
+++ b/core/nginx/certwatcher.py
@@ -5,8 +5,8 @@
 of TLS_FLAVOR=[mail, cert]
 """
 
-from os.path import exists, split as path_split
-from os import system
+from os.path import exists, split as path_split, join as path_join
+from os import system, getenv
 import time
 from watchdog.observers.polling import PollingObserver
 from watchdog.events import FileSystemEventHandler, FileDeletedEvent, \
@@ -14,6 +14,13 @@
 
 class ChangeHandler(FileSystemEventHandler):
     "watchdog-handler listening on any event, executing the correct configuration/reload steps"
+
+    def __init__(self, cert_path, keypair_path):
+        "Initialize a new changehandler"""
+        super().__init__()
+        self.cert_path = cert_path
+        self.keypair_path = keypair_path
+
     @staticmethod
     def reload_nginx():
         "merely reload nginx without re-configuring everything"
@@ -32,11 +39,11 @@ def on_any_event(self, event):
         if event.is_directory:
             return
 
-        filename = path_split(event.src_path)[-1]
+        filename = event.src_path
         if isinstance(event, FileMovedEvent):
-            filename = path_split(event.dest_path)[-1]
+            filename = event.dest_path
 
-        if filename in ['cert.pem', 'key.pem']:
+        if filename in [self.cert_path, self.keypair_path]:
             # all cases except for FileModified need re-configure
             if isinstance(event, (FileCreatedEvent, FileMovedEvent, FileDeletedEvent)):
                 ChangeHandler.reexec_config()
@@ -44,14 +51,21 @@ def on_any_event(self, event):
             elif isinstance(event, FileModifiedEvent):
                 ChangeHandler.reload_nginx()
         # cert files have been moved away, re-configure
-        elif isinstance(event, FileMovedEvent) and path_split(event.src_path)[-1] in ['cert.pem', 'key.pem']:
+        elif isinstance(event, FileMovedEvent) and event.src_path in [self.cert_path, self.keypair_path]:
             ChangeHandler.reexec_config()
 
 
 if __name__ == '__main__':
+    cert_path = path_join("/certs/", getenv("TLS_CERT_FILENAME", default="cert.pem"))
+    cert_dir = path_split(cert_path)[0]
+    keypair_path = path_join("/certs/", getenv("TLS_KEYPAIR_FILENAME", default="key.pem"))
+    keypair_dir = path_split(keypair_path)[0]
+
     observer = PollingObserver()
-    handler = ChangeHandler()
-    observer.schedule(handler, "/certs", recursive=False)
+    handler = ChangeHandler(cert_path, keypair_path)
+    observer.schedule(handler, cert_dir, recursive=False)
+    if keypair_dir != cert_dir:
+       observer.schedule(handler, keypair_dir, recursive=False)
     observer.start()
 
     try:


Test patch: