86 lines
3.0 KiB
Python
86 lines
3.0 KiB
Python
"""Windows service that runs the Intrusion Detection Flask web app.
|
|
|
|
Serves the web UI on localhost using the configured defaults
|
|
(``http://127.0.0.1:54666`` from ``app.utils.constants``; the ``WEB_HOST``
|
|
and ``WEB_PORT`` environment variables or a local ``.env`` override them).
|
|
|
|
Manage with (from the project root, in an activated venv):
|
|
python intrusion-detection-service.py install
|
|
python intrusion-detection-service.py start
|
|
python intrusion-detection-service.py stop
|
|
python intrusion-detection-service.py remove
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import threading
|
|
|
|
import servicemanager
|
|
import win32event
|
|
import win32service
|
|
import win32serviceutil
|
|
|
|
# Ensure the project root is importable. When the SCM launches the service
|
|
# the working directory may be C:\\Windows\\System32, not the project dir.
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from app.utils.constants import WEB_HOST, WEB_PORT # noqa: E402
|
|
|
|
|
|
class IntrusionDetectionService(win32serviceutil.ServiceFramework):
|
|
_svc_name_ = "IntrusionDetectionWebUI"
|
|
_svc_display_name_ = "Intrusion Detection Web UI"
|
|
_svc_description_ = (
|
|
"Serves the Intrusion Detection Flask web app on localhost "
|
|
f"(http://{WEB_HOST}:{WEB_PORT})."
|
|
)
|
|
|
|
def __init__(self, args):
|
|
win32serviceutil.ServiceFramework.__init__(self, args)
|
|
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
|
|
self._flask_thread = None
|
|
|
|
def SvcStop(self):
|
|
# Report STOP_PENDING, then signal the main loop; the SCM marks the
|
|
# service STOPPED once SvcDoRun returns (after Flask shuts down).
|
|
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
|
|
win32event.SetEvent(self.hWaitStop)
|
|
|
|
def SvcDoRun(self):
|
|
servicemanager.LogMsg(
|
|
servicemanager.EVENTLOG_INFORMATION_TYPE,
|
|
servicemanager.PYS_SERVICE_STARTED,
|
|
(self._svc_name_, '')
|
|
)
|
|
try:
|
|
self.main()
|
|
finally:
|
|
servicemanager.LogMsg(
|
|
servicemanager.EVENTLOG_INFORMATION_TYPE,
|
|
servicemanager.PYS_SERVICE_STOPPED,
|
|
(self._svc_name_, '')
|
|
)
|
|
|
|
def main(self):
|
|
from app.web import serve
|
|
|
|
# Flask's app.run() blocks, so run it on a daemon thread and keep the
|
|
# service alive here until SvcStop signals the stop event. serve()
|
|
# passes use_reloader=False, which is required under the service host
|
|
# (the reloader would spawn a child process and break the service).
|
|
self._flask_thread = threading.Thread(
|
|
target=serve,
|
|
kwargs={"host": WEB_HOST, "port": WEB_PORT},
|
|
daemon=True,
|
|
name="flask-web",
|
|
)
|
|
self._flask_thread.start()
|
|
|
|
win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Handles both the service-host launch and command-line control
|
|
# (install / start / stop / remove).
|
|
win32serviceutil.HandleCommandLine(IntrusionDetectionService)
|