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 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: list[CombinedProcess] = []
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 _ in range(self.workers):
52
- p = start_process(
53
- self.start_fn,
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
- if self.reload:
83
- for files_changed in self:
84
- if files_changed:
85
- logger.warning(
86
- f"{', '.join(map(print_path, files_changed))} changed, reloading...",
87
- )
88
- self.restart()
89
- else:
90
- self.stop_event.wait()
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
- pkcs7_certs = load_der_pkcs7_certificates(pkcs7_bytes)
19
+
20
+ content_info = cms.ContentInfo.load(pkcs7_bytes)
21
+ certs = content_info["content"]["certificates"]
22
+
20
23
  ca_certificates = []
21
- for cert in pkcs7_certs:
22
- cert_pem = cert.public_bytes(serialization.Encoding.PEM)
23
- ca_certificates.append(cert_pem.decode("utf-8"))
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.0
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=o_0Sxe2XuTgVAwvBbWkYcO3HkCcfvYP4rgxcuIDPwXo,2426
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=-V3LDAtntYZ4C6IH2rqfAANxmzpOZ32Rd0MK_27YNME,1906
60
+ mrok/ziti/pki.py,sha256=o2tySqHC8-7bvFuI2Tqxg9vX6H6ZSxWxfP_9x29e19M,1954
61
61
  mrok/ziti/services.py,sha256=JnznLTHNZjgbFwnBtv7y2XIp4NiQxLVawwP9EfWdVuM,3208
62
- mrok-0.2.0.dist-info/METADATA,sha256=A2vtrbNcUnIOTYf0xU2KZubFzN_yA7wShKQuMZcnKaE,15506
63
- mrok-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
64
- mrok-0.2.0.dist-info/entry_points.txt,sha256=tloXwvU1uJicBJR2h-8HoVclPgwJWDwuREMHN8Zq-nU,38
65
- mrok-0.2.0.dist-info/licenses/LICENSE.txt,sha256=6PaICaoA3yNsZKLv5G6OKqSfLSoX7MakYqTDgJoTCBs,11346
66
- mrok-0.2.0.dist-info/RECORD,,
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