mrok 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mrok/http/master.py +63 -21
- mrok/ziti/pki.py +10 -5
- {mrok-0.2.0.dist-info → mrok-0.2.2.dist-info}/METADATA +2 -1
- {mrok-0.2.0.dist-info → mrok-0.2.2.dist-info}/RECORD +7 -7
- {mrok-0.2.0.dist-info → mrok-0.2.2.dist-info}/WHEEL +0 -0
- {mrok-0.2.0.dist-info → mrok-0.2.2.dist-info}/entry_points.txt +0 -0
- {mrok-0.2.0.dist-info → mrok-0.2.2.dist-info}/licenses/LICENSE.txt +0 -0
mrok/http/master.py
CHANGED
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
import signal
|
|
4
4
|
import threading
|
|
5
|
+
import time
|
|
5
6
|
from collections.abc import Callable
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
|
|
@@ -11,6 +12,10 @@ from watchfiles.run import CombinedProcess, start_process
|
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger("mrok.agent")
|
|
13
14
|
|
|
15
|
+
MONITOR_THREAD_JOIN_TIMEOUT = 5
|
|
16
|
+
MONITOR_THREAD_CHECK_DELAY = 1
|
|
17
|
+
MONITOR_THREAD_ERROR_DELAY = 3
|
|
18
|
+
|
|
14
19
|
|
|
15
20
|
def print_path(path):
|
|
16
21
|
try:
|
|
@@ -29,7 +34,7 @@ class Master:
|
|
|
29
34
|
self.start_fn = start_fn
|
|
30
35
|
self.workers = workers
|
|
31
36
|
self.reload = reload
|
|
32
|
-
self.worker_processes:
|
|
37
|
+
self.worker_processes: dict[int, CombinedProcess] = {}
|
|
33
38
|
self.stop_event = threading.Event()
|
|
34
39
|
self.watch_filter = PythonFilter(ignore_paths=None)
|
|
35
40
|
self.watcher = watch(
|
|
@@ -39,6 +44,7 @@ class Master:
|
|
|
39
44
|
yield_on_timeout=True,
|
|
40
45
|
)
|
|
41
46
|
self.setup_signals_handler()
|
|
47
|
+
self.monitor_thread = None
|
|
42
48
|
|
|
43
49
|
def setup_signals_handler(self):
|
|
44
50
|
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
@@ -47,26 +53,50 @@ class Master:
|
|
|
47
53
|
def handle_signal(self, *args, **kwargs):
|
|
48
54
|
self.stop_event.set()
|
|
49
55
|
|
|
56
|
+
def start_worker(self, worker_id: int):
|
|
57
|
+
"""Start a single worker process"""
|
|
58
|
+
p = start_process(
|
|
59
|
+
self.start_fn,
|
|
60
|
+
"function",
|
|
61
|
+
(),
|
|
62
|
+
None,
|
|
63
|
+
)
|
|
64
|
+
logger.info(f"Worker {worker_id} [{p.pid}] started")
|
|
65
|
+
return p
|
|
66
|
+
|
|
50
67
|
def start(self):
|
|
51
|
-
for
|
|
52
|
-
p =
|
|
53
|
-
|
|
54
|
-
"function",
|
|
55
|
-
(),
|
|
56
|
-
None,
|
|
57
|
-
)
|
|
58
|
-
logger.info(f"Worker [{p.pid}] started")
|
|
59
|
-
self.worker_processes.append(p)
|
|
68
|
+
for i in range(self.workers):
|
|
69
|
+
p = self.start_worker(i)
|
|
70
|
+
self.worker_processes[i] = p
|
|
60
71
|
|
|
61
72
|
def stop(self):
|
|
62
|
-
for process in self.worker_processes:
|
|
73
|
+
for process in self.worker_processes.values():
|
|
63
74
|
process.stop(sigint_timeout=5, sigkill_timeout=1)
|
|
64
|
-
self.worker_processes
|
|
75
|
+
self.worker_processes.clear()
|
|
65
76
|
|
|
66
77
|
def restart(self):
|
|
67
78
|
self.stop()
|
|
68
79
|
self.start()
|
|
69
80
|
|
|
81
|
+
def monitor_workers(self):
|
|
82
|
+
while not self.stop_event.is_set():
|
|
83
|
+
try:
|
|
84
|
+
for worker_id, process in self.worker_processes.items():
|
|
85
|
+
if not process.is_alive():
|
|
86
|
+
logger.warning(f"Worker {worker_id} [{process.pid}] died unexpectedly")
|
|
87
|
+
process.stop(sigint_timeout=1, sigkill_timeout=1)
|
|
88
|
+
new_process = self.start_worker(worker_id)
|
|
89
|
+
self.worker_processes[worker_id] = new_process
|
|
90
|
+
logger.info(
|
|
91
|
+
f"Restarted worker {worker_id} [{process.pid}] -> [{new_process.pid}]"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
time.sleep(MONITOR_THREAD_CHECK_DELAY)
|
|
95
|
+
|
|
96
|
+
except Exception as e:
|
|
97
|
+
logger.error(f"Error in worker monitoring: {e}")
|
|
98
|
+
time.sleep(MONITOR_THREAD_ERROR_DELAY)
|
|
99
|
+
|
|
70
100
|
def __iter__(self):
|
|
71
101
|
return self
|
|
72
102
|
|
|
@@ -79,12 +109,24 @@ class Master:
|
|
|
79
109
|
def run(self):
|
|
80
110
|
self.start()
|
|
81
111
|
logger.info(f"Master process started: {os.getpid()}")
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
112
|
+
|
|
113
|
+
# Start worker monitoring thread
|
|
114
|
+
self.monitor_thread = threading.Thread(target=self.monitor_workers, daemon=True)
|
|
115
|
+
self.monitor_thread.start()
|
|
116
|
+
logger.debug("Worker monitoring thread started")
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
if self.reload:
|
|
120
|
+
for files_changed in self:
|
|
121
|
+
if files_changed:
|
|
122
|
+
logger.warning(
|
|
123
|
+
f"{', '.join(map(print_path, files_changed))} changed, reloading...",
|
|
124
|
+
)
|
|
125
|
+
self.restart()
|
|
126
|
+
else:
|
|
127
|
+
self.stop_event.wait()
|
|
128
|
+
finally:
|
|
129
|
+
if self.monitor_thread and self.monitor_thread.is_alive(): # pragma: no cover
|
|
130
|
+
logger.debug("Wait for monitor worker to exit")
|
|
131
|
+
self.monitor_thread.join(timeout=MONITOR_THREAD_JOIN_TIMEOUT)
|
|
132
|
+
self.stop()
|
mrok/ziti/pki.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import base64
|
|
2
2
|
|
|
3
|
+
from asn1crypto import cms
|
|
3
4
|
from cryptography import x509
|
|
4
5
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
5
6
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
6
|
-
from cryptography.hazmat.primitives.serialization.pkcs7 import load_der_pkcs7_certificates
|
|
7
7
|
from cryptography.x509.oid import NameOID
|
|
8
8
|
|
|
9
9
|
from mrok.ziti.api import ZitiManagementAPI
|
|
@@ -16,11 +16,16 @@ async def get_ca_certificates(mgmt_api: ZitiManagementAPI) -> str:
|
|
|
16
16
|
if not _ca_certificates:
|
|
17
17
|
cas_pkcs7 = await mgmt_api.fetch_ca_certificates()
|
|
18
18
|
pkcs7_bytes = base64.b64decode(cas_pkcs7)
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
content_info = cms.ContentInfo.load(pkcs7_bytes)
|
|
21
|
+
certs = content_info["content"]["certificates"]
|
|
22
|
+
|
|
20
23
|
ca_certificates = []
|
|
21
|
-
for cert in
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
for cert in certs:
|
|
25
|
+
crypt_cert = x509.load_der_x509_certificate(cert.dump())
|
|
26
|
+
pem = crypt_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8")
|
|
27
|
+
ca_certificates.append(pem)
|
|
28
|
+
|
|
24
29
|
_ca_certificates = "\n".join(ca_certificates)
|
|
25
30
|
return _ca_certificates
|
|
26
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mrok
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: MPT Extensions OpenZiti Orchestrator
|
|
5
5
|
Author: SoftwareOne AG
|
|
6
6
|
License: Apache License
|
|
@@ -206,6 +206,7 @@ License: Apache License
|
|
|
206
206
|
limitations under the License.
|
|
207
207
|
License-File: LICENSE.txt
|
|
208
208
|
Requires-Python: <4,>=3.12
|
|
209
|
+
Requires-Dist: asn1crypto<2.0.0,>=1.5.1
|
|
209
210
|
Requires-Dist: cryptography<46.0.0,>=45.0.7
|
|
210
211
|
Requires-Dist: dynaconf<4.0.0,>=3.2.11
|
|
211
212
|
Requires-Dist: fastapi-pagination<0.15.0,>=0.14.1
|
|
@@ -48,7 +48,7 @@ mrok/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
48
48
|
mrok/http/config.py,sha256=k8mjvD3ninJn-v1t-co-GSa3upm4b70bWyk3fwdcOh8,2161
|
|
49
49
|
mrok/http/forwarder.py,sha256=mo-Z8B8Zg6kdDX-lWEiptRv-9kJU9cEdmg6gt6eF0cc,11374
|
|
50
50
|
mrok/http/lifespan.py,sha256=9qevhD_5Y0f8fGTh2axdfWx7v1K4vnWtiUNyJLesOHE,262
|
|
51
|
-
mrok/http/master.py,sha256=
|
|
51
|
+
mrok/http/master.py,sha256=TwU78yE_GQecogBs_PDpl3gY7_jWYNIRNaAXRzi0rvY,4152
|
|
52
52
|
mrok/http/protocol.py,sha256=ap8jbLUvgbAH81ZJZCBkQiYR7mkV_eL3rpfwEkoE8sU,392
|
|
53
53
|
mrok/http/server.py,sha256=Mj7C85fc-DXp-WTBWaOd7ag808oliLmFBH5bf-G2FHg,370
|
|
54
54
|
mrok/ziti/__init__.py,sha256=20OWMiexRhOovZOX19zlX87-V78QyWnEnSZfyAftUdE,263
|
|
@@ -57,10 +57,10 @@ mrok/ziti/bootstrap.py,sha256=QIDhlkIxPW2QRuumFq2D1WDbD003P5f3z24pAUsyeBI,2696
|
|
|
57
57
|
mrok/ziti/constants.py,sha256=Urq1X3bCBQZfw8NbnEa1pqmY4oq1wmzkwPfzam3kbTw,339
|
|
58
58
|
mrok/ziti/errors.py,sha256=yYCbVDwktnR0AYduqtynIjo73K3HOhIrwA_vQimvEd4,368
|
|
59
59
|
mrok/ziti/identities.py,sha256=oE_3j6Y4xCr6uKNdprW55bxGsyKnmJt-MrxrylB2Ey4,5388
|
|
60
|
-
mrok/ziti/pki.py,sha256
|
|
60
|
+
mrok/ziti/pki.py,sha256=o2tySqHC8-7bvFuI2Tqxg9vX6H6ZSxWxfP_9x29e19M,1954
|
|
61
61
|
mrok/ziti/services.py,sha256=JnznLTHNZjgbFwnBtv7y2XIp4NiQxLVawwP9EfWdVuM,3208
|
|
62
|
-
mrok-0.2.
|
|
63
|
-
mrok-0.2.
|
|
64
|
-
mrok-0.2.
|
|
65
|
-
mrok-0.2.
|
|
66
|
-
mrok-0.2.
|
|
62
|
+
mrok-0.2.2.dist-info/METADATA,sha256=aB7i_YKGCGzw0Eo2yOHE5u7uY4Y4wuDaj24245QH3fE,15546
|
|
63
|
+
mrok-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
64
|
+
mrok-0.2.2.dist-info/entry_points.txt,sha256=tloXwvU1uJicBJR2h-8HoVclPgwJWDwuREMHN8Zq-nU,38
|
|
65
|
+
mrok-0.2.2.dist-info/licenses/LICENSE.txt,sha256=6PaICaoA3yNsZKLv5G6OKqSfLSoX7MakYqTDgJoTCBs,11346
|
|
66
|
+
mrok-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|