pangea-sdk 6.1.0__py3-none-any.whl → 6.2.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.
- pangea/__init__.py +9 -1
- pangea/asyncio/__init__.py +1 -0
- pangea/asyncio/file_uploader.py +4 -2
- pangea/asyncio/request.py +53 -18
- pangea/asyncio/services/__init__.py +2 -0
- pangea/asyncio/services/ai_guard.py +9 -12
- pangea/asyncio/services/audit.py +12 -7
- pangea/asyncio/services/authn.py +36 -25
- pangea/asyncio/services/authz.py +6 -6
- pangea/asyncio/services/base.py +4 -0
- pangea/asyncio/services/file_scan.py +8 -2
- pangea/asyncio/services/intel.py +26 -28
- pangea/asyncio/services/redact.py +7 -3
- pangea/asyncio/services/sanitize.py +5 -1
- pangea/asyncio/services/share.py +5 -1
- pangea/asyncio/services/vault.py +19 -15
- pangea/audit_logger.py +3 -1
- pangea/deep_verify.py +13 -13
- pangea/deprecated.py +1 -1
- pangea/dump_audit.py +2 -3
- pangea/exceptions.py +8 -5
- pangea/file_uploader.py +4 -0
- pangea/request.py +64 -48
- pangea/response.py +21 -18
- pangea/services/__init__.py +2 -0
- pangea/services/ai_guard.py +35 -24
- pangea/services/audit/audit.py +16 -13
- pangea/services/audit/models.py +71 -34
- pangea/services/audit/signing.py +1 -1
- pangea/services/audit/util.py +10 -10
- pangea/services/authn/authn.py +36 -25
- pangea/services/authn/models.py +10 -56
- pangea/services/authz.py +10 -6
- pangea/services/base.py +7 -4
- pangea/services/embargo.py +6 -0
- pangea/services/file_scan.py +8 -2
- pangea/services/intel.py +36 -19
- pangea/services/redact.py +7 -3
- pangea/services/sanitize.py +5 -1
- pangea/services/share/share.py +13 -7
- pangea/services/vault/models/asymmetric.py +4 -0
- pangea/services/vault/models/common.py +4 -0
- pangea/services/vault/models/symmetric.py +4 -0
- pangea/services/vault/vault.py +17 -19
- pangea/tools.py +13 -9
- pangea/utils.py +3 -5
- pangea/verify_audit.py +23 -27
- {pangea_sdk-6.1.0.dist-info → pangea_sdk-6.2.0.dist-info}/METADATA +36 -17
- pangea_sdk-6.2.0.dist-info/RECORD +60 -0
- {pangea_sdk-6.1.0.dist-info → pangea_sdk-6.2.0.dist-info}/WHEEL +1 -1
- pangea_sdk-6.1.0.dist-info/RECORD +0 -60
pangea/services/audit/models.py
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
9
|
import datetime
|
6
10
|
import enum
|
7
11
|
from typing import Any, Dict, List, Optional, Sequence, Union
|
8
12
|
|
13
|
+
from pydantic import Field
|
14
|
+
from typing_extensions import Annotated
|
15
|
+
|
9
16
|
from pangea.response import APIRequestModel, APIResponseModel, PangeaDateTime, PangeaResponseResult
|
10
17
|
|
11
18
|
|
@@ -113,20 +120,25 @@ class Event(Dict[str, Any]):
|
|
113
120
|
|
114
121
|
|
115
122
|
class EventEnvelope(APIResponseModel):
|
116
|
-
|
117
|
-
Contain extra information about an event.
|
123
|
+
event: Optional[dict[str, Any]] = None
|
118
124
|
|
119
|
-
|
120
|
-
|
121
|
-
signature
|
122
|
-
|
123
|
-
|
125
|
+
signature: Optional[str] = None
|
126
|
+
"""
|
127
|
+
This is the signature of the hash of the canonicalized event that can be
|
128
|
+
verified with the public key provided in the public_key field. Signatures
|
129
|
+
cannot be used with the redaction feature turned on. If redaction is
|
130
|
+
required, the user needs to perform redaction before computing the signature
|
131
|
+
that is to be sent with the message. The SDK facilitates this for users.
|
124
132
|
"""
|
125
133
|
|
126
|
-
event: Dict[str, Any]
|
127
|
-
signature: Optional[str] = None
|
128
134
|
public_key: Optional[str] = None
|
129
|
-
|
135
|
+
"""
|
136
|
+
The base64-encoded ed25519 public key used for the signature, if one is
|
137
|
+
provided
|
138
|
+
"""
|
139
|
+
|
140
|
+
received_at: Optional[PangeaDateTime] = None
|
141
|
+
"""A Pangea provided timestamp of when the event was received."""
|
130
142
|
|
131
143
|
|
132
144
|
class LogRequest(APIRequestModel):
|
@@ -177,21 +189,28 @@ class LogBulkRequest(APIRequestModel):
|
|
177
189
|
|
178
190
|
|
179
191
|
class LogResult(PangeaResponseResult):
|
192
|
+
envelope: Optional[EventEnvelope] = None
|
180
193
|
"""
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
hash -- Event envelope hash.
|
185
|
-
unpublished_root -- The current unpublished root.
|
186
|
-
membership_proof -- A proof for verifying the unpublished root.
|
187
|
-
consistency_proof -- If prev_root was present in the request, this proof verifies that the new unpublished root is a continuation of the prev_root
|
194
|
+
The sealed envelope containing the event that was logged. Includes event
|
195
|
+
metadata such as optional client-side signature details and server-added
|
196
|
+
timestamps.
|
188
197
|
"""
|
189
198
|
|
190
|
-
|
191
|
-
hash
|
199
|
+
hash: Annotated[Optional[str], Field(max_length=64, min_length=64)] = None
|
200
|
+
"""The hash of the event data."""
|
201
|
+
|
192
202
|
unpublished_root: Optional[str] = None
|
203
|
+
"""The current unpublished root."""
|
204
|
+
|
193
205
|
membership_proof: Optional[str] = None
|
206
|
+
"""A proof for verifying that the buffer_root contains the received event"""
|
207
|
+
|
194
208
|
consistency_proof: Optional[List[str]] = None
|
209
|
+
"""
|
210
|
+
If prev_buffer_root was present in the request, this proof verifies that the
|
211
|
+
new unpublished root is a continuation of prev_unpublished_root
|
212
|
+
"""
|
213
|
+
|
195
214
|
consistency_verification: EventVerification = EventVerification.NONE
|
196
215
|
membership_verification: EventVerification = EventVerification.NONE
|
197
216
|
signature_verification: EventVerification = EventVerification.NONE
|
@@ -354,29 +373,47 @@ class RootResult(PangeaResponseResult):
|
|
354
373
|
|
355
374
|
|
356
375
|
class SearchEvent(APIResponseModel):
|
376
|
+
envelope: EventEnvelope
|
377
|
+
|
378
|
+
membership_proof: Optional[str] = None
|
379
|
+
"""A cryptographic proof that the record has been persisted in the log"""
|
380
|
+
|
381
|
+
hash: Annotated[Optional[str], Field(max_length=64, min_length=64)] = None
|
382
|
+
"""The record's hash"""
|
383
|
+
|
384
|
+
published: Optional[bool] = None
|
385
|
+
"""
|
386
|
+
If true, a root has been published after this event. If false, there is no
|
387
|
+
published root for this event
|
357
388
|
"""
|
358
|
-
Event information received after a search request
|
359
389
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
membership_proof -- A cryptographic proof that the record has been persisted in the log.
|
365
|
-
consistency_verification -- Consistency verification calculated if required.
|
366
|
-
membership_verification -- Membership verification calculated if required.
|
367
|
-
signature_verification -- Signature verification calculated if required.
|
368
|
-
fpe_context -- The context data needed to decrypt secure audit events that have been redacted with format preserving encryption.
|
390
|
+
imported: Optional[bool] = None
|
391
|
+
"""
|
392
|
+
If true, the even was imported manually and not logged by the standard
|
393
|
+
procedure. Some features such as tamper proofing may not be available
|
369
394
|
"""
|
370
395
|
|
371
|
-
envelope: EventEnvelope
|
372
|
-
hash: str
|
373
|
-
membership_proof: Optional[str] = None
|
374
|
-
published: Optional[bool] = None
|
375
396
|
leaf_index: Optional[int] = None
|
397
|
+
"""
|
398
|
+
The index of the leaf of the Merkle Tree where this record was inserted or
|
399
|
+
null if published=false
|
400
|
+
"""
|
401
|
+
|
402
|
+
valid_signature: Optional[bool] = None
|
403
|
+
"""
|
404
|
+
Result of the verification of the Vault signature, if the event was signed
|
405
|
+
and the parameter `verify_signature` is `true`
|
406
|
+
"""
|
407
|
+
|
408
|
+
fpe_context: Optional[str] = None
|
409
|
+
"""
|
410
|
+
The context data needed to decrypt secure audit events that have been
|
411
|
+
redacted with format preserving encryption.
|
412
|
+
"""
|
413
|
+
|
376
414
|
consistency_verification: EventVerification = EventVerification.NONE
|
377
415
|
membership_verification: EventVerification = EventVerification.NONE
|
378
416
|
signature_verification: EventVerification = EventVerification.NONE
|
379
|
-
fpe_context: Optional[str] = None
|
380
417
|
|
381
418
|
|
382
419
|
class SearchResultOutput(PangeaResponseResult):
|
pangea/services/audit/signing.py
CHANGED
@@ -81,7 +81,7 @@ class Signer:
|
|
81
81
|
with open(self.private_key_file, "rb") as file:
|
82
82
|
file_bytes = file.read()
|
83
83
|
except FileNotFoundError:
|
84
|
-
raise Exception(f"Error: Failed opening private key file {self.private_key_file}")
|
84
|
+
raise Exception(f"Error: Failed opening private key file {self.private_key_file}") from None
|
85
85
|
|
86
86
|
privkey = self._decode_private_key(file_bytes)
|
87
87
|
for cls, signer in signers.items():
|
pangea/services/audit/util.py
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
3
9
|
import base64
|
4
10
|
import json
|
5
11
|
import logging
|
@@ -155,9 +161,9 @@ def verify_membership_proof(node_hash: Hash, root_hash: Hash, proof: MembershipP
|
|
155
161
|
def normalize_log(data: dict) -> dict:
|
156
162
|
ans = {}
|
157
163
|
for key in data:
|
158
|
-
if
|
164
|
+
if isinstance(data[key], datetime):
|
159
165
|
ans[key] = format_datetime(data[key])
|
160
|
-
elif
|
166
|
+
elif isinstance(data[key], dict):
|
161
167
|
ans[key] = normalize_log(data[key]) # type: ignore[assignment]
|
162
168
|
else:
|
163
169
|
ans[key] = data[key]
|
@@ -223,9 +229,7 @@ def get_arweave_published_roots(tree_name: str, tree_sizes: Collection[int]) ->
|
|
223
229
|
}
|
224
230
|
}
|
225
231
|
}
|
226
|
-
""".replace(
|
227
|
-
"{tree_sizes}", ", ".join(f'"{tree_size}"' for tree_size in tree_sizes)
|
228
|
-
).replace(
|
232
|
+
""".replace("{tree_sizes}", ", ".join(f'"{tree_size}"' for tree_size in tree_sizes)).replace(
|
229
233
|
"{tree_name}", tree_name
|
230
234
|
)
|
231
235
|
|
@@ -273,8 +277,4 @@ def verify_consistency_proof(new_root: Hash, prev_root: Hash, proof: Consistency
|
|
273
277
|
return False
|
274
278
|
|
275
279
|
logger.debug("Verifying the proofs for the new root")
|
276
|
-
for item in proof
|
277
|
-
if not verify_membership_proof(item.node_hash, new_root, item.proof):
|
278
|
-
return False
|
279
|
-
|
280
|
-
return True
|
280
|
+
return all(verify_membership_proof(item.node_hash, new_root, item.proof) for item in proof)
|
pangea/services/authn/authn.py
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
9
|
+
from collections.abc import Mapping
|
5
10
|
from typing import Dict, List, Literal, Optional, Union
|
6
11
|
|
7
12
|
import pangea.services.authn.models as m
|
@@ -128,7 +133,7 @@ class AuthN(ServiceBase):
|
|
128
133
|
Returns:
|
129
134
|
A PangeaResponse with a list of sessions in the response.result field.
|
130
135
|
Available response fields can be found in our
|
131
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/session#/v2/session/list).
|
136
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/session#/v2/session/list-post).
|
132
137
|
|
133
138
|
Examples:
|
134
139
|
response = authn.session.list()
|
@@ -192,7 +197,7 @@ class AuthN(ServiceBase):
|
|
192
197
|
Returns:
|
193
198
|
A PangeaResponse with credentials for a login session in the response.result field.
|
194
199
|
Available response fields can be found in our
|
195
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/client/userinfo).
|
200
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/client/userinfo-post).
|
196
201
|
|
197
202
|
Examples:
|
198
203
|
response = authn.client.userinfo(
|
@@ -217,7 +222,7 @@ class AuthN(ServiceBase):
|
|
217
222
|
Returns:
|
218
223
|
A PangeaResponse with jwt verification keys in the response.result field.
|
219
224
|
Available response fields can be found in our
|
220
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/jwt#/v2/client/jwks).
|
225
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/jwt#/v2/client/jwks-post).
|
221
226
|
|
222
227
|
Examples:
|
223
228
|
response = authn.client.jwks()
|
@@ -290,7 +295,7 @@ class AuthN(ServiceBase):
|
|
290
295
|
Returns:
|
291
296
|
A PangeaResponse with a list of sessions in the response.result field.
|
292
297
|
Available response fields can be found in our
|
293
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/session#/v2/client/session/list).
|
298
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/session#/v2/client/session/list-post).
|
294
299
|
|
295
300
|
Examples:
|
296
301
|
response = authn.client.session.list(
|
@@ -349,7 +354,7 @@ class AuthN(ServiceBase):
|
|
349
354
|
Returns:
|
350
355
|
A PangeaResponse with credentials for a login session in the response.result field.
|
351
356
|
Available response fields can be found in our
|
352
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/session#/v2/client/session/refresh).
|
357
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/session#/v2/client/session/refresh-post).
|
353
358
|
|
354
359
|
Examples:
|
355
360
|
response = authn.client.session.refresh(
|
@@ -447,7 +452,7 @@ class AuthN(ServiceBase):
|
|
447
452
|
Returns:
|
448
453
|
A PangeaResponse with a token and its information in the response.result field.
|
449
454
|
Available response fields can be found in our
|
450
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/client/token/check).
|
455
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/client/token/check-post).
|
451
456
|
|
452
457
|
Examples:
|
453
458
|
response = authn.client.token_endpoints.check(
|
@@ -477,7 +482,7 @@ class AuthN(ServiceBase):
|
|
477
482
|
def create(
|
478
483
|
self,
|
479
484
|
email: str,
|
480
|
-
profile:
|
485
|
+
profile: Mapping[str, str],
|
481
486
|
*,
|
482
487
|
username: str | None = None,
|
483
488
|
) -> PangeaResponse[m.UserCreateResult]:
|
@@ -496,7 +501,7 @@ class AuthN(ServiceBase):
|
|
496
501
|
Returns:
|
497
502
|
A PangeaResponse with a user and its information in the response.result field.
|
498
503
|
Available response fields can be found in our
|
499
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/create).
|
504
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/create-post).
|
500
505
|
|
501
506
|
Examples:
|
502
507
|
response = authn.user.create(
|
@@ -561,7 +566,7 @@ class AuthN(ServiceBase):
|
|
561
566
|
Returns:
|
562
567
|
A PangeaResponse with a pending user invitation in the response.result field.
|
563
568
|
Available response fields can be found in our
|
564
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/invite#/v2/user/invite).
|
569
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/invite#/v2/user/invite-post).
|
565
570
|
|
566
571
|
Examples:
|
567
572
|
response = authn.user.invite(
|
@@ -606,7 +611,7 @@ class AuthN(ServiceBase):
|
|
606
611
|
Returns:
|
607
612
|
A PangeaResponse with a user and its information in the response.result field.
|
608
613
|
Available response fields can be found in our
|
609
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/update).
|
614
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/update-post).
|
610
615
|
|
611
616
|
Examples:
|
612
617
|
response = authn.user.update(
|
@@ -649,7 +654,7 @@ class AuthN(ServiceBase):
|
|
649
654
|
Returns:
|
650
655
|
A PangeaResponse with a list of users in the response.result field.
|
651
656
|
Available response fields can be found in our
|
652
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/list).
|
657
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/list-post).
|
653
658
|
|
654
659
|
Examples:
|
655
660
|
response = authn.user.list()
|
@@ -703,7 +708,7 @@ class AuthN(ServiceBase):
|
|
703
708
|
Returns:
|
704
709
|
A PangeaResponse with a list of pending user invitations in the response.result field.
|
705
710
|
Available response fields can be found in our
|
706
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/invite#/v2/user/invite/list).
|
711
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/invite#/v2/user/invite/list-post).
|
707
712
|
Examples:
|
708
713
|
response = authn.user.invites.list()
|
709
714
|
"""
|
@@ -807,7 +812,7 @@ class AuthN(ServiceBase):
|
|
807
812
|
Returns:
|
808
813
|
A PangeaResponse with a list of authenticators in the response.result field.
|
809
814
|
Available response fields can be found in our
|
810
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/authenticators/list).
|
815
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/authenticators/list-post).
|
811
816
|
|
812
817
|
Examples:
|
813
818
|
response = authn.user.authenticators.list(
|
@@ -850,7 +855,7 @@ class AuthN(ServiceBase):
|
|
850
855
|
Returns:
|
851
856
|
A PangeaResponse with a user and its information in the response.result field.
|
852
857
|
Available response fields can be found in our
|
853
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/profile/get).
|
858
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/profile/get-post).
|
854
859
|
|
855
860
|
Examples:
|
856
861
|
response = authn.user.profile.get(
|
@@ -864,7 +869,7 @@ class AuthN(ServiceBase):
|
|
864
869
|
|
865
870
|
def update(
|
866
871
|
self,
|
867
|
-
profile:
|
872
|
+
profile: Mapping[str, str],
|
868
873
|
id: str | None = None,
|
869
874
|
email: str | None = None,
|
870
875
|
*,
|
@@ -886,7 +891,7 @@ class AuthN(ServiceBase):
|
|
886
891
|
Returns:
|
887
892
|
A PangeaResponse with a user and its information in the response.result field.
|
888
893
|
Available response fields can be found in our
|
889
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/profile/update).
|
894
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/user#/v2/user/profile/update-post).
|
890
895
|
|
891
896
|
Examples:
|
892
897
|
response = authn.user.profile.update(
|
@@ -980,7 +985,7 @@ class AuthN(ServiceBase):
|
|
980
985
|
Returns:
|
981
986
|
A PangeaResponse with credentials for a login session in the response.result field.
|
982
987
|
Available response fields can be found in our
|
983
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/complete).
|
988
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/complete-post).
|
984
989
|
|
985
990
|
Examples:
|
986
991
|
response = authn.flow.complete(
|
@@ -991,7 +996,10 @@ class AuthN(ServiceBase):
|
|
991
996
|
return self.request.post("v2/flow/complete", m.FlowCompleteResult, data=input.model_dump(exclude_none=True))
|
992
997
|
|
993
998
|
def restart(
|
994
|
-
self,
|
999
|
+
self,
|
1000
|
+
flow_id: str,
|
1001
|
+
choice: m.FlowChoice,
|
1002
|
+
data: m.FlowRestartData = {}, # noqa: B006
|
995
1003
|
) -> PangeaResponse[m.FlowRestartResult]:
|
996
1004
|
"""
|
997
1005
|
Restart a sign-up/sign-in flow
|
@@ -1009,7 +1017,7 @@ class AuthN(ServiceBase):
|
|
1009
1017
|
A PangeaResponse with information about next steps needed
|
1010
1018
|
to complete a flow in the response.result field.
|
1011
1019
|
Available response fields can be found in our
|
1012
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/restart).
|
1020
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/restart-post).
|
1013
1021
|
|
1014
1022
|
Examples:
|
1015
1023
|
response = authn.flow.restart(
|
@@ -1046,7 +1054,7 @@ class AuthN(ServiceBase):
|
|
1046
1054
|
A PangeaResponse with information about next steps needed
|
1047
1055
|
to complete a flow in the response.result field.
|
1048
1056
|
Available response fields can be found in our
|
1049
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/start).
|
1057
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/start-post).
|
1050
1058
|
|
1051
1059
|
Examples:
|
1052
1060
|
response = authn.flow.start(
|
@@ -1062,7 +1070,10 @@ class AuthN(ServiceBase):
|
|
1062
1070
|
return self.request.post("v2/flow/start", m.FlowStartResult, data=input.model_dump(exclude_none=True))
|
1063
1071
|
|
1064
1072
|
def update(
|
1065
|
-
self,
|
1073
|
+
self,
|
1074
|
+
flow_id: str,
|
1075
|
+
choice: m.FlowChoice,
|
1076
|
+
data: m.FlowUpdateData = {}, # noqa: B006
|
1066
1077
|
) -> PangeaResponse[m.FlowUpdateResult]:
|
1067
1078
|
"""
|
1068
1079
|
Update a sign-up/sign-in flow
|
@@ -1080,7 +1091,7 @@ class AuthN(ServiceBase):
|
|
1080
1091
|
A PangeaResponse with information about next steps needed
|
1081
1092
|
to complete a flow in the response.result field.
|
1082
1093
|
Available response fields can be found in our
|
1083
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/update).
|
1094
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/flow#/v2/flow/update-post).
|
1084
1095
|
|
1085
1096
|
Examples:
|
1086
1097
|
response = authn.flow.update(
|
@@ -1125,7 +1136,7 @@ class AuthN(ServiceBase):
|
|
1125
1136
|
Returns:
|
1126
1137
|
A PangeaResponse with a EULA object in the response.result field.
|
1127
1138
|
Available response fields can be found in our
|
1128
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/agreements#/v2/agreements/create).
|
1139
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/agreements#/v2/agreements/create-post).
|
1129
1140
|
|
1130
1141
|
Examples:
|
1131
1142
|
response = authn.agreements.create(
|
@@ -1192,7 +1203,7 @@ class AuthN(ServiceBase):
|
|
1192
1203
|
Returns:
|
1193
1204
|
A PangeaResponse with a list of EULA objects in the response.result field.
|
1194
1205
|
Available response fields can be found in our
|
1195
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/agreements#/v2/agreements/list).
|
1206
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/agreements#/v2/agreements/list-post).
|
1196
1207
|
|
1197
1208
|
Examples:
|
1198
1209
|
response = authn.agreements.list()
|
@@ -1231,7 +1242,7 @@ class AuthN(ServiceBase):
|
|
1231
1242
|
Returns:
|
1232
1243
|
A PangeaResponse with the updated EULA object in the response.result field.
|
1233
1244
|
Available response fields can be found in our
|
1234
|
-
[API Documentation](https://pangea.cloud/docs/api/authn/agreements#/v2/agreements/update).
|
1245
|
+
[API Documentation](https://pangea.cloud/docs/api/authn/agreements#/v2/agreements/update-post).
|
1235
1246
|
|
1236
1247
|
Examples:
|
1237
1248
|
response = authn.agreements.update(
|
pangea/services/authn/models.py
CHANGED
@@ -1,68 +1,22 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
3
|
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
4
7
|
from __future__ import annotations
|
5
8
|
|
6
9
|
import enum
|
10
|
+
from collections.abc import Mapping
|
7
11
|
from typing import Dict, List, NewType, Optional, Union
|
8
|
-
from warnings import warn
|
9
|
-
|
10
|
-
from typing_extensions import deprecated
|
11
12
|
|
12
13
|
import pangea.services.intel as im
|
13
|
-
from pangea.deprecated import pangea_deprecated
|
14
14
|
from pangea.response import APIRequestModel, APIResponseModel, PangeaResponseResult
|
15
15
|
from pangea.services.vault.models.common import JWK, JWKec, JWKrsa
|
16
16
|
|
17
17
|
Scopes = NewType("Scopes", List[str])
|
18
18
|
|
19
19
|
|
20
|
-
class Profile(Dict[str, str]):
|
21
|
-
@property
|
22
|
-
def first_name(self) -> str:
|
23
|
-
warn(
|
24
|
-
'`Profile.first_name` is deprecated. Use `Profile["first_name"]` instead.', DeprecationWarning, stacklevel=2
|
25
|
-
)
|
26
|
-
return self["first_name"]
|
27
|
-
|
28
|
-
@first_name.setter
|
29
|
-
def first_name(self, value: str) -> None:
|
30
|
-
warn(
|
31
|
-
'`Profile.first_name` is deprecated. Use `Profile["first_name"]` instead.', DeprecationWarning, stacklevel=2
|
32
|
-
)
|
33
|
-
self["first_name"] = value
|
34
|
-
|
35
|
-
@property
|
36
|
-
def last_name(self) -> str:
|
37
|
-
warn('`Profile.last_name` is deprecated. Use `Profile["last_name"]` instead.', DeprecationWarning, stacklevel=2)
|
38
|
-
return self["last_name"]
|
39
|
-
|
40
|
-
@last_name.setter
|
41
|
-
def last_name(self, value: str) -> None:
|
42
|
-
warn('`Profile.last_name` is deprecated. Use `Profile["last_name"]` instead.', DeprecationWarning, stacklevel=2)
|
43
|
-
self["last_name"] = value
|
44
|
-
|
45
|
-
@property
|
46
|
-
def phone(self) -> str:
|
47
|
-
warn('`Profile.phone` is deprecated. Use `Profile["phone"]` instead.', DeprecationWarning, stacklevel=2)
|
48
|
-
return self["phone"]
|
49
|
-
|
50
|
-
@phone.setter
|
51
|
-
def phone(self, value: str) -> None:
|
52
|
-
warn('`Profile.phone` is deprecated. Use `Profile["phone"]` instead.', DeprecationWarning, stacklevel=2)
|
53
|
-
self["phone"] = value
|
54
|
-
|
55
|
-
@deprecated("`Profile.model_dump()` is deprecated. `Profile` is already a `dict[str, str]`.")
|
56
|
-
@pangea_deprecated(reason="`Profile` is already a `dict[str, str]`.")
|
57
|
-
def model_dump(self, *, exclude_none: bool = False) -> dict[str, str]:
|
58
|
-
warn(
|
59
|
-
"`Profile.model_dump()` is deprecated. `Profile` is already a `dict[str, str]`.",
|
60
|
-
DeprecationWarning,
|
61
|
-
stacklevel=2,
|
62
|
-
)
|
63
|
-
return self
|
64
|
-
|
65
|
-
|
66
20
|
class ClientPasswordChangeRequest(APIRequestModel):
|
67
21
|
token: str
|
68
22
|
old_password: str
|
@@ -105,7 +59,7 @@ class SessionToken(PangeaResponseResult):
|
|
105
59
|
identity: str
|
106
60
|
email: str
|
107
61
|
scopes: Optional[Scopes] = None
|
108
|
-
profile:
|
62
|
+
profile: dict[str, str]
|
109
63
|
created_at: str
|
110
64
|
intelligence: Optional[Intelligence] = None
|
111
65
|
|
@@ -245,7 +199,7 @@ class User(PangeaResponseResult):
|
|
245
199
|
username: str
|
246
200
|
"""A username."""
|
247
201
|
|
248
|
-
profile:
|
202
|
+
profile: dict[str, str]
|
249
203
|
"""A user profile as a collection of string properties."""
|
250
204
|
|
251
205
|
verified: bool
|
@@ -278,7 +232,7 @@ class UserCreateRequest(APIRequestModel):
|
|
278
232
|
email: str
|
279
233
|
"""An email address."""
|
280
234
|
|
281
|
-
profile:
|
235
|
+
profile: Mapping[str, str]
|
282
236
|
"""A user profile as a collection of string properties."""
|
283
237
|
|
284
238
|
username: Optional[str] = None
|
@@ -468,7 +422,7 @@ class UserProfileGetResult(User):
|
|
468
422
|
|
469
423
|
|
470
424
|
class UserProfileUpdateRequest(APIRequestModel):
|
471
|
-
profile:
|
425
|
+
profile: Mapping[str, str]
|
472
426
|
"""Updates to a user profile."""
|
473
427
|
|
474
428
|
id: Optional[str] = None
|
@@ -655,7 +609,7 @@ class FlowUpdateDataPassword(APIRequestModel):
|
|
655
609
|
|
656
610
|
|
657
611
|
class FlowUpdateDataProfile(APIRequestModel):
|
658
|
-
profile:
|
612
|
+
profile: dict[str, str]
|
659
613
|
|
660
614
|
|
661
615
|
class FlowUpdateDataProvisionalEnrollment(APIRequestModel):
|
@@ -777,7 +731,7 @@ class SessionItem(APIResponseModel):
|
|
777
731
|
expire: str
|
778
732
|
email: str
|
779
733
|
scopes: Optional[Scopes] = None
|
780
|
-
profile:
|
734
|
+
profile: dict[str, str]
|
781
735
|
created_at: str
|
782
736
|
active_token: Optional[SessionToken] = None
|
783
737
|
|
pangea/services/authz.py
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Use `list` instead of `List`.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
9
|
import enum
|
@@ -243,7 +247,7 @@ class AuthZ(ServiceBase):
|
|
243
247
|
Returns:
|
244
248
|
Pangea Response with empty result.
|
245
249
|
Available response fields can be found in our
|
246
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create).
|
250
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create-post).
|
247
251
|
|
248
252
|
Examples:
|
249
253
|
response = authz.tuple_create(
|
@@ -287,7 +291,7 @@ class AuthZ(ServiceBase):
|
|
287
291
|
Returns:
|
288
292
|
Pangea Response with a list of tuples and the last token.
|
289
293
|
Available response fields can be found in our
|
290
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list).
|
294
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list-post).
|
291
295
|
|
292
296
|
Examples:
|
293
297
|
authz.tuple_list(TupleListFilter(subject_type="user", subject_id="user_1"))
|
@@ -311,7 +315,7 @@ class AuthZ(ServiceBase):
|
|
311
315
|
Returns:
|
312
316
|
Pangea Response with empty result.
|
313
317
|
Available response fields can be found in our
|
314
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete).
|
318
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete-post).
|
315
319
|
|
316
320
|
Examples:
|
317
321
|
response = authz.tuple_delete(
|
@@ -353,7 +357,7 @@ class AuthZ(ServiceBase):
|
|
353
357
|
Returns:
|
354
358
|
Pangea Response with the result of the check.
|
355
359
|
Available response fields can be found in our
|
356
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/check).
|
360
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/check-post).
|
357
361
|
|
358
362
|
Examples:
|
359
363
|
response = authz.check(
|
@@ -387,7 +391,7 @@ class AuthZ(ServiceBase):
|
|
387
391
|
Returns:
|
388
392
|
Pangea Response with a list of resource IDs.
|
389
393
|
Available response fields can be found in our
|
390
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources).
|
394
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources-post).
|
391
395
|
|
392
396
|
Examples:
|
393
397
|
authz.list_resources(
|
@@ -422,7 +426,7 @@ class AuthZ(ServiceBase):
|
|
422
426
|
Returns:
|
423
427
|
Pangea Response with a list of subjects.
|
424
428
|
Available response fields can be found in our
|
425
|
-
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects).
|
429
|
+
[API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects-post).
|
426
430
|
|
427
431
|
Examples:
|
428
432
|
response = authz.list_subjects(
|
pangea/services/base.py
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
9
|
import copy
|
6
10
|
import logging
|
7
|
-
from typing import
|
11
|
+
from typing import Optional, Type, Union
|
8
12
|
|
9
13
|
from typing_extensions import TypeVar
|
10
14
|
|
@@ -17,7 +21,7 @@ from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
|
|
17
21
|
TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
|
18
22
|
|
19
23
|
|
20
|
-
class ServiceBase
|
24
|
+
class ServiceBase:
|
21
25
|
service_name: str = "base"
|
22
26
|
|
23
27
|
def __init__(
|
@@ -43,8 +47,7 @@ class ServiceBase(object):
|
|
43
47
|
self._token = token
|
44
48
|
self.config_id: Optional[str] = config_id
|
45
49
|
self._request: Optional[Union[PangeaRequest, PangeaRequestAsync]] = None
|
46
|
-
|
47
|
-
self.request.set_extra_headers(extra_headers)
|
50
|
+
self.request.set_extra_headers({})
|
48
51
|
|
49
52
|
@property
|
50
53
|
def token(self) -> str:
|