mrok 0.6.0__py3-none-any.whl → 0.8.0__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/agent/devtools/inspector/__main__.py +3 -23
- mrok/agent/devtools/inspector/app.py +407 -112
- mrok/agent/devtools/inspector/utils.py +149 -0
- mrok/cli/commands/admin/bootstrap.py +2 -2
- mrok/cli/commands/admin/register/extensions.py +7 -9
- mrok/cli/commands/admin/register/instances.py +13 -16
- mrok/cli/commands/admin/unregister/extensions.py +7 -11
- mrok/cli/commands/admin/unregister/instances.py +12 -12
- mrok/cli/commands/agent/run/asgi.py +1 -1
- mrok/cli/commands/frontend/run.py +1 -1
- mrok/cli/main.py +17 -1
- mrok/cli/utils.py +26 -0
- mrok/conf.py +15 -7
- mrok/constants.py +21 -0
- mrok/controller/app.py +12 -10
- mrok/controller/auth/__init__.py +11 -0
- mrok/controller/auth/backends.py +60 -0
- mrok/controller/auth/base.py +38 -0
- mrok/controller/auth/manager.py +31 -0
- mrok/controller/auth/registry.py +17 -0
- mrok/frontend/app.py +94 -26
- mrok/frontend/main.py +8 -5
- mrok/frontend/middleware.py +35 -0
- mrok/frontend/utils.py +83 -0
- mrok/logging.py +24 -22
- mrok/proxy/app.py +13 -5
- mrok/proxy/middleware.py +7 -8
- mrok/proxy/models.py +36 -10
- mrok/proxy/ziticorn.py +8 -17
- mrok/ziti/api.py +4 -4
- mrok/ziti/bootstrap.py +0 -5
- mrok/ziti/identities.py +11 -10
- mrok/ziti/services.py +6 -6
- {mrok-0.6.0.dist-info → mrok-0.8.0.dist-info}/METADATA +9 -3
- {mrok-0.6.0.dist-info → mrok-0.8.0.dist-info}/RECORD +38 -35
- mrok/agent/devtools/__main__.py +0 -34
- mrok/cli/commands/agent/utils.py +0 -5
- mrok/controller/auth.py +0 -87
- mrok/proxy/constants.py +0 -22
- mrok/proxy/utils.py +0 -90
- {mrok-0.6.0.dist-info → mrok-0.8.0.dist-info}/WHEEL +0 -0
- {mrok-0.6.0.dist-info → mrok-0.8.0.dist-info}/entry_points.txt +0 -0
- {mrok-0.6.0.dist-info → mrok-0.8.0.dist-info}/licenses/LICENSE.txt +0 -0
mrok/ziti/api.py
CHANGED
|
@@ -38,7 +38,7 @@ class ZitiBadRequestError(ZitiAPIError):
|
|
|
38
38
|
class BaseZitiAPI(ABC):
|
|
39
39
|
def __init__(self, settings: Settings):
|
|
40
40
|
self.settings = settings
|
|
41
|
-
self.limit = self.settings.pagination.limit
|
|
41
|
+
self.limit = self.settings.controller.pagination.limit
|
|
42
42
|
self.token = None
|
|
43
43
|
|
|
44
44
|
@property
|
|
@@ -62,7 +62,7 @@ class BaseZitiAPI(ABC):
|
|
|
62
62
|
auth=self.auth,
|
|
63
63
|
verify=self.settings.ziti.ssl_verify,
|
|
64
64
|
timeout=httpx.Timeout(
|
|
65
|
-
connect=
|
|
65
|
+
connect=self.settings.ziti.connect_timeout,
|
|
66
66
|
read=self.settings.ziti.read_timeout,
|
|
67
67
|
write=2.0,
|
|
68
68
|
pool=5.0,
|
|
@@ -263,7 +263,7 @@ class ZitiIdentityAuth(BaseZitiAuth):
|
|
|
263
263
|
class ZitiManagementAPI(BaseZitiAPI):
|
|
264
264
|
@property
|
|
265
265
|
def base_url(self):
|
|
266
|
-
return f"{self.settings.ziti.
|
|
266
|
+
return f"{self.settings.ziti.base_urls.management}/edge/management/v1"
|
|
267
267
|
|
|
268
268
|
def services(
|
|
269
269
|
self,
|
|
@@ -465,7 +465,7 @@ class ZitiManagementAPI(BaseZitiAPI):
|
|
|
465
465
|
class ZitiClientAPI(BaseZitiAPI):
|
|
466
466
|
@property
|
|
467
467
|
def base_url(self):
|
|
468
|
-
return f"{self.settings.ziti.
|
|
468
|
+
return f"{self.settings.ziti.base_urls.client}/edge/client/v1"
|
|
469
469
|
|
|
470
470
|
async def enroll_identity(self, jti: str, csr_pem: str) -> dict[str, Any]:
|
|
471
471
|
response = await self.httpx_client.post(
|
mrok/ziti/bootstrap.py
CHANGED
|
@@ -36,11 +36,6 @@ async def bootstrap_identity(
|
|
|
36
36
|
logger.info("Deleted existing identity")
|
|
37
37
|
existing_identity = None
|
|
38
38
|
|
|
39
|
-
if forced and config_type:
|
|
40
|
-
await mgmt_api.delete_config_type(config_type["id"])
|
|
41
|
-
logger.info(f"Deleted existing config type '{config_type_name}' ({config_type['id']})")
|
|
42
|
-
config_type = None
|
|
43
|
-
|
|
44
39
|
if existing_identity:
|
|
45
40
|
frontend_id = existing_identity["id"]
|
|
46
41
|
logger.info(f"Identity '{identity_name}' ({frontend_id}) is already enrolled")
|
mrok/ziti/identities.py
CHANGED
|
@@ -41,7 +41,8 @@ async def register_identity(
|
|
|
41
41
|
raise ServiceNotFoundError(f"A service with name `{service_external_id}` does not exists.")
|
|
42
42
|
|
|
43
43
|
identity_name = identity_external_id.lower()
|
|
44
|
-
|
|
44
|
+
router_policy_name = f"{identity_external_id.lower()}.{service_name}"
|
|
45
|
+
service_policy_name = f"{identity_external_id.lower()}.{service_name}:bind"
|
|
45
46
|
self_service_policy_name = f"self.{service_policy_name}"
|
|
46
47
|
|
|
47
48
|
identity = await mgmt_api.search_identity(identity_name)
|
|
@@ -52,7 +53,7 @@ async def register_identity(
|
|
|
52
53
|
service_policy = await mgmt_api.search_service_policy(self_service_policy_name)
|
|
53
54
|
if service_policy:
|
|
54
55
|
await mgmt_api.delete_service_policy(service_policy["id"])
|
|
55
|
-
router_policy = await mgmt_api.search_router_policy(
|
|
56
|
+
router_policy = await mgmt_api.search_router_policy(router_policy_name)
|
|
56
57
|
if router_policy:
|
|
57
58
|
await mgmt_api.delete_router_policy(router_policy["id"])
|
|
58
59
|
await mgmt_api.delete_identity(identity["id"])
|
|
@@ -66,10 +67,9 @@ async def register_identity(
|
|
|
66
67
|
identity_id,
|
|
67
68
|
identity,
|
|
68
69
|
mrok={
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"domain": settings.proxy.domain,
|
|
70
|
+
"extension": service_name,
|
|
71
|
+
"instance": identity_name,
|
|
72
|
+
"domain": settings.frontend.domain,
|
|
73
73
|
"tags": identity_tags,
|
|
74
74
|
},
|
|
75
75
|
)
|
|
@@ -84,7 +84,7 @@ async def register_identity(
|
|
|
84
84
|
self_service["id"],
|
|
85
85
|
identity_id,
|
|
86
86
|
)
|
|
87
|
-
await mgmt_api.create_router_policy(
|
|
87
|
+
await mgmt_api.create_router_policy(router_policy_name, identity_id)
|
|
88
88
|
|
|
89
89
|
return identity, identity_json
|
|
90
90
|
|
|
@@ -100,8 +100,9 @@ async def unregister_identity(
|
|
|
100
100
|
if not service:
|
|
101
101
|
raise ServiceNotFoundError(f"A service with name `{service_external_id}` does not exists.")
|
|
102
102
|
|
|
103
|
-
identity_name =
|
|
104
|
-
|
|
103
|
+
identity_name = identity_external_id.lower()
|
|
104
|
+
router_policy_name = f"{identity_external_id.lower()}.{service_name}"
|
|
105
|
+
service_policy_name = f"{identity_external_id.lower()}.{service_name}:bind"
|
|
105
106
|
|
|
106
107
|
identity = await mgmt_api.search_identity(identity_name)
|
|
107
108
|
if not identity:
|
|
@@ -120,7 +121,7 @@ async def unregister_identity(
|
|
|
120
121
|
service_policy = await mgmt_api.search_service_policy(service_policy_name)
|
|
121
122
|
if service_policy:
|
|
122
123
|
await mgmt_api.delete_service_policy(service_policy["id"])
|
|
123
|
-
router_policy = await mgmt_api.search_router_policy(
|
|
124
|
+
router_policy = await mgmt_api.search_router_policy(router_policy_name)
|
|
124
125
|
if router_policy:
|
|
125
126
|
await mgmt_api.delete_router_policy(router_policy["id"])
|
|
126
127
|
await mgmt_api.delete_identity(identity["id"])
|
mrok/ziti/services.py
CHANGED
|
@@ -19,15 +19,15 @@ async def register_service(
|
|
|
19
19
|
) -> dict[str, Any]:
|
|
20
20
|
service_name = external_id.lower()
|
|
21
21
|
registered = False
|
|
22
|
-
proxy_identity = await mgmt_api.search_identity(settings.
|
|
22
|
+
proxy_identity = await mgmt_api.search_identity(settings.frontend.identity)
|
|
23
23
|
if not proxy_identity:
|
|
24
24
|
raise ProxyIdentityNotFoundError(
|
|
25
|
-
f"Identity for proxy `{settings.
|
|
25
|
+
f"Identity for proxy `{settings.frontend.identity}` not found.",
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
config_type = await mgmt_api.search_config_type(f"{settings.
|
|
28
|
+
config_type = await mgmt_api.search_config_type(f"{settings.frontend.mode}.proxy.v1")
|
|
29
29
|
if not config_type:
|
|
30
|
-
raise ConfigTypeNotFoundError(f"Config type `{settings.
|
|
30
|
+
raise ConfigTypeNotFoundError(f"Config type `{settings.frontend.mode}.proxy.v1` not found.")
|
|
31
31
|
|
|
32
32
|
config = await mgmt_api.search_config(service_name)
|
|
33
33
|
if not config:
|
|
@@ -43,7 +43,7 @@ async def register_service(
|
|
|
43
43
|
else:
|
|
44
44
|
service_id = service["id"]
|
|
45
45
|
proxy_identity_id = proxy_identity["id"]
|
|
46
|
-
service_policy_name = f"{service_name}:{settings.
|
|
46
|
+
service_policy_name = f"{service_name}:{settings.frontend.identity}:dial"
|
|
47
47
|
dial_service_policy = await mgmt_api.search_service_policy(service_policy_name)
|
|
48
48
|
if not dial_service_policy:
|
|
49
49
|
await mgmt_api.create_dial_service_policy(
|
|
@@ -75,7 +75,7 @@ async def unregister_service(
|
|
|
75
75
|
if router_policy:
|
|
76
76
|
await mgmt_api.delete_service_router_policy(router_policy["id"])
|
|
77
77
|
|
|
78
|
-
service_policy_name = f"{service_name}:{settings.
|
|
78
|
+
service_policy_name = f"{service_name}:{settings.frontend.identity}:dial"
|
|
79
79
|
|
|
80
80
|
dial_service_policy = await mgmt_api.search_service_policy(service_policy_name)
|
|
81
81
|
if dial_service_policy:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mrok
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: MPT Extensions OpenZiti Orchestrator
|
|
5
5
|
Author: SoftwareOne AG
|
|
6
6
|
License: Apache License
|
|
@@ -214,6 +214,7 @@ Requires-Dist: fastapi[standard]<0.120.0,>=0.119.0
|
|
|
214
214
|
Requires-Dist: gunicorn<24.0.0,>=23.0.0
|
|
215
215
|
Requires-Dist: hdrhistogram<0.11.0,>=0.10.3
|
|
216
216
|
Requires-Dist: httpcore<2.0.0,>=1.0.9
|
|
217
|
+
Requires-Dist: multipart<2.0.0,>=1.3.0
|
|
217
218
|
Requires-Dist: openziti<2.0.0,>=1.3.1
|
|
218
219
|
Requires-Dist: psutil<8.0.0,>=7.1.3
|
|
219
220
|
Requires-Dist: pydantic<3.0.0,>=2.11.7
|
|
@@ -223,8 +224,8 @@ Requires-Dist: pyyaml<7.0.0,>=6.0.2
|
|
|
223
224
|
Requires-Dist: pyzmq<28.0.0,>=27.1.0
|
|
224
225
|
Requires-Dist: rich<15.0.0,>=14.1.0
|
|
225
226
|
Requires-Dist: textual-serve<2.0.0,>=1.1.3
|
|
226
|
-
Requires-Dist: textual<
|
|
227
|
-
Requires-Dist: typer<0.
|
|
227
|
+
Requires-Dist: textual[syntax]<8.0.0,>=7.2.0
|
|
228
|
+
Requires-Dist: typer<1.0.0,>=0.21.1
|
|
228
229
|
Requires-Dist: uvicorn-worker<0.5.0,>=0.4.0
|
|
229
230
|
Description-Content-Type: text/markdown
|
|
230
231
|
|
|
@@ -240,6 +241,7 @@ It uses the [OpenZiti](https://openziti.io) zero-trust network overlay to create
|
|
|
240
241
|
- **Agent** – Runs alongside an extension in two modes:
|
|
241
242
|
- *Sidecar mode*: proxies traffic between the Ziti network and a local TCP or Unix socket.
|
|
242
243
|
- *Embeddable mode*: integrates with ASGI servers (e.g. Uvicorn) to serve a Python application directly.
|
|
244
|
+
- **Frontend** - Proxies internet request to a specific extension through the OpenZiti network.
|
|
243
245
|
- **CLI** – A command-line tool for administrative tasks and for running the agent in either mode.
|
|
244
246
|
|
|
245
247
|
## Key Features
|
|
@@ -247,5 +249,9 @@ It uses the [OpenZiti](https://openziti.io) zero-trust network overlay to create
|
|
|
247
249
|
- Zero-trust networking with automatic balancing across Extension instances.
|
|
248
250
|
- Simple API and CLI for managing services and identities.
|
|
249
251
|
|
|
252
|
+
## Development
|
|
253
|
+
The included docker compose starts a local Ziti Network (controller + router) and mrok (controller and frontend).
|
|
254
|
+
|
|
255
|
+
|
|
250
256
|
## License
|
|
251
257
|
[Apache 2.0](LICENSE)
|
|
@@ -1,54 +1,57 @@
|
|
|
1
1
|
mrok/__init__.py,sha256=D1PUs3KtMCqG4bFLceVNG62L3RN53NS95uSCNXpgvzs,181
|
|
2
|
-
mrok/conf.py,sha256=
|
|
3
|
-
mrok/constants.py,sha256=
|
|
2
|
+
mrok/conf.py,sha256=5AgRgwE_Yq0Dv7xDv0SWakhPSr3nnUNjIIgnn0Zgf9c,1057
|
|
3
|
+
mrok/constants.py,sha256=QXaMw4LuHijj_TUTCsM5uUjpgT04HBvd0wRbjvn1z9A,449
|
|
4
4
|
mrok/errors.py,sha256=ruNMDFr2_0ezCGXuCG1OswCEv-bHOIzMMd02J_0ABcs,37
|
|
5
|
-
mrok/logging.py,sha256=
|
|
5
|
+
mrok/logging.py,sha256=PS_x0uAQDsIPF_tbF11fIyijwLS03DQwJzzUHMdVdnE,3000
|
|
6
6
|
mrok/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
mrok/agent/ziticorn.py,sha256=eHUYs9QaSp35rBzYHRV-SrYxF5ySyECaQg7U-XbdINE,1025
|
|
8
8
|
mrok/agent/devtools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
mrok/agent/devtools/__main__.py,sha256=R8ezbW7hCik5r45U3w2TgiTubg9SlbVsWA-bapILJXU,781
|
|
10
9
|
mrok/agent/devtools/inspector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
mrok/agent/devtools/inspector/__main__.py,sha256=
|
|
12
|
-
mrok/agent/devtools/inspector/app.py,sha256=
|
|
10
|
+
mrok/agent/devtools/inspector/__main__.py,sha256=vof04S9fwiU8lGjt7YiM6O9YOXEW_lT1AxGoXyF4bg8,97
|
|
11
|
+
mrok/agent/devtools/inspector/app.py,sha256=TxBBIy8lXHj6h8KmQHCeLiIM2QqMzMsCpSWFjH8cGu4,25636
|
|
13
12
|
mrok/agent/devtools/inspector/server.py,sha256=C4uD6_1psSHMjJLUDCMPGvKdQYKaEwYTw27NAbwuuA0,636
|
|
13
|
+
mrok/agent/devtools/inspector/utils.py,sha256=K-_4rTyB54Y0faEIGgutMEHGyP1W7eOhbcuUKxNnsYA,4261
|
|
14
14
|
mrok/agent/sidecar/__init__.py,sha256=DrjJGhqFyxsVODW06KI20Wpr6HsD2lD6qFCKUXc7GIE,59
|
|
15
15
|
mrok/agent/sidecar/app.py,sha256=sPQqjnwETRQk0cj8hAxSVUDCkYqsVZCS6ixEqkcGY5A,2534
|
|
16
16
|
mrok/agent/sidecar/main.py,sha256=jeJzrCbltfXOYsKSCjcw8h5lxh4_bGT87kCC5dV4kYU,2190
|
|
17
17
|
mrok/cli/__init__.py,sha256=mtFEa8IeS1x6Gm4dUYoSnAxyEzNqbUVSmWxtuZUMR84,61
|
|
18
|
-
mrok/cli/main.py,sha256=
|
|
18
|
+
mrok/cli/main.py,sha256=T029FYxK_jDrwiA14oX-Onoqp_X14XHRAA_4bbaOgV8,3123
|
|
19
19
|
mrok/cli/rich.py,sha256=P3Dyu8EArUR9_0j7DPK7LRx85TWdYdZ1SaJzD_S1ZCE,511
|
|
20
|
-
mrok/cli/utils.py,sha256=
|
|
20
|
+
mrok/cli/utils.py,sha256=FXqyNef0cRFy_d-63ZY-kT3uqmDOK3USSNgBSZyKXIE,831
|
|
21
21
|
mrok/cli/commands/__init__.py,sha256=-UOGzh38oWX7fPeI2nc5I9z8LylRdQAt868q4G6rNGk,140
|
|
22
22
|
mrok/cli/commands/admin/__init__.py,sha256=WU49jpMF9p18UONjYywWEFzjF57zLpLKJ0qAZvrzcR4,414
|
|
23
|
-
mrok/cli/commands/admin/bootstrap.py,sha256=
|
|
23
|
+
mrok/cli/commands/admin/bootstrap.py,sha256=McIGngjpRQSsI2CqW_LBTF1lBeGXvTbbt31jYS35xIY,1705
|
|
24
24
|
mrok/cli/commands/admin/utils.py,sha256=Z7YTAFZKOi6nkw2oX4rJoGoUD41RYL3AOqEDhlV3jR0,1357
|
|
25
25
|
mrok/cli/commands/admin/list/__init__.py,sha256=kjCMcpn1gopcrQaaHxfFh8Kyngldepnle8R2br5dJ_0,195
|
|
26
26
|
mrok/cli/commands/admin/list/extensions.py,sha256=16fhDB5ucL8su2WQnSaQ1E6MhgC4vkP9-nuHAcPpzyE,4405
|
|
27
27
|
mrok/cli/commands/admin/list/instances.py,sha256=kaqeyidwUxgYqfaHXqp2m76rm5h2ErBsYyZcNeaBRwY,5912
|
|
28
28
|
mrok/cli/commands/admin/register/__init__.py,sha256=5Jb_bc2L47MEpQIrOcquzduTFWQ01Jd1U1MpqaR-Ekw,209
|
|
29
|
-
mrok/cli/commands/admin/register/extensions.py,sha256=
|
|
30
|
-
mrok/cli/commands/admin/register/instances.py,sha256=
|
|
29
|
+
mrok/cli/commands/admin/register/extensions.py,sha256=3ooHR-zfFImtqAZ-06kS0555v9gQLQ1G5-ARe_mJ9e4,1353
|
|
30
|
+
mrok/cli/commands/admin/register/instances.py,sha256=KjyLJX1mSXK-6ZmkW9I4PJFYNfgsOyAmJWh92XxSkYg,1982
|
|
31
31
|
mrok/cli/commands/admin/unregister/__init__.py,sha256=-GjjCPX1pISbWmJK6GpKO3ijGsDQb21URjU1hNu99O4,215
|
|
32
|
-
mrok/cli/commands/admin/unregister/extensions.py,sha256=
|
|
33
|
-
mrok/cli/commands/admin/unregister/instances.py,sha256
|
|
32
|
+
mrok/cli/commands/admin/unregister/extensions.py,sha256=xL2yX0kn8dhitQL7NcLTn83bbPZfgPJNzHjZAdiP8yM,891
|
|
33
|
+
mrok/cli/commands/admin/unregister/instances.py,sha256=sLBfBhHDgR7Qw5Zc-EVOSuQUgfLMgh7cFnOP-73iM70,1167
|
|
34
34
|
mrok/cli/commands/agent/__init__.py,sha256=ZAi7eTkKQtfwwV1c1mv3uvEEsyMMrhCQ_-id_0wksAQ,218
|
|
35
|
-
mrok/cli/commands/agent/utils.py,sha256=m_olScdIUGks5IoC6p2F9D6CQIucWZ7LHyrvwm2bkJw,106
|
|
36
35
|
mrok/cli/commands/agent/dev/__init__.py,sha256=ZfreyRuaLqO0AwPS8Ll1DIpsKacsu7_dTmbxV5QecOM,172
|
|
37
36
|
mrok/cli/commands/agent/dev/console.py,sha256=rrKAGoKXVQQBOC75H0JSuX1sYyvc2QSrV-dfMPK49p4,673
|
|
38
37
|
mrok/cli/commands/agent/dev/web.py,sha256=O9dYk-o1FV2E_sKLOezdEmLsnexwbJNDdsYL5pATZRQ,1028
|
|
39
38
|
mrok/cli/commands/agent/run/__init__.py,sha256=E_IJCl3BfMffqFASe8gzJwhhQgt5bQfjhuyekVwdEBA,164
|
|
40
|
-
mrok/cli/commands/agent/run/asgi.py,sha256=
|
|
39
|
+
mrok/cli/commands/agent/run/asgi.py,sha256=FzM3suWJPRqQ08SoDrF9mLfjiBJ6huSbfP3wkTbh3Uo,2054
|
|
41
40
|
mrok/cli/commands/agent/run/sidecar.py,sha256=UOewegTLFwAZ70VFJb6_9kV0LmsvnXuq-yqgrMlTeZo,4182
|
|
42
41
|
mrok/cli/commands/controller/__init__.py,sha256=2xw-YVN0akiLiuGUU3XbYyZZ0ugOjQ6XhtTkzEKSmMA,161
|
|
43
42
|
mrok/cli/commands/controller/openapi.py,sha256=QLjVao9UkB2vBaGkFi_q_jrlg4Np4ldMRwDIJsrJ7A8,1175
|
|
44
43
|
mrok/cli/commands/controller/run.py,sha256=yl1p7oRHhQINWWjUKlRHtMIWUCV0KsxYdyVyazhX834,2406
|
|
45
44
|
mrok/cli/commands/frontend/__init__.py,sha256=0kK37yG6qs7yAa8TYlKZUA-nHrWsO4y5CjbVkXafnuk,123
|
|
46
|
-
mrok/cli/commands/frontend/run.py,sha256=
|
|
45
|
+
mrok/cli/commands/frontend/run.py,sha256=E6vJC9LprGyPetGLfyfJm8GDemEIRVnqetao4V3W9Kk,2796
|
|
47
46
|
mrok/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
-
mrok/controller/app.py,sha256=
|
|
49
|
-
mrok/controller/auth.py,sha256=hYa0OPJ5X0beGxRP6qbxwJOVXj5TmzHjmam2OjTBKn4,2704
|
|
47
|
+
mrok/controller/app.py,sha256=JgyfEFbQeGLpHCrjFKQjdP8TRfV4YVec7Re8i0P4FE8,2040
|
|
50
48
|
mrok/controller/pagination.py,sha256=raYpYa34q8Ckl4BXBOEdpWlKkFj6z7e6QLWr2HT7dzI,2187
|
|
51
49
|
mrok/controller/schemas.py,sha256=PZPEsSJNrGSuplfjCPF_E-VJ721AzgR1Jj8P-Shw1cg,1699
|
|
50
|
+
mrok/controller/auth/__init__.py,sha256=st0q-NHQEQwYlvLEnQdonMVsDmczeL5cS4hkVK7NT6s,412
|
|
51
|
+
mrok/controller/auth/backends.py,sha256=xwiF7qFHh5okhqbTld4P2jSnFkSPZlGR4gfQu598Xrg,2288
|
|
52
|
+
mrok/controller/auth/base.py,sha256=NWEVtc9Y8I56NnyYrBiNzxHZxFSzVEbmkMY2u6RCANs,1131
|
|
53
|
+
mrok/controller/auth/manager.py,sha256=VQwov4UiAOXHBl_a9oPG90_QKRMNz2tWONF3JFR5RmM,1118
|
|
54
|
+
mrok/controller/auth/registry.py,sha256=VmwPPI6E2-oyB2MZDkK_G39EaAeU3Uq-b14GGKz1E-A,485
|
|
52
55
|
mrok/controller/dependencies/__init__.py,sha256=voewk6gjkA0OarL6HFmfT_RLqBns0Fpl-VIqK5xVAEI,202
|
|
53
56
|
mrok/controller/dependencies/conf.py,sha256=2Pa8fxJHkZ29q6UL-w6hUP_wr7WnNELfw5LlzWg1Tec,162
|
|
54
57
|
mrok/controller/dependencies/ziti.py,sha256=fYoxeJb4s6p2_3gxbExbFSRabjpvp_gZMBb3ocXZV3Y,702
|
|
@@ -59,36 +62,36 @@ mrok/controller/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
59
62
|
mrok/controller/routes/extensions.py,sha256=zoY4sNz_BIZcbly6WXM7Rbpn2jmB89njS_0xdJkoKfs,9192
|
|
60
63
|
mrok/controller/routes/instances.py,sha256=v-fn_F6JHbDZ4YUNCIZzClgHp6aC1Eu5HB7k7qBG5pk,2202
|
|
61
64
|
mrok/frontend/__init__.py,sha256=SN3LoFwAye18lfJ8OKNNS-7kLc2A9OxPGIEIEYYtAOA,54
|
|
62
|
-
mrok/frontend/app.py,sha256=
|
|
63
|
-
mrok/frontend/main.py,sha256=
|
|
65
|
+
mrok/frontend/app.py,sha256=_FLz5fqZdlFc1tdBBMwhmvjGa0UnNeaNj6EnYEnuPAQ,5280
|
|
66
|
+
mrok/frontend/main.py,sha256=zvfCh7NDx-mkpN-ppM2AqWmgKn1cBrNOCky8UgjLou4,1833
|
|
67
|
+
mrok/frontend/middleware.py,sha256=xTXt5gYikr9RCXaI4uVKgxFhlH49RNY3MD3eZPcX9cc,1161
|
|
68
|
+
mrok/frontend/utils.py,sha256=Oh987pCpg7ZIIIpRWcpX7Nrh8FGbJ4cH4ciiG1xRoQI,2120
|
|
64
69
|
mrok/proxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
65
|
-
mrok/proxy/app.py,sha256=
|
|
70
|
+
mrok/proxy/app.py,sha256=HU-YRKA3ijY2AW9v-NwfUnbSgdI-XqsnkQ90TocZ1Ts,6257
|
|
66
71
|
mrok/proxy/asgi.py,sha256=2uw5bLquyUsiYlNwq8RhJd8OqVvSJDvYjzOVGLLB3Cs,3528
|
|
67
72
|
mrok/proxy/backend.py,sha256=dRmIUJin2DM3PUxrVX0j4t1oB6DOX7N9JV2lIcopE38,1649
|
|
68
|
-
mrok/proxy/constants.py,sha256=ao5gI2HFBWmrdd2Yc6XFK_RGaHk-omxI4AqvfIiGes8,409
|
|
69
73
|
mrok/proxy/event_publisher.py,sha256=TAuwEqIhRYxgazJFgC3DekwUAXlJ2UFjbdx_A9vwA1g,2511
|
|
70
74
|
mrok/proxy/exceptions.py,sha256=61OhdihQNdnBUqAI9mbBkXD1yWg-6Eftk7EhWCU1VF0,642
|
|
71
75
|
mrok/proxy/master.py,sha256=HB2q_nPLim23z0mGDGKs_RshhGVAO8VgOYP4hA__zC4,6891
|
|
72
76
|
mrok/proxy/metrics.py,sha256=Sg2aIiaj9fzkyu190YCsJvNn5P-XLun3BcvuVBsdWbA,3640
|
|
73
|
-
mrok/proxy/middleware.py,sha256=
|
|
74
|
-
mrok/proxy/models.py,sha256=
|
|
77
|
+
mrok/proxy/middleware.py,sha256=So024RvtNgMliClKz4pzau2Wb6tlfZGspmHBzzEeF4U,4208
|
|
78
|
+
mrok/proxy/models.py,sha256=VDou3LGDi9zCpzpOwihP4Og1oRvXl7gb2mgczf6_Z14,6029
|
|
75
79
|
mrok/proxy/stream.py,sha256=7V-bSAF9uNV1yVHKaEhHo95WxafSGWkyHPVABZX0djY,2134
|
|
76
|
-
mrok/proxy/utils.py,sha256=OxX6pJv_Wh_KgWx95YeJ3YeuSgwm2tsd00897P3fxys,2126
|
|
77
80
|
mrok/proxy/worker.py,sha256=uEUC2Hbx0YQiDMFNZfwkHMDnijN96b6iRoIErfI21Tg,1921
|
|
78
|
-
mrok/proxy/ziticorn.py,sha256=
|
|
81
|
+
mrok/proxy/ziticorn.py,sha256=qiHKIB7ZRR9S9f-zXTxkzBWW3qlP9CqPOc0QQr-lgvc,2437
|
|
79
82
|
mrok/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
83
|
mrok/types/proxy.py,sha256=40Yds4tUykMpzsoQbMtHG85r8xtm5Q3fQZ17bp7cDiM,818
|
|
81
84
|
mrok/types/ziti.py,sha256=EeQnTbDEJ-Y-KMS6zu1Xjxb58Up2VxUwqzUwy3H28JY,36
|
|
82
85
|
mrok/ziti/__init__.py,sha256=20OWMiexRhOovZOX19zlX87-V78QyWnEnSZfyAftUdE,263
|
|
83
|
-
mrok/ziti/api.py,sha256=
|
|
84
|
-
mrok/ziti/bootstrap.py,sha256=
|
|
86
|
+
mrok/ziti/api.py,sha256=Z6Hs17-UaKtcRc6uMowhvQW5fbyW6wFr-7lAvI3aZm0,16125
|
|
87
|
+
mrok/ziti/bootstrap.py,sha256=RSL8nZfI-MZ_z6h0F-rNevQoE6g9oGKLr6HlZF696_c,2499
|
|
85
88
|
mrok/ziti/constants.py,sha256=Urq1X3bCBQZfw8NbnEa1pqmY4oq1wmzkwPfzam3kbTw,339
|
|
86
89
|
mrok/ziti/errors.py,sha256=yYCbVDwktnR0AYduqtynIjo73K3HOhIrwA_vQimvEd4,368
|
|
87
|
-
mrok/ziti/identities.py,sha256=
|
|
90
|
+
mrok/ziti/identities.py,sha256=cOMv-Jv8MEjtzyjRcWOF8Ziz4HJY2Z-uHXWpZRqgPxs,6883
|
|
88
91
|
mrok/ziti/pki.py,sha256=o2tySqHC8-7bvFuI2Tqxg9vX6H6ZSxWxfP_9x29e19M,1954
|
|
89
|
-
mrok/ziti/services.py,sha256=
|
|
90
|
-
mrok-0.
|
|
91
|
-
mrok-0.
|
|
92
|
-
mrok-0.
|
|
93
|
-
mrok-0.
|
|
94
|
-
mrok-0.
|
|
92
|
+
mrok/ziti/services.py,sha256=P2c9qRUyUFu1pSKPdT8L6s3yTKYVpTabRiHPWqbBIiU,3231
|
|
93
|
+
mrok-0.8.0.dist-info/METADATA,sha256=SmmFB0ZpkWORFIvUKENkpOszVnFjgqVZS6p7rbPyIwc,15978
|
|
94
|
+
mrok-0.8.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
95
|
+
mrok-0.8.0.dist-info/entry_points.txt,sha256=tloXwvU1uJicBJR2h-8HoVclPgwJWDwuREMHN8Zq-nU,38
|
|
96
|
+
mrok-0.8.0.dist-info/licenses/LICENSE.txt,sha256=6PaICaoA3yNsZKLv5G6OKqSfLSoX7MakYqTDgJoTCBs,11346
|
|
97
|
+
mrok-0.8.0.dist-info/RECORD,,
|
mrok/agent/devtools/__main__.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""mrok agent devtools CLI entrypoint.
|
|
3
|
-
|
|
4
|
-
Provides a small CLI that accepts an optional subscriber port and
|
|
5
|
-
invokes the `run` function with that port.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import argparse
|
|
9
|
-
from typing import Any
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def run(port: int) -> None:
|
|
13
|
-
"""Run the devtools agent using the given subscriber port.
|
|
14
|
-
|
|
15
|
-
This is a stub for the runtime function. Implementation goes here.
|
|
16
|
-
"""
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def main(argv: Any = None) -> None:
|
|
21
|
-
parser = argparse.ArgumentParser(description="mrok devtools agent")
|
|
22
|
-
parser.add_argument(
|
|
23
|
-
"-p",
|
|
24
|
-
"--subscriber-port",
|
|
25
|
-
type=int,
|
|
26
|
-
default=50001,
|
|
27
|
-
help="Port for subscriber (default: 50001)",
|
|
28
|
-
)
|
|
29
|
-
args = parser.parse_args(argv)
|
|
30
|
-
run(args.subscriber_port)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if __name__ == "__main__":
|
|
34
|
-
main()
|
mrok/cli/commands/agent/utils.py
DELETED
mrok/controller/auth.py
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import Annotated
|
|
3
|
-
|
|
4
|
-
import httpx
|
|
5
|
-
import jwt
|
|
6
|
-
from fastapi import Depends, HTTPException, Request, status
|
|
7
|
-
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
8
|
-
|
|
9
|
-
from mrok.controller.dependencies.conf import AppSettings
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger("mrok.controller")
|
|
12
|
-
|
|
13
|
-
UNAUTHORIZED_EXCEPTION = HTTPException(
|
|
14
|
-
status_code=status.HTTP_401_UNAUTHORIZED, detail="Unauthorized."
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class JWTCredentials(HTTPAuthorizationCredentials):
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class JWTBearer(HTTPBearer):
|
|
23
|
-
def __init__(self):
|
|
24
|
-
super().__init__(auto_error=False)
|
|
25
|
-
|
|
26
|
-
async def __call__(self, request: Request) -> JWTCredentials:
|
|
27
|
-
credentials = await super().__call__(request)
|
|
28
|
-
if not credentials:
|
|
29
|
-
raise UNAUTHORIZED_EXCEPTION
|
|
30
|
-
try:
|
|
31
|
-
return JWTCredentials(
|
|
32
|
-
scheme=credentials.scheme,
|
|
33
|
-
credentials=credentials.credentials,
|
|
34
|
-
)
|
|
35
|
-
except jwt.InvalidTokenError:
|
|
36
|
-
raise UNAUTHORIZED_EXCEPTION
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
async def authenticate(
|
|
40
|
-
settings: AppSettings,
|
|
41
|
-
credentials: Annotated[JWTCredentials, Depends(JWTBearer())],
|
|
42
|
-
):
|
|
43
|
-
async with httpx.AsyncClient(
|
|
44
|
-
timeout=httpx.Timeout(
|
|
45
|
-
connect=0.25,
|
|
46
|
-
read=settings.auth.read_timeout,
|
|
47
|
-
write=2.0,
|
|
48
|
-
pool=5.0,
|
|
49
|
-
),
|
|
50
|
-
) as client:
|
|
51
|
-
try:
|
|
52
|
-
config_resp = await client.get(settings.auth.openid_config_url)
|
|
53
|
-
config_resp.raise_for_status()
|
|
54
|
-
config = config_resp.json()
|
|
55
|
-
issuer = config["issuer"]
|
|
56
|
-
jwks_uri = config["jwks_uri"]
|
|
57
|
-
|
|
58
|
-
jwks_resp = await client.get(jwks_uri)
|
|
59
|
-
jwks_resp.raise_for_status()
|
|
60
|
-
jwks = jwks_resp.json()
|
|
61
|
-
|
|
62
|
-
header = jwt.get_unverified_header(credentials.credentials)
|
|
63
|
-
kid = header["kid"]
|
|
64
|
-
|
|
65
|
-
key_data = next((k for k in jwks["keys"] if k["kid"] == kid), None)
|
|
66
|
-
except Exception:
|
|
67
|
-
logger.exception("Error fetching openid-config/jwks")
|
|
68
|
-
raise UNAUTHORIZED_EXCEPTION
|
|
69
|
-
if key_data is None:
|
|
70
|
-
logger.error("Key ID not found in JWKS")
|
|
71
|
-
raise UNAUTHORIZED_EXCEPTION
|
|
72
|
-
|
|
73
|
-
try:
|
|
74
|
-
payload = jwt.decode(
|
|
75
|
-
credentials.credentials,
|
|
76
|
-
jwt.PyJWK(key_data),
|
|
77
|
-
algorithms=[header["alg"]],
|
|
78
|
-
issuer=issuer,
|
|
79
|
-
audience=settings.auth.audience,
|
|
80
|
-
)
|
|
81
|
-
return payload
|
|
82
|
-
except jwt.InvalidKeyError as e:
|
|
83
|
-
logger.error(f"Invalid jwt token: {e} ({credentials.credentials})")
|
|
84
|
-
raise UNAUTHORIZED_EXCEPTION
|
|
85
|
-
except jwt.InvalidTokenError as e:
|
|
86
|
-
logger.error(f"Invalid jwt token: {e} ({credentials.credentials})")
|
|
87
|
-
raise UNAUTHORIZED_EXCEPTION
|
mrok/proxy/constants.py
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
MAX_REQUEST_BODY_BYTES = 2 * 1024 * 1024
|
|
2
|
-
MAX_RESPONSE_BODY_BYTES = 5 * 1024 * 1024
|
|
3
|
-
|
|
4
|
-
BINARY_CONTENT_TYPES = {
|
|
5
|
-
"application/octet-stream",
|
|
6
|
-
"application/pdf",
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
BINARY_PREFIXES = (
|
|
10
|
-
"image/",
|
|
11
|
-
"video/",
|
|
12
|
-
"audio/",
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
TEXTUAL_CONTENT_TYPES = {
|
|
16
|
-
"application/json",
|
|
17
|
-
"application/xml",
|
|
18
|
-
"application/javascript",
|
|
19
|
-
"application/x-www-form-urlencoded",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
TEXTUAL_PREFIXES = ("text/",)
|
mrok/proxy/utils.py
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
from collections.abc import Mapping
|
|
2
|
-
|
|
3
|
-
from mrok.proxy.constants import (
|
|
4
|
-
BINARY_CONTENT_TYPES,
|
|
5
|
-
BINARY_PREFIXES,
|
|
6
|
-
MAX_REQUEST_BODY_BYTES,
|
|
7
|
-
MAX_RESPONSE_BODY_BYTES,
|
|
8
|
-
TEXTUAL_CONTENT_TYPES,
|
|
9
|
-
TEXTUAL_PREFIXES,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def is_binary(content_type: str) -> bool:
|
|
14
|
-
ct = content_type.lower()
|
|
15
|
-
if ct in BINARY_CONTENT_TYPES:
|
|
16
|
-
return True
|
|
17
|
-
if any(ct.startswith(p) for p in BINARY_PREFIXES):
|
|
18
|
-
return True
|
|
19
|
-
return False
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def is_textual(content_type: str) -> bool:
|
|
23
|
-
ct = content_type.lower()
|
|
24
|
-
if ct in TEXTUAL_CONTENT_TYPES:
|
|
25
|
-
return True
|
|
26
|
-
if any(ct.startswith(p) for p in TEXTUAL_PREFIXES):
|
|
27
|
-
return True
|
|
28
|
-
return False
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def must_capture_request(
|
|
32
|
-
method: str,
|
|
33
|
-
headers: Mapping,
|
|
34
|
-
) -> bool:
|
|
35
|
-
method = method.upper()
|
|
36
|
-
|
|
37
|
-
# No body expected
|
|
38
|
-
if method in ("GET", "HEAD", "OPTIONS", "TRACE"):
|
|
39
|
-
return False
|
|
40
|
-
|
|
41
|
-
content_type = headers.get("content-type", "").lower()
|
|
42
|
-
|
|
43
|
-
content_length = None
|
|
44
|
-
if "content-length" in headers:
|
|
45
|
-
content_length = int(headers["content-length"])
|
|
46
|
-
|
|
47
|
-
if is_binary(content_type):
|
|
48
|
-
return False
|
|
49
|
-
|
|
50
|
-
if content_type.startswith("multipart/form-data"):
|
|
51
|
-
return False
|
|
52
|
-
|
|
53
|
-
if content_length is not None and content_length > MAX_REQUEST_BODY_BYTES:
|
|
54
|
-
return False
|
|
55
|
-
|
|
56
|
-
if is_textual(content_type):
|
|
57
|
-
return True
|
|
58
|
-
|
|
59
|
-
if content_length is None:
|
|
60
|
-
return True
|
|
61
|
-
|
|
62
|
-
return content_length <= MAX_REQUEST_BODY_BYTES
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def must_capture_response(
|
|
66
|
-
headers: Mapping,
|
|
67
|
-
) -> bool:
|
|
68
|
-
content_type = headers.get("content-type", "").lower()
|
|
69
|
-
disposition = headers.get("content-disposition", "").lower()
|
|
70
|
-
|
|
71
|
-
content_length = None
|
|
72
|
-
if "content-length" in headers:
|
|
73
|
-
content_length = int(headers["content-length"])
|
|
74
|
-
|
|
75
|
-
if "attachment" in disposition:
|
|
76
|
-
return False
|
|
77
|
-
|
|
78
|
-
if is_binary(content_type):
|
|
79
|
-
return False
|
|
80
|
-
|
|
81
|
-
if content_length is not None and content_length > MAX_RESPONSE_BODY_BYTES:
|
|
82
|
-
return False
|
|
83
|
-
|
|
84
|
-
if is_textual(content_type):
|
|
85
|
-
return True
|
|
86
|
-
|
|
87
|
-
if content_length is None:
|
|
88
|
-
return True
|
|
89
|
-
|
|
90
|
-
return content_length <= MAX_RESPONSE_BODY_BYTES
|
|
File without changes
|
|
File without changes
|
|
File without changes
|