diff --git a/moonraker/app.py b/moonraker/app.py index 6668416..94c81a7 100644 --- a/moonraker/app.py +++ b/moonraker/app.py @@ -11,6 +11,7 @@ import logging import json import datetime import traceback +import ssl import urllib.parse import tornado import tornado.iostream @@ -117,12 +118,23 @@ class APIDefinition: class MoonrakerApp: def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() - self.tornado_server: Optional[HTTPServer] = None + self.http_server: Optional[HTTPServer] = None + self.secure_server: Optional[HTTPServer] = None self.api_cache: Dict[str, APIDefinition] = {} self.registered_base_handlers: List[str] = [] self.max_upload_size = config.getint('max_upload_size', 1024) self.max_upload_size *= 1024 * 1024 + # SSL config + self.cert_path: str = config.get('ssl_certificate_path', "") + self.key_path: str = config.get('ssl_key_path', "") + if self.cert_path: + self.cert_path = os.path.abspath( + os.path.expanduser(self.cert_path)) + if self.key_path: + self.key_path = os.path.abspath( + os.path.expanduser(self.key_path)) + # Set Up Websocket and Authorization Managers self.wsm = WebsocketManager(self.server) @@ -159,10 +171,17 @@ class MoonrakerApp: self.register_static_file_handler( "klippy.log", DEFAULT_KLIPPY_LOG_PATH, force=True) - def listen(self, host: str, port: int) -> None: - self.tornado_server = self.app.listen( + def listen(self, host: str, port: int, ssl_port: int) -> None: + self.http_server = self.app.listen( port, address=host, max_body_size=MAX_BODY_SIZE, xheaders=True) + if os.path.exists(self.cert_path) and os.path.exists(self.key_path): + logging.info(f"Starting secure server on port {ssl_port}") + ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + ssl_ctx.load_cert_chain(self.cert_path, self.key_path) + self.secure_server = self.app.listen( + ssl_port, address=host, max_body_size=MAX_BODY_SIZE, + xheaders=True, ssl_options=ssl_ctx) def log_request(self, handler: tornado.web.RequestHandler) -> None: status_code = handler.get_status() @@ -191,9 +210,12 @@ class MoonrakerApp: return self.wsm async def close(self) -> None: - if self.tornado_server is not None: - self.tornado_server.stop() - await self.tornado_server.close_all_connections() + if self.http_server is not None: + self.http_server.stop() + await self.http_server.close_all_connections() + if self.secure_server is not None: + self.secure_server.stop() + await self.secure_server.close_all_connections() await self.wsm.close() def register_remote_handler(self, endpoint: str) -> None: diff --git a/moonraker/moonraker.py b/moonraker/moonraker.py index 139cd7c..8cc6954 100755 --- a/moonraker/moonraker.py +++ b/moonraker/moonraker.py @@ -75,6 +75,7 @@ class Server: self.add_log_rollover_item('config', cfg_item) self.host: str = config.get('host', "0.0.0.0") self.port: int = config.getint('port', 7125) + self.ssl_port: int = config.getint('ssl_port', 7130) self.exit_reason: str = "" # Event initialization @@ -140,7 +141,7 @@ class Server: logging.info( f"Starting Moonraker on ({self.host}, {hostport}), " f"Hostname: {hostname}") - self.moonraker_app.listen(self.host, self.port) + self.moonraker_app.listen(self.host, self.port, self.ssl_port) self.server_running = True self.ioloop.spawn_callback(self._init_signals) self.ioloop.spawn_callback(self._connect_klippy)