pangea-sdk 3.7.0__py3-none-any.whl → 3.8.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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/vault.py +29 -12
- pangea/utils.py +2 -3
- {pangea_sdk-3.7.0.dist-info → pangea_sdk-3.8.0.dist-info}/METADATA +33 -6
- pangea_sdk-3.8.0.dist-info/RECORD +46 -0
- pangea_sdk-3.7.0.dist-info/RECORD +0 -44
- {pangea_sdk-3.7.0.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
|