pangea-sdk 6.2.0b2__py3-none-any.whl → 6.3.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 +25 -154
- pangea/asyncio/services/__init__.py +0 -1
- pangea/asyncio/services/ai_guard.py +9 -101
- pangea/asyncio/services/audit.py +1 -301
- pangea/asyncio/services/authn.py +7 -9
- pangea/asyncio/services/authz.py +45 -11
- pangea/asyncio/services/intel.py +20 -26
- pangea/asyncio/services/prompt_guard.py +2 -112
- pangea/asyncio/services/redact.py +4 -265
- pangea/asyncio/services/vault.py +52 -40
- pangea/request.py +30 -167
- pangea/response.py +6 -6
- pangea/services/__init__.py +0 -1
- pangea/services/ai_guard.py +20 -490
- pangea/services/audit/audit.py +2 -301
- pangea/services/audit/models.py +65 -307
- pangea/services/authn/authn.py +6 -8
- pangea/services/authn/models.py +183 -151
- pangea/services/authz.py +101 -57
- pangea/services/base.py +2 -3
- pangea/services/intel.py +32 -19
- pangea/services/prompt_guard.py +2 -193
- pangea/services/redact.py +7 -473
- pangea/services/vault/models/common.py +11 -12
- pangea/services/vault/models/keys.py +4 -9
- pangea/services/vault/models/secret.py +3 -8
- pangea/services/vault/vault.py +52 -40
- {pangea_sdk-6.2.0b2.dist-info → pangea_sdk-6.3.0.dist-info}/METADATA +34 -15
- pangea_sdk-6.3.0.dist-info/RECORD +60 -0
- pangea/asyncio/services/management.py +0 -576
- pangea/services/management.py +0 -720
- pangea_sdk-6.2.0b2.dist-info/RECORD +0 -62
- {pangea_sdk-6.2.0b2.dist-info → pangea_sdk-6.3.0.dist-info}/WHEEL +0 -0
pangea/asyncio/services/vault.py
CHANGED
@@ -59,7 +59,6 @@ from pangea.services.vault.models.common import (
|
|
59
59
|
JWTVerifyResult,
|
60
60
|
ListRequest,
|
61
61
|
ListResult,
|
62
|
-
Metadata,
|
63
62
|
PangeaToken,
|
64
63
|
PangeaTokenRotateRequest,
|
65
64
|
RequestManualRotationState,
|
@@ -319,7 +318,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
319
318
|
*,
|
320
319
|
name: str | None = None,
|
321
320
|
folder: str | None = None,
|
322
|
-
metadata:
|
321
|
+
metadata: Mapping[str, str] | None = None,
|
323
322
|
tags: Tags | None = None,
|
324
323
|
disabled_at: str | None = None,
|
325
324
|
enabled: bool | None = None,
|
@@ -395,7 +394,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
395
394
|
result_class: type[TResult] = SecretStoreResult, # type: ignore[assignment]
|
396
395
|
name: str | None = None,
|
397
396
|
folder: str | None = None,
|
398
|
-
metadata:
|
397
|
+
metadata: Mapping[str, str] | None = None,
|
399
398
|
tags: Tags | None = None,
|
400
399
|
disabled_at: datetime.datetime | None = None,
|
401
400
|
**kwargs: Any,
|
@@ -420,22 +419,22 @@ class VaultAsync(ServiceBaseAsync):
|
|
420
419
|
*,
|
421
420
|
name: str | None = None,
|
422
421
|
folder: str | None = None,
|
423
|
-
metadata:
|
422
|
+
metadata: Mapping[str, str] | None = None,
|
424
423
|
tags: Tags | None = None,
|
425
424
|
disabled_at: datetime.datetime | None = None,
|
426
425
|
) -> PangeaResponse[Secret]:
|
427
426
|
"""
|
428
427
|
Store secret
|
429
428
|
|
430
|
-
Store a secret.
|
429
|
+
Store a secret as a Vault item.
|
431
430
|
|
432
431
|
Args:
|
433
|
-
secret:
|
434
|
-
name:
|
435
|
-
folder:
|
436
|
-
metadata:
|
437
|
-
tags:
|
438
|
-
disabled_at: Timestamp indicating when the item will be disabled
|
432
|
+
secret: Secret value
|
433
|
+
name: Name of the item
|
434
|
+
folder: Folder where the item is stored
|
435
|
+
metadata: Metadata provided by the user
|
436
|
+
tags: List of user-defined tags
|
437
|
+
disabled_at: Timestamp indicating when the item will be disabled
|
439
438
|
|
440
439
|
Raises:
|
441
440
|
PangeaAPIException: If an API Error happens
|
@@ -461,25 +460,38 @@ class VaultAsync(ServiceBaseAsync):
|
|
461
460
|
*,
|
462
461
|
name: str | None = None,
|
463
462
|
folder: str | None = None,
|
464
|
-
metadata:
|
463
|
+
metadata: Mapping[str, str] | None = None,
|
465
464
|
tags: Tags | None = None,
|
466
465
|
disabled_at: datetime.datetime | None = None,
|
467
466
|
rotation_frequency: str | None = None,
|
468
|
-
rotation_state:
|
467
|
+
rotation_state: Literal["deactivated", "destroyed", "inherited"] | None = None,
|
469
468
|
rotation_grace_period: str | None = None,
|
470
469
|
) -> PangeaResponse[PangeaToken]:
|
471
470
|
"""
|
472
471
|
Store secret
|
473
472
|
|
474
|
-
Store a Pangea token.
|
473
|
+
Store a Pangea token as a Vault item.
|
475
474
|
|
476
475
|
Args:
|
477
|
-
token:
|
478
|
-
name:
|
479
|
-
folder:
|
480
|
-
metadata:
|
481
|
-
tags:
|
482
|
-
disabled_at: Timestamp indicating when the item will be disabled
|
476
|
+
token: Pangea token value
|
477
|
+
name: Name of the item
|
478
|
+
folder: Folder where the item is stored
|
479
|
+
metadata: Metadata provided by the user
|
480
|
+
tags: List of user-defined tags
|
481
|
+
disabled_at: Timestamp indicating when the item will be disabled
|
482
|
+
rotation_frequency: Time interval between item rotations, provided
|
483
|
+
as a positive number followed by a time unit: `secs`, `mins`, `hrs`,
|
484
|
+
`days`, `weeks`, `months`, or `years`. You can use abbreviations
|
485
|
+
like `1d`. Omit to inherit from the parent folder or default
|
486
|
+
settings. Set to `never` to disable rotation.
|
487
|
+
rotation_state: Target state for the previous version after
|
488
|
+
rotation. Set to `inherited` to inherit from the parent folder
|
489
|
+
or default settings.
|
490
|
+
rotation_grace_period: Grace period for the previous version,
|
491
|
+
provided as a positive number followed by a time unit: `secs`,
|
492
|
+
`mins`, `hrs`, `days`, `weeks`, `months`, or `years`. You can use
|
493
|
+
abbreviations like `1d`. Omit to inherit from the parent folder or
|
494
|
+
default settings.
|
483
495
|
|
484
496
|
Raises:
|
485
497
|
PangeaAPIException: If an API Error happens
|
@@ -510,7 +522,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
510
522
|
*,
|
511
523
|
name: str | None = None,
|
512
524
|
folder: str | None = None,
|
513
|
-
metadata:
|
525
|
+
metadata: Mapping[str, str] | None = None,
|
514
526
|
tags: Tags | None = None,
|
515
527
|
disabled_at: datetime.datetime | None = None,
|
516
528
|
rotation_frequency: str | None = None,
|
@@ -672,7 +684,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
672
684
|
algorithm: AsymmetricKeySigningAlgorithm,
|
673
685
|
name: str | None = None,
|
674
686
|
folder: str | None = None,
|
675
|
-
metadata:
|
687
|
+
metadata: Mapping[str, str] | None = None,
|
676
688
|
tags: Tags | None = None,
|
677
689
|
rotation_frequency: str | None = None,
|
678
690
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -718,7 +730,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
718
730
|
algorithm: AsymmetricKeyEncryptionAlgorithm,
|
719
731
|
name: str | None = None,
|
720
732
|
folder: str | None = None,
|
721
|
-
metadata:
|
733
|
+
metadata: Mapping[str, str] | None = None,
|
722
734
|
tags: Tags | None = None,
|
723
735
|
rotation_frequency: str | None = None,
|
724
736
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -764,7 +776,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
764
776
|
algorithm: AsymmetricKeyJwtAlgorithm,
|
765
777
|
name: str | None = None,
|
766
778
|
folder: str | None = None,
|
767
|
-
metadata:
|
779
|
+
metadata: Mapping[str, str] | None = None,
|
768
780
|
tags: Tags | None = None,
|
769
781
|
rotation_frequency: str | None = None,
|
770
782
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -810,7 +822,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
810
822
|
algorithm: AsymmetricKeyPkiAlgorithm,
|
811
823
|
name: str | None = None,
|
812
824
|
folder: str | None = None,
|
813
|
-
metadata:
|
825
|
+
metadata: Mapping[str, str] | None = None,
|
814
826
|
tags: Tags | None = None,
|
815
827
|
rotation_frequency: str | None = None,
|
816
828
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -856,7 +868,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
856
868
|
algorithm: AsymmetricKeyAlgorithm,
|
857
869
|
name: str | None = None,
|
858
870
|
folder: str | None = None,
|
859
|
-
metadata:
|
871
|
+
metadata: Mapping[str, str] | None = None,
|
860
872
|
tags: Tags | None = None,
|
861
873
|
rotation_frequency: str | None = None,
|
862
874
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -902,7 +914,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
902
914
|
algorithm: SymmetricKeyEncryptionAlgorithm,
|
903
915
|
name: str | None = None,
|
904
916
|
folder: str | None = None,
|
905
|
-
metadata:
|
917
|
+
metadata: Mapping[str, str] | None = None,
|
906
918
|
tags: Tags | None = None,
|
907
919
|
rotation_frequency: str | None = None,
|
908
920
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -948,7 +960,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
948
960
|
algorithm: SymmetricKeyJwtAlgorithm,
|
949
961
|
name: str | None = None,
|
950
962
|
folder: str | None = None,
|
951
|
-
metadata:
|
963
|
+
metadata: Mapping[str, str] | None = None,
|
952
964
|
tags: Tags | None = None,
|
953
965
|
rotation_frequency: str | None = None,
|
954
966
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -994,7 +1006,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
994
1006
|
algorithm: SymmetricKeyFpeAlgorithm,
|
995
1007
|
name: str | None = None,
|
996
1008
|
folder: str | None = None,
|
997
|
-
metadata:
|
1009
|
+
metadata: Mapping[str, str] | None = None,
|
998
1010
|
tags: Tags | None = None,
|
999
1011
|
rotation_frequency: str | None = None,
|
1000
1012
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1040,7 +1052,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1040
1052
|
algorithm: SymmetricKeyAlgorithm,
|
1041
1053
|
name: str | None = None,
|
1042
1054
|
folder: str | None = None,
|
1043
|
-
metadata:
|
1055
|
+
metadata: Mapping[str, str] | None = None,
|
1044
1056
|
tags: Tags | None = None,
|
1045
1057
|
rotation_frequency: str | None = None,
|
1046
1058
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1085,7 +1097,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1085
1097
|
algorithm: AsymmetricKeyAlgorithm | SymmetricKeyAlgorithm,
|
1086
1098
|
name: str | None = None,
|
1087
1099
|
folder: str | None = None,
|
1088
|
-
metadata:
|
1100
|
+
metadata: Mapping[str, str] | None = None,
|
1089
1101
|
tags: Tags | None = None,
|
1090
1102
|
rotation_frequency: str | None = None,
|
1091
1103
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1151,7 +1163,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1151
1163
|
private_key: str,
|
1152
1164
|
name: str | None = None,
|
1153
1165
|
folder: str | None = None,
|
1154
|
-
metadata:
|
1166
|
+
metadata: Mapping[str, str] | None = None,
|
1155
1167
|
tags: Tags | None = None,
|
1156
1168
|
rotation_frequency: str | None = None,
|
1157
1169
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1201,7 +1213,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1201
1213
|
private_key: str,
|
1202
1214
|
name: str | None = None,
|
1203
1215
|
folder: str | None = None,
|
1204
|
-
metadata:
|
1216
|
+
metadata: Mapping[str, str] | None = None,
|
1205
1217
|
tags: Tags | None = None,
|
1206
1218
|
rotation_frequency: str | None = None,
|
1207
1219
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1251,7 +1263,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1251
1263
|
private_key: str,
|
1252
1264
|
name: str | None = None,
|
1253
1265
|
folder: str | None = None,
|
1254
|
-
metadata:
|
1266
|
+
metadata: Mapping[str, str] | None = None,
|
1255
1267
|
tags: Tags | None = None,
|
1256
1268
|
rotation_frequency: str | None = None,
|
1257
1269
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1301,7 +1313,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1301
1313
|
private_key: str,
|
1302
1314
|
name: str | None = None,
|
1303
1315
|
folder: str | None = None,
|
1304
|
-
metadata:
|
1316
|
+
metadata: Mapping[str, str] | None = None,
|
1305
1317
|
tags: Tags | None = None,
|
1306
1318
|
rotation_frequency: str | None = None,
|
1307
1319
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1350,7 +1362,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1350
1362
|
key: str,
|
1351
1363
|
name: str | None = None,
|
1352
1364
|
folder: str | None = None,
|
1353
|
-
metadata:
|
1365
|
+
metadata: Mapping[str, str] | None = None,
|
1354
1366
|
tags: Tags | None = None,
|
1355
1367
|
rotation_frequency: str | None = None,
|
1356
1368
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1398,7 +1410,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1398
1410
|
key: str,
|
1399
1411
|
name: str | None = None,
|
1400
1412
|
folder: str | None = None,
|
1401
|
-
metadata:
|
1413
|
+
metadata: Mapping[str, str] | None = None,
|
1402
1414
|
tags: Tags | None = None,
|
1403
1415
|
rotation_frequency: str | None = None,
|
1404
1416
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1446,7 +1458,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1446
1458
|
key: str,
|
1447
1459
|
name: str | None = None,
|
1448
1460
|
folder: str | None = None,
|
1449
|
-
metadata:
|
1461
|
+
metadata: Mapping[str, str] | None = None,
|
1450
1462
|
tags: Tags | None = None,
|
1451
1463
|
rotation_frequency: str | None = None,
|
1452
1464
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1503,7 +1515,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1503
1515
|
key: str | None = None,
|
1504
1516
|
name: str | None = None,
|
1505
1517
|
folder: str | None = None,
|
1506
|
-
metadata:
|
1518
|
+
metadata: Mapping[str, str] | None = None,
|
1507
1519
|
tags: Tags | None = None,
|
1508
1520
|
rotation_frequency: str | None = None,
|
1509
1521
|
rotation_state: RequestRotationState | None = RequestRotationState.INHERITED,
|
@@ -1941,7 +1953,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1941
1953
|
name: str,
|
1942
1954
|
folder: str,
|
1943
1955
|
*,
|
1944
|
-
metadata:
|
1956
|
+
metadata: Mapping[str, str] | None = None,
|
1945
1957
|
tags: Tags | None = None,
|
1946
1958
|
rotation_frequency: str | None = None,
|
1947
1959
|
rotation_state: RequestRotationState = RequestRotationState.INHERITED,
|
pangea/request.py
CHANGED
@@ -11,14 +11,14 @@ import json
|
|
11
11
|
import logging
|
12
12
|
import time
|
13
13
|
from collections.abc import Iterable, Mapping
|
14
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union, cast
|
14
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union, cast
|
15
15
|
|
16
16
|
import requests
|
17
|
-
from pydantic import BaseModel
|
17
|
+
from pydantic import BaseModel
|
18
18
|
from pydantic_core import to_jsonable_python
|
19
19
|
from requests.adapters import HTTPAdapter, Retry
|
20
20
|
from requests_toolbelt import MultipartDecoder # type: ignore[import-untyped]
|
21
|
-
from typing_extensions import
|
21
|
+
from typing_extensions import TypeAlias, TypeVar, override
|
22
22
|
from yarl import URL
|
23
23
|
|
24
24
|
import pangea
|
@@ -43,6 +43,8 @@ _FileSpecTuple4: TypeAlias = tuple[_FileName, _FileContent, _FileContentType, _F
|
|
43
43
|
_FileSpec: TypeAlias = Union[_FileContent, _FileSpecTuple2, _FileSpecTuple3, _FileSpecTuple4]
|
44
44
|
_Files: TypeAlias = Union[Mapping[str, _FileSpec], Iterable[tuple[str, _FileSpec]]]
|
45
45
|
|
46
|
+
_HeadersUpdateMapping: TypeAlias = Mapping[str, str]
|
47
|
+
|
46
48
|
|
47
49
|
class MultipartResponse:
|
48
50
|
pangea_json: Dict[str, str]
|
@@ -66,7 +68,7 @@ class PangeaRequestBase:
|
|
66
68
|
self._queued_retry_enabled = config.queued_retry_enabled
|
67
69
|
|
68
70
|
# Custom headers
|
69
|
-
self._extra_headers:
|
71
|
+
self._extra_headers: _HeadersUpdateMapping = {}
|
70
72
|
self._user_agent = ""
|
71
73
|
|
72
74
|
self.set_custom_user_agent(config.custom_user_agent)
|
@@ -81,18 +83,17 @@ class PangeaRequestBase:
|
|
81
83
|
|
82
84
|
return self._session
|
83
85
|
|
84
|
-
def set_extra_headers(self, headers:
|
86
|
+
def set_extra_headers(self, headers: _HeadersUpdateMapping):
|
85
87
|
"""Sets any additional headers in the request.
|
86
88
|
|
87
89
|
Args:
|
88
|
-
headers
|
90
|
+
headers: key-value pairs containing extra headers to set
|
89
91
|
|
90
92
|
Example:
|
91
93
|
set_extra_headers({ "My-Header" : "foobar" })
|
92
94
|
"""
|
93
95
|
|
94
|
-
|
95
|
-
self._extra_headers = headers
|
96
|
+
self._extra_headers = headers
|
96
97
|
|
97
98
|
def set_custom_user_agent(self, user_agent: Optional[str]):
|
98
99
|
self.config.custom_user_agent = user_agent
|
@@ -129,17 +130,14 @@ class PangeaRequestBase:
|
|
129
130
|
url = URL(self.config.base_url_template.format(SERVICE_NAME=self.service))
|
130
131
|
return str(url / path)
|
131
132
|
|
132
|
-
def _headers(self) -> dict:
|
133
|
-
|
134
|
-
|
133
|
+
def _headers(self) -> dict[str, str]:
|
134
|
+
return {
|
135
|
+
**self._extra_headers,
|
135
136
|
"Authorization": f"Bearer {self.token}",
|
136
137
|
"Content-Type": "application/json",
|
138
|
+
"User-Agent": self._user_agent,
|
137
139
|
}
|
138
140
|
|
139
|
-
# We want to ignore previous headers if user tried to set them, so we will overwrite them.
|
140
|
-
self._extra_headers.update(headers)
|
141
|
-
return self._extra_headers
|
142
|
-
|
143
141
|
def _get_filename_from_content_disposition(self, content_disposition: str) -> Optional[str]:
|
144
142
|
filename_parts = content_disposition.split("name=")
|
145
143
|
if len(filename_parts) > 1:
|
@@ -222,24 +220,6 @@ class PangeaRequest(PangeaRequestBase):
|
|
222
220
|
def __del__(self) -> None:
|
223
221
|
self.session.close()
|
224
222
|
|
225
|
-
def delete(self, endpoint: str) -> None:
|
226
|
-
"""
|
227
|
-
Makes a DELETE call to a Pangea endpoint.
|
228
|
-
|
229
|
-
Args:
|
230
|
-
endpoint: The Pangea API endpoint.
|
231
|
-
"""
|
232
|
-
|
233
|
-
url = self._url(endpoint)
|
234
|
-
|
235
|
-
self.logger.debug(
|
236
|
-
json.dumps({"service": self.service, "action": "delete", "url": url}, default=default_encoder)
|
237
|
-
)
|
238
|
-
|
239
|
-
requests_response = self._http_delete(url, headers=self._headers())
|
240
|
-
self._check_http_errors(requests_response)
|
241
|
-
|
242
|
-
@overload
|
243
223
|
def post(
|
244
224
|
self,
|
245
225
|
endpoint: str,
|
@@ -248,62 +228,18 @@ class PangeaRequest(PangeaRequestBase):
|
|
248
228
|
files: Optional[list[Tuple]] = None,
|
249
229
|
poll_result: bool = True,
|
250
230
|
url: Optional[str] = None,
|
251
|
-
*,
|
252
|
-
pangea_response: Literal[True] = True,
|
253
231
|
) -> PangeaResponse[TResult]:
|
254
|
-
"""
|
255
|
-
Makes the POST call to a Pangea Service endpoint.
|
232
|
+
"""Makes the POST call to a Pangea Service endpoint.
|
256
233
|
|
257
234
|
Args:
|
258
|
-
endpoint: The Pangea Service API endpoint.
|
259
|
-
data: The POST body payload object
|
235
|
+
endpoint(str): The Pangea Service API endpoint.
|
236
|
+
data(dict): The POST body payload object
|
260
237
|
|
261
238
|
Returns:
|
262
239
|
PangeaResponse which contains the response in its entirety and
|
263
240
|
various properties to retrieve individual fields
|
264
241
|
"""
|
265
242
|
|
266
|
-
@overload
|
267
|
-
def post(
|
268
|
-
self,
|
269
|
-
endpoint: str,
|
270
|
-
result_class: Type[TResult],
|
271
|
-
data: str | BaseModel | Mapping[str, Any] | None = None,
|
272
|
-
files: Optional[list[Tuple]] = None,
|
273
|
-
poll_result: bool = True,
|
274
|
-
url: Optional[str] = None,
|
275
|
-
*,
|
276
|
-
pangea_response: Literal[False],
|
277
|
-
) -> TResult:
|
278
|
-
"""
|
279
|
-
Makes the POST call to a Pangea Service endpoint.
|
280
|
-
|
281
|
-
Args:
|
282
|
-
endpoint: The Pangea Service API endpoint.
|
283
|
-
data: The POST body payload object
|
284
|
-
"""
|
285
|
-
|
286
|
-
def post(
|
287
|
-
self,
|
288
|
-
endpoint: str,
|
289
|
-
result_class: Type[TResult],
|
290
|
-
data: str | BaseModel | Mapping[str, Any] | None = None,
|
291
|
-
files: Optional[list[Tuple]] = None,
|
292
|
-
poll_result: bool = True,
|
293
|
-
url: Optional[str] = None,
|
294
|
-
*,
|
295
|
-
pangea_response: bool = True,
|
296
|
-
) -> PangeaResponse[TResult] | TResult:
|
297
|
-
"""
|
298
|
-
Makes a POST call to a Pangea Service endpoint.
|
299
|
-
|
300
|
-
Args:
|
301
|
-
endpoint: The Pangea Service API endpoint.
|
302
|
-
data: The POST body payload object
|
303
|
-
pangea_response: Whether or not the response body follows Pangea's
|
304
|
-
standard response schema
|
305
|
-
"""
|
306
|
-
|
307
243
|
if isinstance(data, BaseModel):
|
308
244
|
data = data.model_dump(exclude_none=True)
|
309
245
|
|
@@ -341,13 +277,9 @@ class PangeaRequest(PangeaRequestBase):
|
|
341
277
|
|
342
278
|
self._check_http_errors(requests_response)
|
343
279
|
|
344
|
-
if not pangea_response:
|
345
|
-
type_adapter = TypeAdapter(result_class)
|
346
|
-
return type_adapter.validate_python(requests_response.json())
|
347
|
-
|
348
280
|
if "multipart/form-data" in requests_response.headers.get("content-type", ""):
|
349
281
|
multipart_response = self._process_multipart_response(requests_response)
|
350
|
-
|
282
|
+
pangea_response: PangeaResponse = PangeaResponse(
|
351
283
|
requests_response,
|
352
284
|
result_class=result_class,
|
353
285
|
json=multipart_response.pangea_json,
|
@@ -360,14 +292,14 @@ class PangeaRequest(PangeaRequestBase):
|
|
360
292
|
json.dumps({"service": self.service, "action": "post", "url": url, "response": json_resp})
|
361
293
|
)
|
362
294
|
|
363
|
-
|
295
|
+
pangea_response = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
|
364
296
|
except requests.exceptions.JSONDecodeError as e:
|
365
297
|
raise pe.PangeaException(f"Failed to decode json response. {e}. Body: {requests_response.text}") from e
|
366
298
|
|
367
299
|
if poll_result:
|
368
|
-
|
300
|
+
pangea_response = self._handle_queued_result(pangea_response)
|
369
301
|
|
370
|
-
return self._check_response(
|
302
|
+
return self._check_response(pangea_response)
|
371
303
|
|
372
304
|
def _get_pangea_json(self, decoder: MultipartDecoder) -> Optional[Dict]:
|
373
305
|
# Iterate through parts
|
@@ -410,18 +342,10 @@ class PangeaRequest(PangeaRequestBase):
|
|
410
342
|
if resp.status_code == 503:
|
411
343
|
raise pe.ServiceTemporarilyUnavailable(resp.json())
|
412
344
|
|
413
|
-
def _http_delete(
|
414
|
-
self,
|
415
|
-
url: str,
|
416
|
-
*,
|
417
|
-
headers: Mapping[str, str | bytes | None] = {},
|
418
|
-
) -> requests.Response:
|
419
|
-
return self.session.delete(url, headers=headers)
|
420
|
-
|
421
345
|
def _http_post(
|
422
346
|
self,
|
423
347
|
url: str,
|
424
|
-
headers:
|
348
|
+
headers: _HeadersUpdateMapping = {}, # noqa: B006
|
425
349
|
data: str | dict[Any, Any] = {}, # noqa: B006
|
426
350
|
files: _Files | None = None,
|
427
351
|
multipart_post: bool = True,
|
@@ -462,98 +386,37 @@ class PangeaRequest(PangeaRequestBase):
|
|
462
386
|
|
463
387
|
return response
|
464
388
|
|
465
|
-
|
466
|
-
|
467
|
-
self,
|
468
|
-
path: str,
|
469
|
-
result_class: Type[TResult],
|
470
|
-
check_response: bool = True,
|
471
|
-
*,
|
472
|
-
params: (
|
473
|
-
Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
|
474
|
-
| None
|
475
|
-
) = None,
|
476
|
-
pangea_response: Literal[True] = True,
|
477
|
-
) -> PangeaResponse[TResult]:
|
478
|
-
"""
|
479
|
-
Makes the GET call to a Pangea Service endpoint.
|
389
|
+
def get(self, path: str, result_class: Type[TResult], check_response: bool = True) -> PangeaResponse[TResult]:
|
390
|
+
"""Makes the GET call to a Pangea Service endpoint.
|
480
391
|
|
481
392
|
Args:
|
482
|
-
|
483
|
-
|
393
|
+
endpoint(str): The Pangea Service API endpoint.
|
394
|
+
path(str): Additional URL path
|
484
395
|
|
485
396
|
Returns:
|
486
397
|
PangeaResponse which contains the response in its entirety and
|
487
398
|
various properties to retrieve individual fields
|
488
399
|
"""
|
489
400
|
|
490
|
-
@overload
|
491
|
-
def get(
|
492
|
-
self,
|
493
|
-
path: str,
|
494
|
-
result_class: Type[TResult],
|
495
|
-
check_response: bool = True,
|
496
|
-
*,
|
497
|
-
params: (
|
498
|
-
Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
|
499
|
-
| None
|
500
|
-
) = None,
|
501
|
-
pangea_response: Literal[False] = False,
|
502
|
-
) -> TResult:
|
503
|
-
"""
|
504
|
-
Makes the GET call to a Pangea Service endpoint.
|
505
|
-
|
506
|
-
Args:
|
507
|
-
path: Additional URL path
|
508
|
-
params: Dictionary of querystring data to attach to the request
|
509
|
-
"""
|
510
|
-
|
511
|
-
def get(
|
512
|
-
self,
|
513
|
-
path: str,
|
514
|
-
result_class: Type[TResult],
|
515
|
-
check_response: bool = True,
|
516
|
-
*,
|
517
|
-
params: (
|
518
|
-
Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
|
519
|
-
| None
|
520
|
-
) = None,
|
521
|
-
pangea_response: bool = True,
|
522
|
-
) -> PangeaResponse[TResult] | TResult:
|
523
|
-
"""
|
524
|
-
Makes the GET call to a Pangea Service endpoint.
|
525
|
-
|
526
|
-
Args:
|
527
|
-
path: Additional URL path
|
528
|
-
params: Dictionary of querystring data to attach to the request
|
529
|
-
pangea_response: Whether or not the response body follows Pangea's
|
530
|
-
standard response schema
|
531
|
-
"""
|
532
|
-
|
533
401
|
url = self._url(path)
|
534
402
|
self.logger.debug(json.dumps({"service": self.service, "action": "get", "url": url}))
|
535
|
-
requests_response = self.session.get(url,
|
403
|
+
requests_response = self.session.get(url, headers=self._headers())
|
536
404
|
self._check_http_errors(requests_response)
|
537
|
-
|
538
|
-
if not pangea_response:
|
539
|
-
type_adapter = TypeAdapter(result_class)
|
540
|
-
return type_adapter.validate_python(requests_response.json())
|
541
|
-
|
542
|
-
pangea_response_obj: PangeaResponse = PangeaResponse(
|
405
|
+
pangea_response: PangeaResponse = PangeaResponse(
|
543
406
|
requests_response, result_class=result_class, json=requests_response.json()
|
544
407
|
)
|
545
408
|
|
546
409
|
self.logger.debug(
|
547
410
|
json.dumps(
|
548
|
-
{"service": self.service, "action": "get", "url": url, "response":
|
411
|
+
{"service": self.service, "action": "get", "url": url, "response": pangea_response.json},
|
549
412
|
default=default_encoder,
|
550
413
|
)
|
551
414
|
)
|
552
415
|
|
553
416
|
if check_response is False:
|
554
|
-
return
|
417
|
+
return pangea_response
|
555
418
|
|
556
|
-
return self._check_response(
|
419
|
+
return self._check_response(pangea_response)
|
557
420
|
|
558
421
|
def download_file(self, url: str, filename: str | None = None) -> AttachedFile:
|
559
422
|
"""
|
pangea/response.py
CHANGED
@@ -82,14 +82,12 @@ class TransferMethod(str, enum.Enum):
|
|
82
82
|
PangeaDateTime = Annotated[datetime.datetime, PlainSerializer(format_datetime)]
|
83
83
|
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
85
|
+
class APIRequestModel(BaseModel):
|
86
|
+
model_config = ConfigDict(extra="forbid")
|
88
87
|
|
89
88
|
|
90
|
-
|
91
|
-
|
92
|
-
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
89
|
+
class APIResponseModel(BaseModel):
|
90
|
+
model_config = ConfigDict(extra="allow")
|
93
91
|
|
94
92
|
|
95
93
|
class PangeaResponseResult(APIResponseModel):
|
@@ -195,6 +193,8 @@ T = TypeVar("T", bound=PangeaResponseResult)
|
|
195
193
|
|
196
194
|
|
197
195
|
class PangeaResponse(ResponseHeader, Generic[T]):
|
196
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
|
197
|
+
|
198
198
|
raw_result: Optional[Dict[str, Any]] = None
|
199
199
|
raw_response: Optional[Union[requests.Response, aiohttp.ClientResponse]] = None
|
200
200
|
result: Optional[T] = None
|
pangea/services/__init__.py
CHANGED
@@ -7,7 +7,6 @@ from .authz import AuthZ
|
|
7
7
|
from .embargo import Embargo
|
8
8
|
from .file_scan import FileScan
|
9
9
|
from .intel import DomainIntel, FileIntel, IpIntel, UrlIntel, UserIntel
|
10
|
-
from .management import Management
|
11
10
|
from .prompt_guard import PromptGuard
|
12
11
|
from .redact import Redact
|
13
12
|
from .sanitize import Sanitize
|