pangea-sdk 3.8.0b1__py3-none-any.whl → 5.4.0b1__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/file_uploader.py +1 -1
- pangea/asyncio/request.py +56 -34
- pangea/asyncio/services/__init__.py +4 -0
- pangea/asyncio/services/ai_guard.py +75 -0
- pangea/asyncio/services/audit.py +192 -31
- pangea/asyncio/services/authn.py +187 -109
- pangea/asyncio/services/authz.py +285 -0
- pangea/asyncio/services/base.py +21 -2
- pangea/asyncio/services/embargo.py +2 -2
- pangea/asyncio/services/file_scan.py +24 -9
- pangea/asyncio/services/intel.py +108 -34
- pangea/asyncio/services/prompt_guard.py +73 -0
- pangea/asyncio/services/redact.py +72 -4
- pangea/asyncio/services/sanitize.py +217 -0
- pangea/asyncio/services/share.py +246 -73
- pangea/asyncio/services/vault.py +1710 -750
- pangea/crypto/rsa.py +135 -0
- pangea/deep_verify.py +7 -1
- pangea/dump_audit.py +9 -8
- pangea/request.py +87 -59
- pangea/response.py +49 -31
- pangea/services/__init__.py +4 -0
- pangea/services/ai_guard.py +128 -0
- pangea/services/audit/audit.py +205 -42
- pangea/services/audit/models.py +56 -8
- pangea/services/audit/signing.py +6 -5
- pangea/services/audit/util.py +3 -3
- pangea/services/authn/authn.py +140 -70
- pangea/services/authn/models.py +167 -11
- pangea/services/authz.py +400 -0
- pangea/services/base.py +39 -8
- pangea/services/embargo.py +2 -2
- pangea/services/file_scan.py +32 -15
- pangea/services/intel.py +157 -32
- pangea/services/prompt_guard.py +83 -0
- pangea/services/redact.py +152 -4
- pangea/services/sanitize.py +371 -0
- pangea/services/share/share.py +683 -107
- pangea/services/vault/models/asymmetric.py +120 -18
- pangea/services/vault/models/common.py +439 -141
- pangea/services/vault/models/keys.py +94 -0
- pangea/services/vault/models/secret.py +27 -3
- pangea/services/vault/models/symmetric.py +68 -22
- pangea/services/vault/vault.py +1690 -749
- pangea/tools.py +6 -7
- pangea/utils.py +16 -27
- pangea/verify_audit.py +270 -83
- {pangea_sdk-3.8.0b1.dist-info → pangea_sdk-5.4.0b1.dist-info}/METADATA +43 -35
- pangea_sdk-5.4.0b1.dist-info/RECORD +60 -0
- {pangea_sdk-3.8.0b1.dist-info → pangea_sdk-5.4.0b1.dist-info}/WHEEL +1 -1
- pangea_sdk-3.8.0b1.dist-info/RECORD +0 -50
pangea/services/base.py
CHANGED
@@ -1,23 +1,40 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
3
4
|
|
4
5
|
import copy
|
5
6
|
import logging
|
6
7
|
from typing import Dict, Optional, Type, Union
|
7
8
|
|
9
|
+
from typing_extensions import TypeVar
|
10
|
+
|
8
11
|
from pangea.asyncio.request import PangeaRequestAsync
|
9
12
|
from pangea.config import PangeaConfig
|
10
13
|
from pangea.exceptions import AcceptedRequestException
|
11
14
|
from pangea.request import PangeaRequest
|
12
15
|
from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
|
13
16
|
|
17
|
+
TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
|
18
|
+
|
14
19
|
|
15
20
|
class ServiceBase(object):
|
16
21
|
service_name: str = "base"
|
17
22
|
|
18
23
|
def __init__(
|
19
|
-
self,
|
20
|
-
|
24
|
+
self,
|
25
|
+
token: str,
|
26
|
+
config: PangeaConfig | None = None,
|
27
|
+
logger_name: str = "pangea",
|
28
|
+
config_id: str | None = None,
|
29
|
+
) -> None:
|
30
|
+
"""
|
31
|
+
Initializes a new Pangea service client.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
token: Pangea API token.
|
35
|
+
config: Configuration.
|
36
|
+
logger_name: Logger name.
|
37
|
+
"""
|
21
38
|
if not token:
|
22
39
|
raise Exception("No token provided")
|
23
40
|
|
@@ -30,11 +47,11 @@ class ServiceBase(object):
|
|
30
47
|
self.request.set_extra_headers(extra_headers)
|
31
48
|
|
32
49
|
@property
|
33
|
-
def token(self):
|
50
|
+
def token(self) -> str:
|
34
51
|
return self._token
|
35
52
|
|
36
53
|
@token.setter
|
37
|
-
def token(self, value):
|
54
|
+
def token(self, value: str) -> None:
|
38
55
|
self._token = value
|
39
56
|
|
40
57
|
@property
|
@@ -55,15 +72,16 @@ class ServiceBase(object):
|
|
55
72
|
exception: Optional[AcceptedRequestException] = None,
|
56
73
|
response: Optional[PangeaResponse] = None,
|
57
74
|
request_id: Optional[str] = None,
|
58
|
-
result_class:
|
59
|
-
) -> PangeaResponse:
|
75
|
+
result_class: Type[TResult] = PangeaResponseResult, # type: ignore[assignment]
|
76
|
+
) -> PangeaResponse[TResult]:
|
60
77
|
"""
|
61
78
|
Poll result
|
62
79
|
|
63
80
|
Returns request's result that has been accepted by the server
|
64
81
|
|
65
82
|
Args:
|
66
|
-
exception
|
83
|
+
exception: Exception that was previously raised by the SDK on a call
|
84
|
+
that is being processed.
|
67
85
|
|
68
86
|
Returns:
|
69
87
|
PangeaResponse
|
@@ -83,5 +101,18 @@ class ServiceBase(object):
|
|
83
101
|
else:
|
84
102
|
raise AttributeError("Need to set exception, response or request_id")
|
85
103
|
|
86
|
-
def download_file(self, url: str, filename:
|
104
|
+
def download_file(self, url: str, filename: str | None = None) -> AttachedFile:
|
105
|
+
"""
|
106
|
+
Download file
|
107
|
+
|
108
|
+
Download a file from the specified URL and save it with the given
|
109
|
+
filename.
|
110
|
+
|
111
|
+
Args:
|
112
|
+
url: URL of the file to download
|
113
|
+
filename: Name to save the downloaded file as. If not provided, the
|
114
|
+
filename will be determined from the Content-Disposition header or
|
115
|
+
the URL.
|
116
|
+
"""
|
117
|
+
|
87
118
|
return self.request.download_file(url=url, filename=filename)
|
pangea/services/embargo.py
CHANGED
@@ -103,7 +103,7 @@ class Embargo(ServiceBase):
|
|
103
103
|
response = embargo.ip_check("190.6.64.94")
|
104
104
|
"""
|
105
105
|
input = IPCheckRequest(ip=ip)
|
106
|
-
return self.request.post("v1/ip/check", EmbargoResult, data=input.
|
106
|
+
return self.request.post("v1/ip/check", EmbargoResult, data=input.model_dump())
|
107
107
|
|
108
108
|
def iso_check(self, iso_code: str) -> PangeaResponse[EmbargoResult]:
|
109
109
|
"""
|
@@ -130,4 +130,4 @@ class Embargo(ServiceBase):
|
|
130
130
|
response = embargo.iso_check("CU")
|
131
131
|
"""
|
132
132
|
input = ISOCheckRequest(iso_code=iso_code)
|
133
|
-
return self.request.post("v1/iso/check", result_class=EmbargoResult, data=input.
|
133
|
+
return self.request.post("v1/iso/check", result_class=EmbargoResult, data=input.model_dump())
|
pangea/services/file_scan.py
CHANGED
@@ -11,22 +11,25 @@ from pangea.utils import FileUploadParams, get_file_upload_params
|
|
11
11
|
|
12
12
|
|
13
13
|
class FileScanRequest(APIRequestModel):
|
14
|
-
"""
|
15
|
-
File Scan request data
|
16
|
-
|
17
|
-
provider (str, optional): Provider of the information. Default provider defined by the configuration.
|
18
|
-
verbose (bool, optional): Echo back the parameters of the API in the response
|
19
|
-
raw (bool, optional): Return additional details from the provider.
|
20
|
-
"""
|
14
|
+
"""File Scan request data."""
|
21
15
|
|
22
16
|
verbose: Optional[bool] = None
|
17
|
+
"""Echo back the parameters of the API in the response."""
|
18
|
+
|
23
19
|
raw: Optional[bool] = None
|
20
|
+
"""Return additional details from the provider."""
|
21
|
+
|
24
22
|
provider: Optional[str] = None
|
23
|
+
"""Provider of the information. Default provider defined by the configuration."""
|
24
|
+
|
25
25
|
size: Optional[int] = None
|
26
26
|
crc32c: Optional[str] = None
|
27
27
|
sha256: Optional[str] = None
|
28
28
|
source_url: Optional[str] = None
|
29
|
+
"""A URL where the file to be scanned can be downloaded."""
|
30
|
+
|
29
31
|
transfer_method: TransferMethod = TransferMethod.POST_URL
|
32
|
+
"""The transfer method used to upload the file data."""
|
30
33
|
|
31
34
|
|
32
35
|
class FileScanData(PangeaResponseResult):
|
@@ -71,7 +74,6 @@ class FileScan(ServiceBase):
|
|
71
74
|
"""
|
72
75
|
|
73
76
|
service_name = "file-scan"
|
74
|
-
version = "v1"
|
75
77
|
|
76
78
|
def file_scan(
|
77
79
|
self,
|
@@ -92,12 +94,14 @@ class FileScan(ServiceBase):
|
|
92
94
|
OperationId: file_scan_post_v1_scan
|
93
95
|
|
94
96
|
Args:
|
95
|
-
file (io.BufferedReader, optional): file to be scanned (should be opened with read permissions and in binary format)
|
96
97
|
file_path (str, optional): filepath to be opened and scanned
|
98
|
+
file (io.BufferedReader, optional): file to be scanned (should be opened with read permissions and in binary format)
|
97
99
|
verbose (bool, optional): Echo the API parameters in the response
|
98
100
|
raw (bool, optional): Include raw data from this provider
|
99
101
|
provider (str, optional): Scan file using this provider
|
100
102
|
sync_call (bool, optional): True to wait until server returns a result, False to return immediately and retrieve result asynchronously
|
103
|
+
transfer_method (TransferMethod, optional): Transfer method used to upload the file data.
|
104
|
+
source_url (str, optional): A URL where the Pangea APIs can fetch the contents of the input file.
|
101
105
|
|
102
106
|
Raises:
|
103
107
|
PangeaAPIException: If an API Error happens
|
@@ -118,6 +122,15 @@ class FileScan(ServiceBase):
|
|
118
122
|
print(f"\\t{err.detail} \\n")
|
119
123
|
"""
|
120
124
|
|
125
|
+
if transfer_method == TransferMethod.SOURCE_URL and source_url is None:
|
126
|
+
raise ValueError("`source_url` argument is required when using `TransferMethod.SOURCE_URL`.")
|
127
|
+
|
128
|
+
if source_url is not None and transfer_method != TransferMethod.SOURCE_URL:
|
129
|
+
raise ValueError(
|
130
|
+
"`transfer_method` should be `TransferMethod.SOURCE_URL` when using the `source_url` argument."
|
131
|
+
)
|
132
|
+
|
133
|
+
files: Optional[List[Tuple]] = None
|
121
134
|
if file or file_path:
|
122
135
|
if file_path:
|
123
136
|
file = open(file_path, "rb")
|
@@ -128,9 +141,9 @@ class FileScan(ServiceBase):
|
|
128
141
|
size = params.size
|
129
142
|
else:
|
130
143
|
crc, sha, size = None, None, None
|
131
|
-
files
|
132
|
-
|
133
|
-
raise ValueError("Need to set file_path or
|
144
|
+
files = [("upload", ("filename", file, "application/octet-stream"))]
|
145
|
+
elif source_url is None:
|
146
|
+
raise ValueError("Need to set one of `file_path`, `file`, or `source_url` arguments.")
|
134
147
|
|
135
148
|
input = FileScanRequest(
|
136
149
|
verbose=verbose,
|
@@ -142,8 +155,12 @@ class FileScan(ServiceBase):
|
|
142
155
|
transfer_method=transfer_method,
|
143
156
|
source_url=source_url,
|
144
157
|
)
|
145
|
-
data = input.
|
146
|
-
|
158
|
+
data = input.model_dump(exclude_none=True)
|
159
|
+
try:
|
160
|
+
return self.request.post("v1/scan", FileScanResult, data=data, files=files, poll_result=sync_call)
|
161
|
+
finally:
|
162
|
+
if file_path and file:
|
163
|
+
file.close()
|
147
164
|
|
148
165
|
def request_upload_url(
|
149
166
|
self,
|
@@ -164,7 +181,7 @@ class FileScan(ServiceBase):
|
|
164
181
|
input.sha256 = params.sha256_hex
|
165
182
|
input.size = params.size
|
166
183
|
|
167
|
-
data = input.
|
184
|
+
data = input.model_dump(exclude_none=True)
|
168
185
|
return self.request.request_presigned_url("v1/scan", FileScanResult, data=data)
|
169
186
|
|
170
187
|
|