openshell-shared 0.1.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.
- api/__init__.py +1 -0
- api/manager/__init__.py +1 -0
- api/manager/v1/__init__.py +78 -0
- api/manager/v1/authentication.py +278 -0
- api/manager/v1/client.py +111 -0
- api/manager/v1/domains.py +64 -0
- api/manager/v1/entities.py +97 -0
- api/manager/v1/exceptions.py +98 -0
- api/manager/v1/identity.py +44 -0
- api/manager/v1/models.py +342 -0
- api/manager/v1/passports.py +131 -0
- api/manager/v1/sessions.py +83 -0
- api/manager/v1/transport.py +253 -0
- api/manager/v1/tunnels.py +120 -0
- cryptography/__init__.py +0 -0
- cryptography/certificate.py +390 -0
- cryptography/encoding.py +0 -0
- cryptography/identity.py +124 -0
- cryptography/keys.py +463 -0
- cryptography/signatures.py +63 -0
- cryptography/utils.py +0 -0
- domain/__init__.py +0 -0
- domain/domain.py +80 -0
- domain/membership.py +21 -0
- domain/permissions.py +14 -0
- domain/policies.py +2 -0
- identity/__init__.py +0 -0
- identity/identification.py +64 -0
- identity/store.py +150 -0
- modules/__init__.py +0 -0
- modules/shell/__init__.py +0 -0
- modules/shell/client.py +361 -0
- modules/shell/models.py +61 -0
- modules/shell/protocol.py +249 -0
- modules/shell/server.py +511 -0
- modules/shell/session.py +339 -0
- modules/utils.py +212 -0
- openshell_shared-0.1.2.dist-info/METADATA +59 -0
- openshell_shared-0.1.2.dist-info/RECORD +62 -0
- openshell_shared-0.1.2.dist-info/WHEEL +5 -0
- openshell_shared-0.1.2.dist-info/top_level.txt +7 -0
- protocols/__init__.py +0 -0
- protocols/negotiation/challenge.py +127 -0
- protocols/negotiation/models.py +28 -0
- standards/__init__.py +0 -0
- standards/certificates/__init__.py +0 -0
- standards/certificates/status.py +12 -0
- standards/certificates/types.py +11 -0
- standards/entities/__init__.py +0 -0
- standards/entities/types.py +14 -0
- standards/events/__init__.py +0 -0
- standards/events/schemas/__init__.py +0 -0
- standards/events/schemas/entity_registered.py +13 -0
- standards/events/types.py +18 -0
- standards/passports/__init__.py +0 -0
- standards/passports/types.py +5 -0
- standards/permissions/__init__.py +0 -0
- standards/permissions/types.py +14 -0
- standards/roles/__init__.py +0 -0
- standards/roles/types.py +8 -0
- standards/transports/__init__.py +0 -0
- standards/transports/types.py +24 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# shared/protocols/negotiation/challenge.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import secrets
|
|
5
|
+
from time import time
|
|
6
|
+
from uuid6 import uuid7
|
|
7
|
+
|
|
8
|
+
from .models import AuthenticationChallenge, AuthenticationResponse
|
|
9
|
+
from shared.cryptography.signatures import sign_data, verify_signature
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
SCHEMA_VERSION = 1
|
|
13
|
+
|
|
14
|
+
CHALLENGE_TYPE_SERVER_AUTHENTICATION = "server_authentication"
|
|
15
|
+
CHALLENGE_TYPE_CLIENT_AUTHENTICATION = "client_authentication"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ChallengeProtocol:
|
|
19
|
+
|
|
20
|
+
# -----------------------------
|
|
21
|
+
# SERIALIZATION CANÓNICA
|
|
22
|
+
# -----------------------------
|
|
23
|
+
@staticmethod
|
|
24
|
+
def _serialize(data: dict) -> dict:
|
|
25
|
+
return json.loads(
|
|
26
|
+
json.dumps(data, sort_keys=True, separators=(",", ":"))
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def _challenge_payload(challenge: AuthenticationChallenge) -> dict:
|
|
31
|
+
# SOLO campos relevantes para firma (CRÍTICO)
|
|
32
|
+
return ChallengeProtocol._serialize({
|
|
33
|
+
"schema": challenge.schema,
|
|
34
|
+
"challenge_type": challenge.challenge_type,
|
|
35
|
+
"challenge_id": challenge.challenge_id,
|
|
36
|
+
"issuer_uid": challenge.issuer_uid,
|
|
37
|
+
"target_uid": challenge.target_uid,
|
|
38
|
+
"nonce": challenge.nonce,
|
|
39
|
+
"issued_at": challenge.issued_at,
|
|
40
|
+
"expires_at": challenge.expires_at,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
# -----------------------------
|
|
44
|
+
# CREACIÓN
|
|
45
|
+
# -----------------------------
|
|
46
|
+
@staticmethod
|
|
47
|
+
def create(challenge_type: str, issuer_uid: str, target_uid: str, expires_in: int = 60):
|
|
48
|
+
now = int(time())
|
|
49
|
+
|
|
50
|
+
return AuthenticationChallenge(
|
|
51
|
+
schema=SCHEMA_VERSION,
|
|
52
|
+
challenge_type=challenge_type,
|
|
53
|
+
challenge_id=str(uuid7()),
|
|
54
|
+
issuer_uid=issuer_uid,
|
|
55
|
+
target_uid=target_uid,
|
|
56
|
+
nonce=secrets.token_hex(32),
|
|
57
|
+
issued_at=now,
|
|
58
|
+
expires_at=now + expires_in
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# -----------------------------
|
|
62
|
+
# FIRMA
|
|
63
|
+
# -----------------------------
|
|
64
|
+
@staticmethod
|
|
65
|
+
def sign(private_key: str, challenge: AuthenticationChallenge) -> AuthenticationResponse:
|
|
66
|
+
payload = ChallengeProtocol._challenge_payload(challenge)
|
|
67
|
+
|
|
68
|
+
signature = sign_data(private_key, payload)
|
|
69
|
+
|
|
70
|
+
return AuthenticationResponse(
|
|
71
|
+
schema=SCHEMA_VERSION,
|
|
72
|
+
challenge_id=challenge.challenge_id,
|
|
73
|
+
responder_uid=challenge.target_uid,
|
|
74
|
+
signature=signature
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# -----------------------------
|
|
78
|
+
# VERIFICACIÓN
|
|
79
|
+
# -----------------------------
|
|
80
|
+
@staticmethod
|
|
81
|
+
def verify(public_key: str, challenge: AuthenticationChallenge, response: AuthenticationResponse) -> bool:
|
|
82
|
+
payload = ChallengeProtocol._challenge_payload(challenge)
|
|
83
|
+
return verify_signature(public_key, payload, response.signature)
|
|
84
|
+
|
|
85
|
+
# -----------------------------
|
|
86
|
+
# UTILIDADES
|
|
87
|
+
# -----------------------------
|
|
88
|
+
@staticmethod
|
|
89
|
+
def is_expired(challenge) -> bool:
|
|
90
|
+
return int(time()) > challenge.expires_at
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def validate_type(challenge, expected_type: str) -> bool:
|
|
94
|
+
return challenge.challenge_type == expected_type
|
|
95
|
+
|
|
96
|
+
# -----------------------------
|
|
97
|
+
# SERIALIZACIÓN ROBUSTA
|
|
98
|
+
# -----------------------------
|
|
99
|
+
@staticmethod
|
|
100
|
+
def challenge_to_dict(challenge) -> dict:
|
|
101
|
+
return {
|
|
102
|
+
"schema": challenge.schema,
|
|
103
|
+
"challenge_type": challenge.challenge_type,
|
|
104
|
+
"challenge_id": challenge.challenge_id,
|
|
105
|
+
"issuer_uid": challenge.issuer_uid,
|
|
106
|
+
"target_uid": challenge.target_uid,
|
|
107
|
+
"nonce": challenge.nonce,
|
|
108
|
+
"issued_at": challenge.issued_at,
|
|
109
|
+
"expires_at": challenge.expires_at,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def response_to_dict(response) -> dict:
|
|
114
|
+
return {
|
|
115
|
+
"schema": response.schema,
|
|
116
|
+
"challenge_id": response.challenge_id,
|
|
117
|
+
"responder_uid": response.responder_uid,
|
|
118
|
+
"signature": response.signature,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@staticmethod
|
|
122
|
+
def challenge_from_dict(data: dict):
|
|
123
|
+
return AuthenticationChallenge(**data)
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def response_from_dict(data: dict):
|
|
127
|
+
return AuthenticationResponse(**data)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclass
|
|
5
|
+
class AuthenticationChallenge:
|
|
6
|
+
schema: int
|
|
7
|
+
|
|
8
|
+
challenge_type: str
|
|
9
|
+
|
|
10
|
+
challenge_id: str
|
|
11
|
+
|
|
12
|
+
issuer_uid: str
|
|
13
|
+
target_uid: str
|
|
14
|
+
|
|
15
|
+
nonce: str
|
|
16
|
+
|
|
17
|
+
issued_at: int
|
|
18
|
+
expires_at: int
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class AuthenticationResponse:
|
|
22
|
+
schema: int
|
|
23
|
+
|
|
24
|
+
challenge_id: str
|
|
25
|
+
|
|
26
|
+
responder_uid: str
|
|
27
|
+
|
|
28
|
+
signature: str
|
standards/__init__.py
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CertificateStatus(str, Enum):
|
|
5
|
+
ACTIVE = "ACTIVE"
|
|
6
|
+
REVOKED = "REVOKED"
|
|
7
|
+
EXPIRED = "EXPIRED"
|
|
8
|
+
COMPROMISED = "COMPROMISED"
|
|
9
|
+
|
|
10
|
+
@staticmethod
|
|
11
|
+
def exists(value: str) -> bool:
|
|
12
|
+
return value in CertificateStatus._value2member_map_
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
SCHEMA_VERSION = 1
|
|
4
|
+
|
|
5
|
+
class CertificateType(str, Enum):
|
|
6
|
+
DOMAIN_MANAGEMENT = "DOMAIN_MANAGEMENT"
|
|
7
|
+
MANAGER_AUTHORIZATION = "MANAGER_AUTHORIZATION"
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
def exists(value: str) -> bool:
|
|
11
|
+
return value in CertificateType._value2member_map_
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class EventType(str, Enum):
|
|
5
|
+
|
|
6
|
+
ENTITY_REGISTERED = "entity.registered"
|
|
7
|
+
|
|
8
|
+
ENTITY_REVOKED = "entity.revoked"
|
|
9
|
+
|
|
10
|
+
DOMAIN_CREATED = "domain.created"
|
|
11
|
+
|
|
12
|
+
DOMAIN_UPDATED = "domain.updated"
|
|
13
|
+
|
|
14
|
+
DOMAIN_DELETED = "domain.deleted"
|
|
15
|
+
|
|
16
|
+
MEMBERSHIP_CREATED = "membership.created"
|
|
17
|
+
|
|
18
|
+
TRUST_ESTABLISHED = "trust.established"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
standards/roles/types.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TransportType(str, Enum):
|
|
5
|
+
TCP = "TCP"
|
|
6
|
+
UDP = "UDP"
|
|
7
|
+
|
|
8
|
+
HTTP = "HTTP"
|
|
9
|
+
HTTPS = "HTTPS"
|
|
10
|
+
|
|
11
|
+
WEBSOCKET = "WEBSOCKET"
|
|
12
|
+
WEBSOCKET_SECURE = "WEBSOCKET_SECURE"
|
|
13
|
+
|
|
14
|
+
QUIC = "QUIC"
|
|
15
|
+
|
|
16
|
+
BLUETOOTH = "BLUETOOTH"
|
|
17
|
+
SERIAL = "SERIAL"
|
|
18
|
+
|
|
19
|
+
TOR = "TOR"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def exists(value: str) -> bool:
|
|
24
|
+
return value in TransportType._value2member_map_
|