mrok 0.1.9__tar.gz → 0.2.1__tar.gz
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-0.1.9 → mrok-0.2.1}/PKG-INFO +2 -1
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/app.py +3 -1
- mrok-0.2.1/mrok/controller/routes/instances.py +71 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/pki.py +10 -5
- {mrok-0.1.9 → mrok-0.2.1}/pyproject.toml +2 -1
- mrok-0.1.9/tests/controller/test_instances.py → mrok-0.2.1/tests/controller/test_extensions.py +228 -10
- mrok-0.2.1/tests/controller/test_instances.py +157 -0
- mrok-0.2.1/tests/ziti/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/uv.lock +11 -0
- mrok-0.1.9/tests/controller/test_extensions.py +0 -221
- {mrok-0.1.9 → mrok-0.2.1}/.github/actions/setup-python-env/action.yml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.github/workflows/assets/turing_team_pr_bot.png +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.github/workflows/notify-pr-closed.yaml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.github/workflows/notify-pr-reviewed.yml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.github/workflows/pr-build-merge.yaml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.github/workflows/release.yml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.gitignore +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.pre-commit-config.yaml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/.python-version +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/LICENSE.txt +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/README.md +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/dev.Dockerfile +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/docker-compose.yaml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/entrypoint.sh +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/agent/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/agent/sidecar/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/agent/sidecar/app.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/agent/sidecar/main.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/agent/ziticorn.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/bootstrap.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/list/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/list/extensions.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/list/instances.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/register/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/register/extensions.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/register/instances.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/unregister/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/unregister/extensions.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/unregister/instances.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/admin/utils.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/agent/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/agent/run/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/agent/run/asgi.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/agent/run/sidecar.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/controller/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/controller/openapi.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/commands/controller/run.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/main.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/cli/rich.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/conf.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/auth.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/dependencies/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/dependencies/conf.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/dependencies/ziti.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/openapi/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/openapi/examples.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/openapi/utils.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/pagination.py +0 -0
- {mrok-0.1.9/mrok/http → mrok-0.2.1/mrok/controller/routes}/__init__.py +0 -0
- /mrok-0.1.9/mrok/controller/routes.py → /mrok-0.2.1/mrok/controller/routes/extensions.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/controller/schemas.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/errors.py +0 -0
- {mrok-0.1.9/tests → mrok-0.2.1/mrok/http}/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/http/config.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/http/forwarder.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/http/lifespan.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/http/master.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/http/protocol.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/http/server.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/logging.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/api.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/bootstrap.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/constants.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/errors.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/identities.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/mrok/ziti/services.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/prod.Dockerfile +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/scripts/ziti.sh +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/settings.yaml +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/sonar-project.properties +0 -0
- {mrok-0.1.9/tests/agent → mrok-0.2.1/tests}/__init__.py +0 -0
- {mrok-0.1.9/tests/agent/sidecar → mrok-0.2.1/tests/agent}/__init__.py +0 -0
- {mrok-0.1.9/tests/cli → mrok-0.2.1/tests/agent/sidecar}/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/agent/sidecar/test_app.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/agent/sidecar/test_main.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/agent/test_ziticorn.py +0 -0
- {mrok-0.1.9/tests/cli/admin → mrok-0.2.1/tests/cli}/__init__.py +0 -0
- {mrok-0.1.9/tests/cli/agent → mrok-0.2.1/tests/cli/admin}/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/admin/test_bootstrap.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/admin/test_list.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/admin/test_register.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/admin/test_unregister.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/admin/test_utils.py +0 -0
- {mrok-0.1.9/tests/cli/controller → mrok-0.2.1/tests/cli/agent}/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/agent/test_run.py +0 -0
- {mrok-0.1.9/tests → mrok-0.2.1/tests/cli}/controller/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/controller/test_openapi.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/controller/test_run.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/cli/test_main.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/conftest.py +0 -0
- {mrok-0.1.9/tests/http → mrok-0.2.1/tests/controller}/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/controller/test_auth.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/controller/test_openapi.py +0 -0
- {mrok-0.1.9/tests/ziti → mrok-0.2.1/tests/http}/__init__.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/http/test_config.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/http/test_forwarder.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/http/test_lifespan.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/http/test_master.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/http/test_protocol.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/http/test_server.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/ziti/test_api.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/ziti/test_bootstrap.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/ziti/test_identities.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/ziti/test_pki.py +0 -0
- {mrok-0.1.9 → mrok-0.2.1}/tests/ziti/test_services.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mrok
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
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
|
|
@@ -8,7 +8,8 @@ from fastapi.routing import APIRoute, APIRouter
|
|
|
8
8
|
from mrok.conf import get_settings
|
|
9
9
|
from mrok.controller.auth import authenticate
|
|
10
10
|
from mrok.controller.openapi import generate_openapi_spec
|
|
11
|
-
from mrok.controller.routes import router as extensions_router
|
|
11
|
+
from mrok.controller.routes.extensions import router as extensions_router
|
|
12
|
+
from mrok.controller.routes.instances import router as instances_router
|
|
12
13
|
|
|
13
14
|
logger = logging.getLogger(__name__)
|
|
14
15
|
|
|
@@ -52,6 +53,7 @@ def setup_app():
|
|
|
52
53
|
app.include_router(
|
|
53
54
|
extensions_router, prefix="/extensions", dependencies=[Depends(authenticate)]
|
|
54
55
|
)
|
|
56
|
+
app.include_router(instances_router, prefix="/instances", dependencies=[Depends(authenticate)])
|
|
55
57
|
|
|
56
58
|
settings = get_settings()
|
|
57
59
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, HTTPException, status
|
|
4
|
+
|
|
5
|
+
from mrok.controller.dependencies import ZitiManagementAPI
|
|
6
|
+
from mrok.controller.openapi import examples
|
|
7
|
+
from mrok.controller.pagination import LimitOffsetPage, paginate
|
|
8
|
+
from mrok.controller.schemas import InstanceRead
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger("mrok.controller")
|
|
11
|
+
|
|
12
|
+
router = APIRouter()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def fetch_instance_or_404(mgmt_api: ZitiManagementAPI, id_or_instance_id: str):
|
|
16
|
+
identity = await mgmt_api.search_identity(id_or_instance_id)
|
|
17
|
+
if not identity:
|
|
18
|
+
raise HTTPException(
|
|
19
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
20
|
+
)
|
|
21
|
+
return identity
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@router.get(
|
|
25
|
+
"/{id_or_instance_id}",
|
|
26
|
+
response_model=InstanceRead,
|
|
27
|
+
responses={
|
|
28
|
+
200: {
|
|
29
|
+
"description": "Instance",
|
|
30
|
+
"content": {"application/json": {"example": examples.INSTANCE_RESPONSE}},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
dependencies=[],
|
|
34
|
+
tags=["Instances"],
|
|
35
|
+
)
|
|
36
|
+
async def get_instance_by_id_or_instance_id(
|
|
37
|
+
mgmt_api: ZitiManagementAPI,
|
|
38
|
+
id_or_instance_id: str,
|
|
39
|
+
):
|
|
40
|
+
identity = await fetch_instance_or_404(mgmt_api, id_or_instance_id)
|
|
41
|
+
return InstanceRead(**identity)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@router.get(
|
|
45
|
+
"",
|
|
46
|
+
response_model=LimitOffsetPage[InstanceRead],
|
|
47
|
+
responses={
|
|
48
|
+
200: {
|
|
49
|
+
"description": "List of Instances",
|
|
50
|
+
"content": {
|
|
51
|
+
"application/json": {
|
|
52
|
+
"example": {
|
|
53
|
+
"data": [examples.INSTANCE_RESPONSE],
|
|
54
|
+
"$meta": {
|
|
55
|
+
"pagination": {
|
|
56
|
+
"total": 1,
|
|
57
|
+
"limit": 10,
|
|
58
|
+
"offset": 0,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
tags=["Instances"],
|
|
67
|
+
)
|
|
68
|
+
async def get_instances(
|
|
69
|
+
mgmt_api: ZitiManagementAPI,
|
|
70
|
+
):
|
|
71
|
+
return await paginate(mgmt_api, "/identities", InstanceRead)
|
|
@@ -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
|
[project]
|
|
2
2
|
name = "mrok"
|
|
3
|
-
version = "0.1
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "MPT Extensions OpenZiti Orchestrator"
|
|
5
5
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
6
6
|
authors = [
|
|
@@ -9,6 +9,7 @@ authors = [
|
|
|
9
9
|
license = { file = "LICENSE.txt" }
|
|
10
10
|
requires-python = ">=3.12,<4"
|
|
11
11
|
dependencies = [
|
|
12
|
+
"asn1crypto>=1.5.1,<2.0.0",
|
|
12
13
|
"cryptography>=45.0.7,<46.0.0",
|
|
13
14
|
"dynaconf>=3.2.11,<4.0.0",
|
|
14
15
|
"fastapi-pagination>=0.14.1,<0.15.0",
|
mrok-0.1.9/tests/controller/test_instances.py → mrok-0.2.1/tests/controller/test_extensions.py
RENAMED
|
@@ -1,15 +1,227 @@
|
|
|
1
1
|
from urllib.parse import quote
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
+
from dynaconf.base import LazySettings
|
|
4
5
|
from httpx import AsyncClient
|
|
5
6
|
from pytest_httpx import HTTPXMock
|
|
6
7
|
from pytest_mock import MockerFixture
|
|
7
8
|
|
|
8
9
|
from mrok.ziti.api import ZitiClientAPI, ZitiManagementAPI
|
|
9
10
|
from mrok.ziti.constants import MROK_SERVICE_TAG_NAME, MROK_VERSION_TAG_NAME
|
|
11
|
+
from mrok.ziti.errors import (
|
|
12
|
+
ConfigTypeNotFoundError,
|
|
13
|
+
MrokError,
|
|
14
|
+
ProxyIdentityNotFoundError,
|
|
15
|
+
ServiceAlreadyRegisteredError,
|
|
16
|
+
ServiceNotFoundError,
|
|
17
|
+
)
|
|
10
18
|
from tests.conftest import SettingsFactory
|
|
11
19
|
|
|
12
20
|
|
|
21
|
+
@pytest.mark.asyncio
|
|
22
|
+
async def test_list_extensions(
|
|
23
|
+
api_client: AsyncClient, settings_factory: SettingsFactory, httpx_mock: HTTPXMock
|
|
24
|
+
):
|
|
25
|
+
settings = settings_factory()
|
|
26
|
+
httpx_mock.add_response(
|
|
27
|
+
method="GET",
|
|
28
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/services?limit=5&offset=0",
|
|
29
|
+
json={
|
|
30
|
+
"meta": {"pagination": {"totalCount": 10, "limit": 5, "offset": 0}},
|
|
31
|
+
"data": [{"id": f"svc{i}", "name": "svc"} for i in range(5)],
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
httpx_mock.add_response(
|
|
35
|
+
method="GET",
|
|
36
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/services?limit=5&offset=5",
|
|
37
|
+
json={
|
|
38
|
+
"meta": {"pagination": {"totalCount": 10, "limit": 5, "offset": 5}},
|
|
39
|
+
"data": [{"id": f"svc{5 + i}", "name": "svc"} for i in range(5)],
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
response = await api_client.get("/extensions?limit=5&offset=0")
|
|
43
|
+
assert response.status_code == 200
|
|
44
|
+
page_1 = response.json()
|
|
45
|
+
assert len(page_1["data"]) == 5
|
|
46
|
+
assert page_1["$meta"]["pagination"]["offset"] == 0
|
|
47
|
+
|
|
48
|
+
response = await api_client.get("/extensions?limit=5&offset=5")
|
|
49
|
+
assert response.status_code == 200
|
|
50
|
+
page_2 = response.json()
|
|
51
|
+
assert len(page_2["data"]) == 5
|
|
52
|
+
assert page_2["$meta"]["pagination"]["offset"] == 5
|
|
53
|
+
|
|
54
|
+
assert sorted(page_1["data"], key=lambda x: x["id"]) != sorted(
|
|
55
|
+
page_2["data"], key=lambda x: x["id"]
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.mark.asyncio
|
|
60
|
+
async def test_register_extension(mocker: MockerFixture, api_client: AsyncClient):
|
|
61
|
+
mocked_register = mocker.patch(
|
|
62
|
+
"mrok.controller.routes.extensions.register_extension",
|
|
63
|
+
return_value={
|
|
64
|
+
"id": "a1b2cd",
|
|
65
|
+
"name": "ext-1234-5678",
|
|
66
|
+
"tags": {
|
|
67
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
68
|
+
"account": "ACC-1234-5678",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
response = await api_client.post(
|
|
74
|
+
"/extensions",
|
|
75
|
+
json={
|
|
76
|
+
"extension": {"id": "EXT-1234-5678"},
|
|
77
|
+
"tags": {"account": "ACC-1234-5678"},
|
|
78
|
+
},
|
|
79
|
+
)
|
|
80
|
+
assert response.status_code == 201
|
|
81
|
+
assert response.json() == {
|
|
82
|
+
"id": "a1b2cd",
|
|
83
|
+
"extension": {"id": "EXT-1234-5678"},
|
|
84
|
+
"name": "ext-1234-5678",
|
|
85
|
+
"tags": {
|
|
86
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
87
|
+
"account": "ACC-1234-5678",
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
assert mocked_register.call_count == 1
|
|
91
|
+
assert isinstance(mocked_register.mock_calls[0].args[0], LazySettings)
|
|
92
|
+
assert isinstance(mocked_register.mock_calls[0].args[1], ZitiManagementAPI)
|
|
93
|
+
assert mocked_register.mock_calls[0].args[2] == "EXT-1234-5678"
|
|
94
|
+
assert mocked_register.mock_calls[0].args[3] == {"account": "ACC-1234-5678"}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.mark.asyncio
|
|
98
|
+
async def test_register_extension_already_exists(mocker: MockerFixture, api_client: AsyncClient):
|
|
99
|
+
mocker.patch(
|
|
100
|
+
"mrok.controller.routes.extensions.register_extension",
|
|
101
|
+
side_effect=ServiceAlreadyRegisteredError("Extension `EXT-1234-5678` already registered."),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
response = await api_client.post(
|
|
105
|
+
"/extensions",
|
|
106
|
+
json={
|
|
107
|
+
"extension": {"id": "EXT-1234-5678"},
|
|
108
|
+
"tags": {"account": "ACC-1234-5678"},
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
assert response.status_code == 400
|
|
112
|
+
assert response.json() == {"detail": "Extension `EXT-1234-5678` already registered."}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@pytest.mark.asyncio
|
|
116
|
+
@pytest.mark.parametrize("exc_type", [ProxyIdentityNotFoundError, ConfigTypeNotFoundError])
|
|
117
|
+
async def test_register_extension_mrok_not_configured(
|
|
118
|
+
mocker: MockerFixture,
|
|
119
|
+
api_client: AsyncClient,
|
|
120
|
+
exc_type: MrokError,
|
|
121
|
+
):
|
|
122
|
+
mocker.patch(
|
|
123
|
+
"mrok.controller.routes.extensions.register_extension",
|
|
124
|
+
side_effect=exc_type("this is the error."), # type: ignore
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
response = await api_client.post(
|
|
128
|
+
"/extensions",
|
|
129
|
+
json={
|
|
130
|
+
"extension": {"id": "EXT-1234-5678"},
|
|
131
|
+
"tags": {"account": "ACC-1234-5678"},
|
|
132
|
+
},
|
|
133
|
+
)
|
|
134
|
+
assert response.status_code == 400
|
|
135
|
+
assert response.json() == {"detail": "OpenZiti not configured properly: this is the error."}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@pytest.mark.asyncio
|
|
139
|
+
async def test_get_extension(
|
|
140
|
+
settings_factory: SettingsFactory,
|
|
141
|
+
api_client: AsyncClient,
|
|
142
|
+
httpx_mock: HTTPXMock,
|
|
143
|
+
):
|
|
144
|
+
settings = settings_factory()
|
|
145
|
+
query = quote(
|
|
146
|
+
f'(id="EXT-1234-5678" or name="ext-1234-5678") and tags.{MROK_VERSION_TAG_NAME} != null'
|
|
147
|
+
)
|
|
148
|
+
httpx_mock.add_response(
|
|
149
|
+
method="GET",
|
|
150
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/services?filter={query}",
|
|
151
|
+
json={
|
|
152
|
+
"meta": {"pagination": {"totalCount": 1}},
|
|
153
|
+
"data": [
|
|
154
|
+
{
|
|
155
|
+
"id": "svc1",
|
|
156
|
+
"name": "ext-1234-5678",
|
|
157
|
+
"tags": {MROK_VERSION_TAG_NAME: "0.0.0.dev0"},
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
response = await api_client.get("/extensions/EXT-1234-5678")
|
|
164
|
+
assert response.status_code == 200
|
|
165
|
+
assert response.json() == {
|
|
166
|
+
"id": "svc1",
|
|
167
|
+
"extension": {"id": "EXT-1234-5678"},
|
|
168
|
+
"name": "ext-1234-5678",
|
|
169
|
+
"tags": {
|
|
170
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@pytest.mark.asyncio
|
|
176
|
+
async def test_get_extension_not_found(
|
|
177
|
+
settings_factory: SettingsFactory,
|
|
178
|
+
api_client: AsyncClient,
|
|
179
|
+
httpx_mock: HTTPXMock,
|
|
180
|
+
):
|
|
181
|
+
settings = settings_factory()
|
|
182
|
+
query = quote(
|
|
183
|
+
f'(id="EXT-1234-5678" or name="ext-1234-5678") and tags.{MROK_VERSION_TAG_NAME} != null'
|
|
184
|
+
)
|
|
185
|
+
httpx_mock.add_response(
|
|
186
|
+
method="GET",
|
|
187
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/services?filter={query}",
|
|
188
|
+
json={
|
|
189
|
+
"meta": {"pagination": {"totalCount": 0}},
|
|
190
|
+
"data": [],
|
|
191
|
+
},
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
response = await api_client.get("/extensions/EXT-1234-5678")
|
|
195
|
+
assert response.status_code == 404
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@pytest.mark.asyncio
|
|
199
|
+
async def test_delete_extension(
|
|
200
|
+
mocker: MockerFixture,
|
|
201
|
+
api_client: AsyncClient,
|
|
202
|
+
):
|
|
203
|
+
mocker.patch(
|
|
204
|
+
"mrok.controller.routes.extensions.unregister_extension",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
response = await api_client.delete("/extensions/EXT-1234-5678")
|
|
208
|
+
assert response.status_code == 204
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@pytest.mark.asyncio
|
|
212
|
+
async def test_delete_extension_not_found(
|
|
213
|
+
mocker: MockerFixture,
|
|
214
|
+
api_client: AsyncClient,
|
|
215
|
+
):
|
|
216
|
+
mocker.patch(
|
|
217
|
+
"mrok.controller.routes.extensions.unregister_extension",
|
|
218
|
+
side_effect=ServiceNotFoundError("not found"),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
response = await api_client.delete("/extensions/EXT-1234-5678")
|
|
222
|
+
assert response.status_code == 404
|
|
223
|
+
|
|
224
|
+
|
|
13
225
|
@pytest.mark.asyncio
|
|
14
226
|
async def test_list_instances(
|
|
15
227
|
mocker: MockerFixture,
|
|
@@ -19,7 +231,8 @@ async def test_list_instances(
|
|
|
19
231
|
):
|
|
20
232
|
settings = settings_factory()
|
|
21
233
|
mocker.patch(
|
|
22
|
-
"mrok.controller.routes.fetch_extension_or_404",
|
|
234
|
+
"mrok.controller.routes.extensions.fetch_extension_or_404",
|
|
235
|
+
return_value={"name": "ext-1234-5678"},
|
|
23
236
|
)
|
|
24
237
|
query = quote(f'tags.{MROK_SERVICE_TAG_NAME} = "ext-1234-5678"')
|
|
25
238
|
httpx_mock.add_response(
|
|
@@ -58,10 +271,11 @@ async def test_list_instances(
|
|
|
58
271
|
@pytest.mark.asyncio
|
|
59
272
|
async def test_register_instance(mocker: MockerFixture, api_client: AsyncClient):
|
|
60
273
|
mocker.patch(
|
|
61
|
-
"mrok.controller.routes.fetch_extension_or_404",
|
|
274
|
+
"mrok.controller.routes.extensions.fetch_extension_or_404",
|
|
275
|
+
return_value={"name": "ext-1234-5678"},
|
|
62
276
|
)
|
|
63
277
|
mocked_register = mocker.patch(
|
|
64
|
-
"mrok.controller.routes.register_instance",
|
|
278
|
+
"mrok.controller.routes.extensions.register_instance",
|
|
65
279
|
return_value=(
|
|
66
280
|
{
|
|
67
281
|
"id": "a1b2cd",
|
|
@@ -114,7 +328,8 @@ async def test_get_instance(
|
|
|
114
328
|
httpx_mock: HTTPXMock,
|
|
115
329
|
):
|
|
116
330
|
mocker.patch(
|
|
117
|
-
"mrok.controller.routes.fetch_extension_or_404",
|
|
331
|
+
"mrok.controller.routes.extensions.fetch_extension_or_404",
|
|
332
|
+
return_value={"name": "ext-1234-5678"},
|
|
118
333
|
)
|
|
119
334
|
settings = settings_factory()
|
|
120
335
|
query = quote(
|
|
@@ -161,7 +376,8 @@ async def test_get_instance_by_instance_id(
|
|
|
161
376
|
httpx_mock: HTTPXMock,
|
|
162
377
|
):
|
|
163
378
|
mocker.patch(
|
|
164
|
-
"mrok.controller.routes.fetch_extension_or_404",
|
|
379
|
+
"mrok.controller.routes.extensions.fetch_extension_or_404",
|
|
380
|
+
return_value={"name": "ext-1234-5678"},
|
|
165
381
|
)
|
|
166
382
|
settings = settings_factory()
|
|
167
383
|
query = quote(f'(id="ins1" or name="ins1") and tags.{MROK_VERSION_TAG_NAME} != null')
|
|
@@ -205,7 +421,8 @@ async def test_get_instance_not_found(
|
|
|
205
421
|
httpx_mock: HTTPXMock,
|
|
206
422
|
):
|
|
207
423
|
mocker.patch(
|
|
208
|
-
"mrok.controller.routes.fetch_extension_or_404",
|
|
424
|
+
"mrok.controller.routes.extensions.fetch_extension_or_404",
|
|
425
|
+
return_value={"name": "ext-1234-5678"},
|
|
209
426
|
)
|
|
210
427
|
settings = settings_factory()
|
|
211
428
|
query = quote(
|
|
@@ -231,11 +448,11 @@ async def test_delete_instance(
|
|
|
231
448
|
api_client: AsyncClient,
|
|
232
449
|
):
|
|
233
450
|
mocker.patch(
|
|
234
|
-
"mrok.controller.routes.fetch_instance_or_404",
|
|
451
|
+
"mrok.controller.routes.extensions.fetch_instance_or_404",
|
|
235
452
|
return_value={"name": "ins-1234-5678.ext-1234-5678"},
|
|
236
453
|
)
|
|
237
454
|
mocker.patch(
|
|
238
|
-
"mrok.controller.routes.unregister_instance",
|
|
455
|
+
"mrok.controller.routes.extensions.unregister_instance",
|
|
239
456
|
)
|
|
240
457
|
|
|
241
458
|
response = await api_client.delete("/extensions/EXT-1234-5678/instances/INS-1234-5678-0001")
|
|
@@ -243,7 +460,7 @@ async def test_delete_instance(
|
|
|
243
460
|
|
|
244
461
|
|
|
245
462
|
@pytest.mark.asyncio
|
|
246
|
-
async def
|
|
463
|
+
async def test_delete_instance_extension_not_found(
|
|
247
464
|
mocker: MockerFixture,
|
|
248
465
|
api_client: AsyncClient,
|
|
249
466
|
settings_factory: SettingsFactory,
|
|
@@ -251,7 +468,8 @@ async def test_delete_extension_not_found(
|
|
|
251
468
|
):
|
|
252
469
|
settings = settings_factory()
|
|
253
470
|
mocker.patch(
|
|
254
|
-
"mrok.controller.routes.fetch_extension_or_404",
|
|
471
|
+
"mrok.controller.routes.extensions.fetch_extension_or_404",
|
|
472
|
+
return_value={"name": "ext-1234-5678"},
|
|
255
473
|
)
|
|
256
474
|
|
|
257
475
|
query = quote(
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from urllib.parse import quote
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from httpx import AsyncClient
|
|
5
|
+
from pytest_httpx import HTTPXMock
|
|
6
|
+
|
|
7
|
+
from mrok.ziti.constants import MROK_SERVICE_TAG_NAME, MROK_VERSION_TAG_NAME
|
|
8
|
+
from tests.conftest import SettingsFactory
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.asyncio
|
|
12
|
+
async def test_list_instances(
|
|
13
|
+
api_client: AsyncClient,
|
|
14
|
+
settings_factory: SettingsFactory,
|
|
15
|
+
httpx_mock: HTTPXMock,
|
|
16
|
+
):
|
|
17
|
+
settings = settings_factory()
|
|
18
|
+
httpx_mock.add_response(
|
|
19
|
+
method="GET",
|
|
20
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/identities?&limit=10&offset=0",
|
|
21
|
+
json={
|
|
22
|
+
"meta": {"pagination": {"totalCount": 15, "limit": 10, "offset": 0}},
|
|
23
|
+
"data": [{"id": f"ins{i}", "name": "ins.svc"} for i in range(10)],
|
|
24
|
+
},
|
|
25
|
+
)
|
|
26
|
+
httpx_mock.add_response(
|
|
27
|
+
method="GET",
|
|
28
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/identities?&limit=10&offset=10",
|
|
29
|
+
json={
|
|
30
|
+
"meta": {"pagination": {"totalCount": 15, "limit": 10, "offset": 10}},
|
|
31
|
+
"data": [{"id": f"ins{i}", "name": "ins.svc"} for i in range(11, 16)],
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
response = await api_client.get("/instances?limit=10&offset=0")
|
|
35
|
+
assert response.status_code == 200
|
|
36
|
+
page_1 = response.json()
|
|
37
|
+
assert len(page_1["data"]) == 10
|
|
38
|
+
assert page_1["$meta"]["pagination"]["offset"] == 0
|
|
39
|
+
|
|
40
|
+
response = await api_client.get("/instances?limit=10&offset=10")
|
|
41
|
+
assert response.status_code == 200
|
|
42
|
+
page_2 = response.json()
|
|
43
|
+
assert len(page_2["data"]) == 5
|
|
44
|
+
assert page_2["$meta"]["pagination"]["offset"] == 10
|
|
45
|
+
|
|
46
|
+
assert sorted(page_1["data"], key=lambda x: x["id"]) != sorted(
|
|
47
|
+
page_2["data"], key=lambda x: x["id"]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.mark.asyncio
|
|
52
|
+
async def test_get_instance(
|
|
53
|
+
settings_factory: SettingsFactory,
|
|
54
|
+
api_client: AsyncClient,
|
|
55
|
+
httpx_mock: HTTPXMock,
|
|
56
|
+
):
|
|
57
|
+
settings = settings_factory()
|
|
58
|
+
query = quote(
|
|
59
|
+
'(id="INS-1234-1234-0001.ext-1234-1234" or name="ins-1234-1234-0001.ext-1234-1234") '
|
|
60
|
+
f"and tags.{MROK_VERSION_TAG_NAME} != null"
|
|
61
|
+
)
|
|
62
|
+
httpx_mock.add_response(
|
|
63
|
+
method="GET",
|
|
64
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/identities?filter={query}",
|
|
65
|
+
json={
|
|
66
|
+
"meta": {"pagination": {"totalCount": 1}},
|
|
67
|
+
"data": [
|
|
68
|
+
{
|
|
69
|
+
"id": "ins1",
|
|
70
|
+
"name": "ins-1234-1234-0001.ext-1234-1234",
|
|
71
|
+
"tags": {
|
|
72
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
73
|
+
MROK_SERVICE_TAG_NAME: "ext-1234-1234",
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
response = await api_client.get("/instances/INS-1234-1234-0001.ext-1234-1234")
|
|
81
|
+
assert response.status_code == 200
|
|
82
|
+
assert response.json() == {
|
|
83
|
+
"id": "ins1",
|
|
84
|
+
"identity": None,
|
|
85
|
+
"extension": {"id": "EXT-1234-1234"},
|
|
86
|
+
"instance": {"id": "INS-1234-1234-0001"},
|
|
87
|
+
"name": "ins-1234-1234-0001.ext-1234-1234",
|
|
88
|
+
"tags": {
|
|
89
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
90
|
+
MROK_SERVICE_TAG_NAME: "ext-1234-1234",
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@pytest.mark.asyncio
|
|
96
|
+
async def test_get_instance_by_instance_id(
|
|
97
|
+
settings_factory: SettingsFactory,
|
|
98
|
+
api_client: AsyncClient,
|
|
99
|
+
httpx_mock: HTTPXMock,
|
|
100
|
+
):
|
|
101
|
+
settings = settings_factory()
|
|
102
|
+
query = quote(f'(id="ins1" or name="ins1") and tags.{MROK_VERSION_TAG_NAME} != null')
|
|
103
|
+
httpx_mock.add_response(
|
|
104
|
+
method="GET",
|
|
105
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/identities?filter={query}",
|
|
106
|
+
json={
|
|
107
|
+
"meta": {"pagination": {"totalCount": 1}},
|
|
108
|
+
"data": [
|
|
109
|
+
{
|
|
110
|
+
"id": "ins1",
|
|
111
|
+
"name": "ins-1234-1234-0001.ext-1234-1234",
|
|
112
|
+
"tags": {
|
|
113
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
114
|
+
MROK_SERVICE_TAG_NAME: "ext-1234-1234",
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
response = await api_client.get("/instances/ins1")
|
|
122
|
+
assert response.status_code == 200
|
|
123
|
+
assert response.json() == {
|
|
124
|
+
"id": "ins1",
|
|
125
|
+
"extension": {"id": "EXT-1234-1234"},
|
|
126
|
+
"instance": {"id": "INS-1234-1234-0001"},
|
|
127
|
+
"name": "ins-1234-1234-0001.ext-1234-1234",
|
|
128
|
+
"tags": {
|
|
129
|
+
MROK_VERSION_TAG_NAME: "0.0.0.dev0",
|
|
130
|
+
MROK_SERVICE_TAG_NAME: "ext-1234-1234",
|
|
131
|
+
},
|
|
132
|
+
"identity": None,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@pytest.mark.asyncio
|
|
137
|
+
async def test_get_instance_not_found(
|
|
138
|
+
settings_factory: SettingsFactory,
|
|
139
|
+
api_client: AsyncClient,
|
|
140
|
+
httpx_mock: HTTPXMock,
|
|
141
|
+
):
|
|
142
|
+
settings = settings_factory()
|
|
143
|
+
query = quote(
|
|
144
|
+
'(id="INS-1234-1234-0001.ext-1234-1234" or name="ins-1234-1234-0001.ext-1234-1234") '
|
|
145
|
+
f"and tags.{MROK_VERSION_TAG_NAME} != null"
|
|
146
|
+
)
|
|
147
|
+
httpx_mock.add_response(
|
|
148
|
+
method="GET",
|
|
149
|
+
url=f"{settings.ziti.api.management}/edge/management/v1/identities?filter={query}",
|
|
150
|
+
json={
|
|
151
|
+
"meta": {"pagination": {"totalCount": 10}},
|
|
152
|
+
"data": [],
|
|
153
|
+
},
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
response = await api_client.get("/instances/INS-1234-1234-0001.ext-1234-1234")
|
|
157
|
+
assert response.status_code == 404
|
|
File without changes
|
|
@@ -37,6 +37,15 @@ wheels = [
|
|
|
37
37
|
{ url = "https://files.pythonhosted.org/packages/2f/f5/c36551e93acba41a59939ae6a0fb77ddb3f2e8e8caa716410c65f7341f72/asgi_lifespan-2.1.0-py3-none-any.whl", hash = "sha256:ed840706680e28428c01e14afb3875d7d76d3206f3d5b2f2294e059b5c23804f", size = 10895, upload-time = "2023-03-28T17:35:47.772Z" },
|
|
38
38
|
]
|
|
39
39
|
|
|
40
|
+
[[package]]
|
|
41
|
+
name = "asn1crypto"
|
|
42
|
+
version = "1.5.1"
|
|
43
|
+
source = { registry = "https://pypi.org/simple" }
|
|
44
|
+
sdist = { url = "https://files.pythonhosted.org/packages/de/cf/d547feed25b5244fcb9392e288ff9fdc3280b10260362fc45d37a798a6ee/asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c", size = 121080, upload-time = "2022-03-15T14:46:52.889Z" }
|
|
45
|
+
wheels = [
|
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/c9/7f/09065fd9e27da0eda08b4d6897f1c13535066174cc023af248fc2a8d5e5a/asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67", size = 105045, upload-time = "2022-03-15T14:46:51.055Z" },
|
|
47
|
+
]
|
|
48
|
+
|
|
40
49
|
[[package]]
|
|
41
50
|
name = "asttokens"
|
|
42
51
|
version = "3.0.0"
|
|
@@ -672,6 +681,7 @@ name = "mrok"
|
|
|
672
681
|
version = "0.0.0.dev0"
|
|
673
682
|
source = { editable = "." }
|
|
674
683
|
dependencies = [
|
|
684
|
+
{ name = "asn1crypto" },
|
|
675
685
|
{ name = "cryptography" },
|
|
676
686
|
{ name = "dynaconf" },
|
|
677
687
|
{ name = "fastapi", extra = ["standard"] },
|
|
@@ -708,6 +718,7 @@ dev = [
|
|
|
708
718
|
|
|
709
719
|
[package.metadata]
|
|
710
720
|
requires-dist = [
|
|
721
|
+
{ name = "asn1crypto", specifier = ">=1.5.1,<2.0.0" },
|
|
711
722
|
{ name = "cryptography", specifier = ">=45.0.7,<46.0.0" },
|
|
712
723
|
{ name = "dynaconf", specifier = ">=3.2.11,<4.0.0" },
|
|
713
724
|
{ name = "fastapi", extras = ["standard"], specifier = ">=0.119.0,<0.120.0" },
|