feat: implement Windows service for Intrusion Detection Flask web app
This commit is contained in:
1 parent
67576e3c69
commit
af5da6c332
2 files changed
+87
-1
No files matched your search
@@ -0,0 +1,85 @@
|
|||||||
|
"""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)
|
||||||
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
flask
|
||||||
paramiko
|
paramiko
|
||||||
python-dotenv
|
python-dotenv
|
||||||
flask
|
pywin32
|
||||||
Reference in new issue
Block a user