pangea-sdk 3.6.1__py3-none-any.whl → 3.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.
- pangea/__init__.py +1 -1
- pangea/asyncio/request.py +123 -32
- pangea/asyncio/services/__init__.py +1 -0
- pangea/asyncio/services/audit.py +236 -21
- pangea/asyncio/services/authn.py +79 -50
- pangea/asyncio/services/authz.py +259 -0
- pangea/asyncio/services/base.py +9 -6
- pangea/asyncio/services/file_scan.py +3 -4
- pangea/asyncio/services/intel.py +5 -6
- pangea/asyncio/services/redact.py +21 -3
- pangea/asyncio/services/vault.py +28 -12
- pangea/config.py +10 -18
- pangea/dump_audit.py +1 -0
- pangea/exceptions.py +8 -0
- pangea/request.py +164 -74
- pangea/response.py +63 -17
- pangea/services/__init__.py +1 -0
- pangea/services/audit/audit.py +241 -55
- pangea/services/audit/exceptions.py +1 -2
- pangea/services/audit/models.py +83 -21
- pangea/services/audit/signing.py +1 -0
- pangea/services/audit/util.py +1 -0
- pangea/services/authn/authn.py +38 -4
- pangea/services/authn/models.py +9 -9
- pangea/services/authz.py +377 -0
- pangea/services/base.py +34 -14
- pangea/services/embargo.py +1 -2
- pangea/services/file_scan.py +3 -4
- pangea/services/intel.py +3 -4
- pangea/services/redact.py +21 -3
- pangea/services/vault/models/common.py +15 -0
- pangea/services/vault/vault.py +29 -12
- pangea/utils.py +2 -3
- {pangea_sdk-3.6.1.dist-info → pangea_sdk-3.8.0.dist-info}/METADATA +36 -10
- pangea_sdk-3.8.0.dist-info/RECORD +46 -0
- pangea_sdk-3.6.1.dist-info/RECORD +0 -44
- {pangea_sdk-3.6.1.dist-info → pangea_sdk-3.8.0.dist-info}/WHEEL +0 -0
pangea/services/audit/models.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import datetime
|
4
6
|
import enum
|
5
|
-
from typing import Any, Dict, List, Optional, Union
|
7
|
+
from typing import Any, Dict, List, Optional, Sequence, Union
|
6
8
|
|
7
9
|
from pangea.response import APIRequestModel, APIResponseModel, PangeaResponseResult
|
8
10
|
|
@@ -19,14 +21,14 @@ class EventVerification(str, enum.Enum):
|
|
19
21
|
return str(self.value)
|
20
22
|
|
21
23
|
|
22
|
-
class Event(
|
24
|
+
class Event(Dict[str, Any]):
|
23
25
|
"""
|
24
26
|
Event to perform an auditable activity
|
25
27
|
|
26
28
|
Auxiliary class to be compatible with older SDKs
|
27
29
|
"""
|
28
30
|
|
29
|
-
def __init__(self, **data):
|
31
|
+
def __init__(self, **data) -> None:
|
30
32
|
super().__init__(**data)
|
31
33
|
|
32
34
|
@property
|
@@ -206,7 +208,7 @@ class SearchRestriction(APIResponseModel):
|
|
206
208
|
Arguments:
|
207
209
|
actor -- List of actors to include in search. If empty include all.
|
208
210
|
action -- List of action to include in search. If empty include all.
|
209
|
-
source -- List of
|
211
|
+
source -- List of sources to include in search. If empty include all.
|
210
212
|
status -- List of status to include in search. If empty include all.
|
211
213
|
target -- List of targets to include in search. If empty include all.
|
212
214
|
"""
|
@@ -279,7 +281,7 @@ class SearchRequest(APIRequestModel):
|
|
279
281
|
end: Optional[str] = None
|
280
282
|
limit: Optional[int] = None
|
281
283
|
max_results: Optional[int] = None
|
282
|
-
search_restriction: Optional[
|
284
|
+
search_restriction: Optional[Dict[str, Sequence[str]]] = None
|
283
285
|
verbose: Optional[bool] = None
|
284
286
|
|
285
287
|
|
@@ -373,7 +375,24 @@ class SearchEvent(APIResponseModel):
|
|
373
375
|
signature_verification: EventVerification = EventVerification.NONE
|
374
376
|
|
375
377
|
|
376
|
-
class
|
378
|
+
class SearchResultOutput(PangeaResponseResult):
|
379
|
+
"""
|
380
|
+
Return class after a pagination search
|
381
|
+
|
382
|
+
Arguments:
|
383
|
+
count -- The total number of results that were returned by the search.
|
384
|
+
events -- A list of matching audit records.
|
385
|
+
root -- A root of a Merkle Tree.
|
386
|
+
unpublished_root -- Root of a unpublished Merkle Tree
|
387
|
+
"""
|
388
|
+
|
389
|
+
count: int
|
390
|
+
events: List[SearchEvent]
|
391
|
+
root: Optional[Root] = None
|
392
|
+
unpublished_root: Optional[Root] = None
|
393
|
+
|
394
|
+
|
395
|
+
class SearchOutput(SearchResultOutput):
|
377
396
|
"""
|
378
397
|
Result class after an audit search action
|
379
398
|
|
@@ -386,12 +405,8 @@ class SearchOutput(PangeaResponseResult):
|
|
386
405
|
unpublished_root -- Root of a unpublished Merkle Tree
|
387
406
|
"""
|
388
407
|
|
389
|
-
count: int
|
390
|
-
events: List[SearchEvent]
|
391
408
|
id: str
|
392
409
|
expires_at: datetime.datetime
|
393
|
-
root: Optional[Root] = None
|
394
|
-
unpublished_root: Optional[Root] = None
|
395
410
|
|
396
411
|
|
397
412
|
class SearchResultRequest(APIRequestModel):
|
@@ -402,25 +417,72 @@ class SearchResultRequest(APIRequestModel):
|
|
402
417
|
id -- A search results identifier returned by the search call.
|
403
418
|
limit -- Number of audit records to include from the first page of the results.
|
404
419
|
offset -- Offset from the start of the result set to start returning results from.
|
420
|
+
assert_search_restriction -- Assert the requested search results were queried with the exact same search restrictions, to ensure the results comply to the expected restrictions.
|
405
421
|
"""
|
406
422
|
|
407
423
|
id: str
|
408
424
|
limit: Optional[int] = 20
|
409
425
|
offset: Optional[int] = 0
|
426
|
+
assert_search_restriction: Optional[Dict[str, Sequence[str]]] = None
|
410
427
|
|
411
428
|
|
412
|
-
class
|
429
|
+
class DownloadFormat(str, enum.Enum):
|
430
|
+
JSON = "json"
|
431
|
+
"""JSON."""
|
432
|
+
|
433
|
+
CSV = "csv"
|
434
|
+
"""CSV."""
|
435
|
+
|
436
|
+
def __str__(self):
|
437
|
+
return str(self.value)
|
438
|
+
|
439
|
+
def __repr__(self):
|
440
|
+
return str(self.value)
|
441
|
+
|
442
|
+
|
443
|
+
class DownloadRequest(APIRequestModel):
|
444
|
+
request_id: Optional[str] = None
|
445
|
+
"""ID returned by the export API."""
|
446
|
+
|
447
|
+
result_id: Optional[str] = None
|
448
|
+
"""ID returned by the search API."""
|
449
|
+
|
450
|
+
format: Optional[str] = None
|
451
|
+
"""Format for the records."""
|
452
|
+
|
453
|
+
|
454
|
+
class DownloadResult(PangeaResponseResult):
|
455
|
+
dest_url: str
|
456
|
+
"""URL where search results can be downloaded."""
|
457
|
+
|
458
|
+
expires_at: str
|
459
|
+
"""
|
460
|
+
The time when the results will no longer be available to page through via
|
461
|
+
the results API.
|
413
462
|
"""
|
414
|
-
Return class after a pagination search
|
415
463
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
464
|
+
|
465
|
+
class ExportRequest(APIRequestModel):
|
466
|
+
format: DownloadFormat = DownloadFormat.CSV
|
467
|
+
"""Format for the records."""
|
468
|
+
|
469
|
+
start: Optional[datetime.datetime] = None
|
470
|
+
"""The start of the time range to perform the search on."""
|
471
|
+
|
472
|
+
end: Optional[datetime.datetime] = None
|
473
|
+
"""
|
474
|
+
The end of the time range to perform the search on. If omitted, then all
|
475
|
+
records up to the latest will be searched.
|
421
476
|
"""
|
422
477
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
478
|
+
order_by: Optional[str] = None
|
479
|
+
"""Name of column to sort the results by."""
|
480
|
+
|
481
|
+
order: Optional[SearchOrder] = None
|
482
|
+
"""Specify the sort order of the response."""
|
483
|
+
|
484
|
+
verbose: bool = True
|
485
|
+
"""
|
486
|
+
Whether or not to include the root hash of the tree and the membership proof
|
487
|
+
for each record.
|
488
|
+
"""
|
pangea/services/audit/signing.py
CHANGED
@@ -7,6 +7,7 @@ from cryptography import exceptions
|
|
7
7
|
from cryptography.hazmat.primitives import serialization
|
8
8
|
from cryptography.hazmat.primitives.asymmetric import ed25519
|
9
9
|
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes, PublicKeyTypes
|
10
|
+
|
10
11
|
from pangea.exceptions import PangeaException
|
11
12
|
from pangea.services.audit.util import b64decode, b64decode_ascii, b64encode_ascii
|
12
13
|
from pangea.services.vault.models.common import AsymmetricAlgorithm
|
pangea/services/audit/util.py
CHANGED
pangea/services/authn/authn.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
3
4
|
|
4
5
|
from typing import Dict, List, Optional, Union
|
5
6
|
|
6
7
|
import pangea.services.authn.models as m
|
8
|
+
from pangea.config import PangeaConfig
|
7
9
|
from pangea.response import PangeaResponse
|
8
10
|
from pangea.services.base import ServiceBase
|
9
11
|
|
@@ -37,10 +39,24 @@ class AuthN(ServiceBase):
|
|
37
39
|
|
38
40
|
def __init__(
|
39
41
|
self,
|
40
|
-
token,
|
41
|
-
config=None,
|
42
|
-
logger_name="pangea",
|
43
|
-
):
|
42
|
+
token: str,
|
43
|
+
config: PangeaConfig | None = None,
|
44
|
+
logger_name: str = "pangea",
|
45
|
+
) -> None:
|
46
|
+
"""
|
47
|
+
AuthN client
|
48
|
+
|
49
|
+
Initializes a new AuthN client.
|
50
|
+
|
51
|
+
Args:
|
52
|
+
token: Pangea API token.
|
53
|
+
config: Configuration.
|
54
|
+
logger_name: Logger name.
|
55
|
+
|
56
|
+
Examples:
|
57
|
+
config = PangeaConfig(domain="pangea_domain")
|
58
|
+
authn = AuthN(token="pangea_token", config=config)
|
59
|
+
"""
|
44
60
|
super().__init__(token, config, logger_name=logger_name)
|
45
61
|
self.user = AuthN.User(token, config, logger_name=logger_name)
|
46
62
|
self.flow = AuthN.Flow(token, config, logger_name=logger_name)
|
@@ -113,6 +129,10 @@ class AuthN(ServiceBase):
|
|
113
129
|
Examples:
|
114
130
|
response = authn.session.list()
|
115
131
|
"""
|
132
|
+
|
133
|
+
if isinstance(filter, dict):
|
134
|
+
filter = m.SessionListFilter(**filter)
|
135
|
+
|
116
136
|
input = m.SessionListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
|
117
137
|
return self.request.post("v2/session/list", m.SessionListResults, data=input.dict(exclude_none=True))
|
118
138
|
|
@@ -267,6 +287,10 @@ class AuthN(ServiceBase):
|
|
267
287
|
token="ptu_wuk7tvtpswyjtlsx52b7yyi2l7zotv4a",
|
268
288
|
)
|
269
289
|
"""
|
290
|
+
|
291
|
+
if isinstance(filter, dict):
|
292
|
+
filter = m.SessionListFilter(**filter)
|
293
|
+
|
270
294
|
input = m.ClientSessionListRequest(
|
271
295
|
token=token, filter=filter, last=last, order=order, order_by=order_by, size=size
|
272
296
|
)
|
@@ -589,6 +613,10 @@ class AuthN(ServiceBase):
|
|
589
613
|
Examples:
|
590
614
|
response = authn.user.list()
|
591
615
|
"""
|
616
|
+
|
617
|
+
if isinstance(filter, dict):
|
618
|
+
filter = m.UserListFilter(**filter)
|
619
|
+
|
592
620
|
input = m.UserListRequest(
|
593
621
|
filter=filter,
|
594
622
|
last=last,
|
@@ -638,6 +666,9 @@ class AuthN(ServiceBase):
|
|
638
666
|
Examples:
|
639
667
|
response = authn.user.invites.list()
|
640
668
|
"""
|
669
|
+
if isinstance(filter, dict):
|
670
|
+
filter = m.UserInviteListFilter(**filter)
|
671
|
+
|
641
672
|
input = m.UserInviteListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
|
642
673
|
return self.request.post(
|
643
674
|
"v2/user/invite/list", m.UserInviteListResult, data=input.dict(exclude_none=True)
|
@@ -1061,6 +1092,9 @@ class AuthN(ServiceBase):
|
|
1061
1092
|
response = authn.agreements.list()
|
1062
1093
|
"""
|
1063
1094
|
|
1095
|
+
if isinstance(filter, dict):
|
1096
|
+
filter = m.AgreementListFilter(**filter)
|
1097
|
+
|
1064
1098
|
input = m.AgreementListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
|
1065
1099
|
return self.request.post("v2/agreements/list", m.AgreementListResult, data=input.dict(exclude_none=True))
|
1066
1100
|
|
pangea/services/authn/models.py
CHANGED
@@ -51,7 +51,7 @@ class Intelligence(PangeaResponseResult):
|
|
51
51
|
user_intel: bool
|
52
52
|
|
53
53
|
|
54
|
-
class SessionToken(
|
54
|
+
class SessionToken(PangeaResponseResult):
|
55
55
|
id: str
|
56
56
|
type: str
|
57
57
|
life: int
|
@@ -68,8 +68,8 @@ class LoginToken(SessionToken):
|
|
68
68
|
token: str
|
69
69
|
|
70
70
|
|
71
|
-
class ClientTokenCheckResult(
|
72
|
-
|
71
|
+
class ClientTokenCheckResult(SessionToken):
|
72
|
+
token: Optional[str]
|
73
73
|
|
74
74
|
|
75
75
|
class IDProvider(str, enum.Enum):
|
@@ -234,7 +234,7 @@ class UserListFilter(APIRequestModel):
|
|
234
234
|
|
235
235
|
|
236
236
|
class UserListRequest(APIRequestModel):
|
237
|
-
filter: Optional[
|
237
|
+
filter: Optional[UserListFilter] = None
|
238
238
|
last: Optional[str] = None
|
239
239
|
order: Optional[ItemOrder] = None
|
240
240
|
order_by: Optional[UserListOrderBy] = None
|
@@ -289,7 +289,7 @@ class UserInviterOrderBy(enum.Enum):
|
|
289
289
|
|
290
290
|
|
291
291
|
class UserInviteListFilter(APIRequestModel):
|
292
|
-
callback: Optional[str]
|
292
|
+
callback: Optional[str]
|
293
293
|
callback__contains: Optional[List[str]] = None
|
294
294
|
callback__in: Optional[List[str]] = None
|
295
295
|
created_at: Optional[str] = None
|
@@ -322,7 +322,7 @@ class UserInviteListFilter(APIRequestModel):
|
|
322
322
|
|
323
323
|
|
324
324
|
class UserInviteListRequest(APIRequestModel):
|
325
|
-
filter: Optional[
|
325
|
+
filter: Optional[UserInviteListFilter] = None
|
326
326
|
last: Optional[str] = None
|
327
327
|
order: Optional[ItemOrder] = None
|
328
328
|
order_by: Optional[UserInviterOrderBy] = None
|
@@ -607,7 +607,7 @@ class SessionListFilter(APIRequestModel):
|
|
607
607
|
|
608
608
|
class ClientSessionListRequest(APIRequestModel):
|
609
609
|
token: str
|
610
|
-
filter: Optional[
|
610
|
+
filter: Optional[SessionListFilter] = None
|
611
611
|
last: Optional[str] = None
|
612
612
|
order: Optional[ItemOrder] = None
|
613
613
|
order_by: Optional[SessionListOrderBy] = None
|
@@ -663,7 +663,7 @@ class SessionInvalidateResult(PangeaResponseResult):
|
|
663
663
|
|
664
664
|
|
665
665
|
class SessionListRequest(APIRequestModel):
|
666
|
-
filter: Optional[
|
666
|
+
filter: Optional[SessionListFilter] = None
|
667
667
|
last: Optional[str] = None
|
668
668
|
order: Optional[ItemOrder] = None
|
669
669
|
order_by: Optional[SessionListOrderBy] = None
|
@@ -760,7 +760,7 @@ class AgreementListFilter(APIRequestModel):
|
|
760
760
|
|
761
761
|
|
762
762
|
class AgreementListRequest(APIRequestModel):
|
763
|
-
filter: Optional[
|
763
|
+
filter: Optional[AgreementListFilter] = None
|
764
764
|
last: Optional[str] = None
|
765
765
|
order: Optional[ItemOrder] = None
|
766
766
|
order_by: Optional[AgreementListOrderBy] = None
|