pangea-sdk 3.8.0__py3-none-any.whl → 5.3.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. pangea/__init__.py +2 -1
  2. pangea/asyncio/__init__.py +1 -0
  3. pangea/asyncio/file_uploader.py +39 -0
  4. pangea/asyncio/request.py +46 -23
  5. pangea/asyncio/services/__init__.py +2 -0
  6. pangea/asyncio/services/audit.py +46 -20
  7. pangea/asyncio/services/authn.py +123 -61
  8. pangea/asyncio/services/authz.py +57 -31
  9. pangea/asyncio/services/base.py +21 -2
  10. pangea/asyncio/services/embargo.py +2 -2
  11. pangea/asyncio/services/file_scan.py +24 -9
  12. pangea/asyncio/services/intel.py +104 -30
  13. pangea/asyncio/services/redact.py +52 -3
  14. pangea/asyncio/services/sanitize.py +217 -0
  15. pangea/asyncio/services/share.py +733 -0
  16. pangea/asyncio/services/vault.py +1709 -766
  17. pangea/crypto/rsa.py +135 -0
  18. pangea/deep_verify.py +7 -1
  19. pangea/dump_audit.py +9 -8
  20. pangea/file_uploader.py +35 -0
  21. pangea/request.py +70 -49
  22. pangea/response.py +36 -17
  23. pangea/services/__init__.py +2 -0
  24. pangea/services/audit/audit.py +57 -29
  25. pangea/services/audit/models.py +12 -3
  26. pangea/services/audit/signing.py +6 -5
  27. pangea/services/audit/util.py +3 -3
  28. pangea/services/authn/authn.py +120 -66
  29. pangea/services/authn/models.py +167 -11
  30. pangea/services/authz.py +53 -30
  31. pangea/services/base.py +16 -2
  32. pangea/services/embargo.py +2 -2
  33. pangea/services/file_scan.py +32 -15
  34. pangea/services/intel.py +155 -30
  35. pangea/services/redact.py +132 -3
  36. pangea/services/sanitize.py +388 -0
  37. pangea/services/share/file_format.py +170 -0
  38. pangea/services/share/share.py +1440 -0
  39. pangea/services/vault/models/asymmetric.py +120 -18
  40. pangea/services/vault/models/common.py +439 -141
  41. pangea/services/vault/models/keys.py +94 -0
  42. pangea/services/vault/models/secret.py +27 -3
  43. pangea/services/vault/models/symmetric.py +68 -22
  44. pangea/services/vault/vault.py +1690 -766
  45. pangea/tools.py +6 -7
  46. pangea/utils.py +94 -33
  47. pangea/verify_audit.py +270 -83
  48. {pangea_sdk-3.8.0.dist-info → pangea_sdk-5.3.0.dist-info}/METADATA +21 -29
  49. pangea_sdk-5.3.0.dist-info/RECORD +56 -0
  50. {pangea_sdk-3.8.0.dist-info → pangea_sdk-5.3.0.dist-info}/WHEEL +1 -1
  51. pangea_sdk-3.8.0.dist-info/RECORD +0 -46
@@ -0,0 +1,388 @@
1
+ # Copyright 2022 Pangea Cyber Corporation
2
+ # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
4
+
5
+ import io
6
+ from typing import Dict, List, Optional, Tuple
7
+
8
+ from pydantic import Field
9
+
10
+ from pangea.config import PangeaConfig
11
+ from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult, TransferMethod
12
+ from pangea.services.base import ServiceBase
13
+ from pangea.utils import FileUploadParams, get_file_upload_params
14
+
15
+
16
+ class SanitizeFile(APIRequestModel):
17
+ scan_provider: Optional[str] = None
18
+ """Provider to use for File Scan."""
19
+
20
+
21
+ class SanitizeContent(APIRequestModel):
22
+ url_intel: Optional[bool] = None
23
+ """Perform URL Intel lookup."""
24
+
25
+ url_intel_provider: Optional[str] = None
26
+ """Provider to use for URL Intel."""
27
+
28
+ domain_intel: Optional[bool] = None
29
+ """Perform Domain Intel lookup."""
30
+
31
+ domain_intel_provider: Optional[str] = None
32
+ """Provider to use for Domain Intel lookup."""
33
+
34
+ defang: Optional[bool] = None
35
+ """Defang external links."""
36
+
37
+ defang_threshold: Optional[int] = None
38
+ """Defang risk threshold."""
39
+
40
+ redact: Optional[bool] = None
41
+ """Redact sensitive content."""
42
+
43
+ redact_detect_only: Optional[bool] = None
44
+ """
45
+ If redact is enabled, avoids redacting the file and instead returns the PII
46
+ analysis engine results. Only works if redact is enabled.
47
+ """
48
+
49
+ remove_attachments: Optional[bool] = None
50
+ """Remove file attachments (PDF only)."""
51
+
52
+ remove_interactive: Optional[bool] = None
53
+ """Remove interactive content (PDF only)."""
54
+
55
+
56
+ class SanitizeShareOutput(APIRequestModel):
57
+ enabled: Optional[bool] = None
58
+ """Store Sanitized files to Pangea Secure Share."""
59
+
60
+ output_folder: Optional[str] = None
61
+ """
62
+ Store Sanitized files to this Secure Share folder (will be auto-created if
63
+ it does not exist)
64
+ """
65
+
66
+
67
+ class SanitizeRequest(APIRequestModel):
68
+ transfer_method: TransferMethod = TransferMethod.POST_URL
69
+ """The transfer method used to upload the file data."""
70
+
71
+ source_url: Optional[str] = None
72
+ """A URL where the file to be sanitized can be downloaded."""
73
+
74
+ share_id: Optional[str] = None
75
+ """A Pangea Secure Share ID where the file to be Sanitized is stored."""
76
+
77
+ file: Optional[SanitizeFile] = None
78
+ """File."""
79
+
80
+ content: Optional[SanitizeContent] = None
81
+ """Content."""
82
+
83
+ share_output: Optional[SanitizeShareOutput] = None
84
+ """Share output."""
85
+
86
+ size: Optional[int] = None
87
+ """The size (in bytes) of the file. If the upload doesn't match, the call will fail."""
88
+
89
+ crc32c: Optional[str] = None
90
+ """The CRC32C hash of the file data, which will be verified by the server if provided."""
91
+
92
+ sha256: Optional[str] = None
93
+ """The hexadecimal-encoded SHA256 hash of the file data, which will be verified by the server if provided."""
94
+
95
+ uploaded_file_name: Optional[str] = None
96
+ """Name of the user-uploaded file, required for transfer-method 'put-url' and 'post-url'."""
97
+
98
+
99
+ class DefangData(PangeaResponseResult):
100
+ external_urls_count: Optional[int] = None
101
+ """Number of external links found."""
102
+
103
+ external_domains_count: Optional[int] = None
104
+ """Number of external domains found."""
105
+
106
+ defanged_count: Optional[int] = None
107
+ """Number of items defanged per provided rules and detections."""
108
+
109
+ url_intel_summary: Optional[str] = None
110
+ """Processed N URLs: X are malicious, Y are suspicious, Z are unknown."""
111
+
112
+ domain_intel_summary: Optional[str] = None
113
+ """Processed N Domains: X are malicious, Y are suspicious, Z are unknown."""
114
+
115
+
116
+ class RedactRecognizerResult(PangeaResponseResult):
117
+ field_type: str
118
+ """The entity name."""
119
+
120
+ score: float
121
+ """The certainty score that the entity matches this specific snippet."""
122
+
123
+ text: str
124
+ """The text snippet that matched."""
125
+
126
+ start: int
127
+ """The starting index of a snippet."""
128
+
129
+ end: int
130
+ """The ending index of a snippet."""
131
+
132
+ redacted: bool
133
+ """Indicates if this rule was used to anonymize a text snippet."""
134
+
135
+
136
+ class RedactData(PangeaResponseResult):
137
+ redaction_count: int
138
+ """Number of items redacted"""
139
+
140
+ summary_counts: Dict[str, int] = Field(default_factory=dict)
141
+ """Summary counts."""
142
+
143
+ recognizer_results: Optional[List[RedactRecognizerResult]] = None
144
+ """The scoring result of a set of rules."""
145
+
146
+
147
+ class CDR(PangeaResponseResult):
148
+ file_attachments_removed: Optional[int] = None
149
+ """Number of file attachments removed."""
150
+
151
+ interactive_contents_removed: Optional[int] = None
152
+ """Number of interactive content items removed."""
153
+
154
+
155
+ class SanitizeData(PangeaResponseResult):
156
+ defang: Optional[DefangData] = None
157
+ """Defang."""
158
+
159
+ redact: Optional[RedactData] = None
160
+ """Redact."""
161
+
162
+ malicious_file: Optional[bool] = None
163
+ """If the file scanned was malicious."""
164
+
165
+ cdr: Optional[CDR] = None
166
+ """Content Disarm and Reconstruction."""
167
+
168
+
169
+ class SanitizeResult(PangeaResponseResult):
170
+ dest_url: Optional[str] = None
171
+ """A URL where the Sanitized file can be downloaded."""
172
+
173
+ dest_share_id: Optional[str] = None
174
+ """Pangea Secure Share ID of the Sanitized file."""
175
+
176
+ data: SanitizeData
177
+ """Sanitize data."""
178
+
179
+ parameters: Dict = {}
180
+ """The parameters, which were passed in the request, echoed back."""
181
+
182
+
183
+ class Sanitize(ServiceBase):
184
+ """Sanitize service client.
185
+
186
+ Examples:
187
+ import os
188
+
189
+ # Pangea SDK
190
+ from pangea.config import PangeaConfig
191
+ from pangea.services import Sanitize
192
+
193
+ PANGEA_SANITIZE_TOKEN = os.getenv("PANGEA_SANITIZE_TOKEN")
194
+ config = PangeaConfig(domain="pangea.cloud")
195
+
196
+ sanitize = Sanitize(token=PANGEA_SANITIZE_TOKEN, config=config)
197
+ """
198
+
199
+ service_name = "sanitize"
200
+
201
+ def __init__(
202
+ self, token: str, config: PangeaConfig | None = None, logger_name: str = "pangea", config_id: str | None = None
203
+ ) -> None:
204
+ """
205
+ Sanitize client
206
+
207
+ Initializes a new Sanitize client.
208
+
209
+ Args:
210
+ token: Pangea API token.
211
+ config: Configuration.
212
+ logger_name: Logger name.
213
+ config_id: Configuration ID.
214
+
215
+ Examples:
216
+ config = PangeaConfig(domain="aws.us.pangea.cloud")
217
+ authz = Sanitize(token="pangea_token", config=config)
218
+ """
219
+
220
+ super().__init__(token, config, logger_name, config_id=config_id)
221
+
222
+ def sanitize(
223
+ self,
224
+ transfer_method: TransferMethod = TransferMethod.POST_URL,
225
+ file_path: Optional[str] = None,
226
+ file: Optional[io.BufferedReader] = None,
227
+ source_url: Optional[str] = None,
228
+ share_id: Optional[str] = None,
229
+ file_scan: Optional[SanitizeFile] = None,
230
+ content: Optional[SanitizeContent] = None,
231
+ share_output: Optional[SanitizeShareOutput] = None,
232
+ size: Optional[int] = None,
233
+ crc32c: Optional[str] = None,
234
+ sha256: Optional[str] = None,
235
+ uploaded_file_name: Optional[str] = None,
236
+ sync_call: bool = True,
237
+ ) -> PangeaResponse[SanitizeResult]:
238
+ """
239
+ Sanitize
240
+
241
+ Apply file sanitization actions according to specified rules.
242
+
243
+ OperationId: sanitize_post_v1_sanitize
244
+
245
+ Args:
246
+ transfer_method: The transfer method used to upload the file data.
247
+ file_path: Path to file to sanitize.
248
+ file: File to sanitize.
249
+ source_url: A URL where the file to be sanitized can be downloaded.
250
+ share_id: A Pangea Secure Share ID where the file to be sanitized is stored.
251
+ file_scan: Options for File Scan.
252
+ content: Options for how the file should be sanitized.
253
+ share_output: Integration with Secure Share.
254
+ size: The size (in bytes) of the file. If the upload doesn't match, the call will fail.
255
+ crc32c: The CRC32C hash of the file data, which will be verified by the server if provided.
256
+ sha256: The hexadecimal-encoded SHA256 hash of the file data, which will be verified by the server if provided.
257
+ uploaded_file_name: Name of the user-uploaded file, required for `TransferMethod.PUT_URL` and `TransferMethod.POST_URL`.
258
+ sync_call: Whether or not to poll on HTTP/202.
259
+
260
+ Raises:
261
+ PangeaAPIException: If an API error happens.
262
+
263
+ Returns:
264
+ The sanitized file and information on the sanitization that was
265
+ performed.
266
+
267
+ Examples:
268
+ with open("/path/to/file.pdf", "rb") as f:
269
+ response = sanitize.sanitize(
270
+ file=f,
271
+ transfer_method=TransferMethod.POST_URL,
272
+ uploaded_file_name="uploaded_file",
273
+ )
274
+ """
275
+
276
+ if transfer_method == TransferMethod.SOURCE_URL and source_url is None:
277
+ raise ValueError("`source_url` argument is required when using `TransferMethod.SOURCE_URL`.")
278
+
279
+ if source_url is not None and transfer_method != TransferMethod.SOURCE_URL:
280
+ raise ValueError(
281
+ "`transfer_method` should be `TransferMethod.SOURCE_URL` when using the `source_url` argument."
282
+ )
283
+
284
+ files: Optional[List[Tuple]] = None
285
+ if file or file_path:
286
+ if file_path:
287
+ file = open(file_path, "rb")
288
+ if (
289
+ transfer_method == TransferMethod.POST_URL
290
+ and file
291
+ and (sha256 is None or crc32c is None or size is None)
292
+ ):
293
+ params = get_file_upload_params(file)
294
+ crc32c = params.crc_hex if crc32c is None else crc32c
295
+ sha256 = params.sha256_hex if sha256 is None else sha256
296
+ size = params.size if size is None else size
297
+ else:
298
+ crc32c, sha256, size = None, None, None
299
+ files = [("upload", ("filename", file, "application/octet-stream"))]
300
+ elif source_url is None:
301
+ raise ValueError("Need to set one of `file_path`, `file`, or `source_url` arguments.")
302
+
303
+ input = SanitizeRequest(
304
+ transfer_method=transfer_method,
305
+ source_url=source_url,
306
+ share_id=share_id,
307
+ file=file_scan,
308
+ content=content,
309
+ share_output=share_output,
310
+ crc32c=crc32c,
311
+ sha256=sha256,
312
+ size=size,
313
+ uploaded_file_name=uploaded_file_name,
314
+ )
315
+ data = input.model_dump(exclude_none=True)
316
+ try:
317
+ response = self.request.post("v1/sanitize", SanitizeResult, data=data, files=files, poll_result=sync_call)
318
+ finally:
319
+ if file_path and file is not None:
320
+ file.close()
321
+ return response
322
+
323
+ def request_upload_url(
324
+ self,
325
+ transfer_method: TransferMethod = TransferMethod.PUT_URL,
326
+ params: Optional[FileUploadParams] = None,
327
+ file_scan: Optional[SanitizeFile] = None,
328
+ content: Optional[SanitizeContent] = None,
329
+ share_output: Optional[SanitizeShareOutput] = None,
330
+ size: Optional[int] = None,
331
+ crc32c: Optional[str] = None,
332
+ sha256: Optional[str] = None,
333
+ uploaded_file_name: Optional[str] = None,
334
+ ) -> PangeaResponse[SanitizeResult]:
335
+ """
336
+ Sanitize via presigned URL
337
+
338
+ Apply file sanitization actions according to specified rules via a
339
+ [presigned URL](https://pangea.cloud/docs/api/transfer-methods).
340
+
341
+ OperationId: sanitize_post_v1_sanitize 2
342
+
343
+ Args:
344
+ transfer_method: The transfer method used to upload the file data.
345
+ params: File upload parameters.
346
+ file_scan: Options for File Scan.
347
+ content: Options for how the file should be sanitized.
348
+ share_output: Integration with Secure Share.
349
+ size: The size (in bytes) of the file. If the upload doesn't match, the call will fail.
350
+ crc32c: The CRC32C hash of the file data, which will be verified by the server if provided.
351
+ sha256: The hexadecimal-encoded SHA256 hash of the file data, which will be verified by the server if provided.
352
+ uploaded_file_name: Name of the user-uploaded file, required for `TransferMethod.PUT_URL` and `TransferMethod.POST_URL`.
353
+
354
+ Raises:
355
+ PangeaAPIException: If an API error happens.
356
+
357
+ Returns:
358
+ A presigned URL.
359
+
360
+ Examples:
361
+ presignedUrl = sanitize.request_upload_url(
362
+ transfer_method=TransferMethod.PUT_URL,
363
+ uploaded_file_name="uploaded_file",
364
+ )
365
+
366
+ # Upload file to `presignedUrl.accepted_result.put_url`.
367
+
368
+ # Poll for Sanitize's result.
369
+ response: PangeaResponse[SanitizeResult] = sanitize.poll_result(response=presignedUrl)
370
+ """
371
+
372
+ input = SanitizeRequest(
373
+ transfer_method=transfer_method,
374
+ file=file_scan,
375
+ content=content,
376
+ share_output=share_output,
377
+ crc32c=crc32c,
378
+ sha256=sha256,
379
+ size=size,
380
+ uploaded_file_name=uploaded_file_name,
381
+ )
382
+ if params is not None and (transfer_method == TransferMethod.POST_URL):
383
+ input.crc32c = params.crc_hex
384
+ input.sha256 = params.sha256_hex
385
+ input.size = params.size
386
+
387
+ data = input.model_dump(exclude_none=True)
388
+ return self.request.request_presigned_url("v1/sanitize", SanitizeResult, data=data)
@@ -0,0 +1,170 @@
1
+ import enum
2
+
3
+
4
+ class FileFormat(str, enum.Enum):
5
+ F3G2 = "3G2"
6
+ F3GP = "3GP"
7
+ F3MF = "3MF"
8
+ F7Z = "7Z"
9
+ A = "A"
10
+ AAC = "AAC"
11
+ ACCDB = "ACCDB"
12
+ AIFF = "AIFF"
13
+ AMF = "AMF"
14
+ AMR = "AMR"
15
+ APE = "APE"
16
+ ASF = "ASF"
17
+ ATOM = "ATOM"
18
+ AU = "AU"
19
+ AVI = "AVI"
20
+ AVIF = "AVIF"
21
+ BIN = "BIN"
22
+ BMP = "BMP"
23
+ BPG = "BPG"
24
+ BZ2 = "BZ2"
25
+ CAB = "CAB"
26
+ CLASS = "CLASS"
27
+ CPIO = "CPIO"
28
+ CRX = "CRX"
29
+ CSV = "CSV"
30
+ DAE = "DAE"
31
+ DBF = "DBF"
32
+ DCM = "DCM"
33
+ DEB = "DEB"
34
+ DJVU = "DJVU"
35
+ DLL = "DLL"
36
+ DOC = "DOC"
37
+ DOCX = "DOCX"
38
+ DWG = "DWG"
39
+ EOT = "EOT"
40
+ EPUB = "EPUB"
41
+ EXE = "EXE"
42
+ FDF = "FDF"
43
+ FITS = "FITS"
44
+ FLAC = "FLAC"
45
+ FLV = "FLV"
46
+ GBR = "GBR"
47
+ GEOJSON = "GEOJSON"
48
+ GIF = "GIF"
49
+ GLB = "GLB"
50
+ GML = "GML"
51
+ GPX = "GPX"
52
+ GZ = "GZ"
53
+ HAR = "HAR"
54
+ HDR = "HDR"
55
+ HEIC = "HEIC"
56
+ HEIF = "HEIF"
57
+ HTML = "HTML"
58
+ ICNS = "ICNS"
59
+ ICO = "ICO"
60
+ ICS = "ICS"
61
+ ISO = "ISO"
62
+ JAR = "JAR"
63
+ JP2 = "JP2"
64
+ JPF = "JPF"
65
+ JPG = "JPG"
66
+ JPM = "JPM"
67
+ JS = "JS"
68
+ JSON = "JSON"
69
+ JXL = "JXL"
70
+ JXR = "JXR"
71
+ KML = "KML"
72
+ LIT = "LIT"
73
+ LNK = "LNK"
74
+ LUA = "LUA"
75
+ LZ = "LZ"
76
+ M3U = "M3U"
77
+ M4A = "M4A"
78
+ MACHO = "MACHO"
79
+ MDB = "MDB"
80
+ MIDI = "MIDI"
81
+ MKV = "MKV"
82
+ MOBI = "MOBI"
83
+ MOV = "MOV"
84
+ MP3 = "MP3"
85
+ MP4 = "MP4"
86
+ MPC = "MPC"
87
+ MPEG = "MPEG"
88
+ MQV = "MQV"
89
+ MRC = "MRC"
90
+ MSG = "MSG"
91
+ MSI = "MSI"
92
+ NDJSON = "NDJSON"
93
+ NES = "NES"
94
+ ODC = "ODC"
95
+ ODF = "ODF"
96
+ ODG = "ODG"
97
+ ODP = "ODP"
98
+ ODS = "ODS"
99
+ ODT = "ODT"
100
+ OGA = "OGA"
101
+ OGV = "OGV"
102
+ OTF = "OTF"
103
+ OTG = "OTG"
104
+ OTP = "OTP"
105
+ OTS = "OTS"
106
+ OTT = "OTT"
107
+ OWL = "OWL"
108
+ P7S = "P7S"
109
+ PAT = "PAT"
110
+ PDF = "PDF"
111
+ PHP = "PHP"
112
+ PL = "PL"
113
+ PNG = "PNG"
114
+ PPT = "PPT"
115
+ PPTX = "PPTX"
116
+ PS = "PS"
117
+ PSD = "PSD"
118
+ PUB = "PUB"
119
+ PY = "PY"
120
+ QCP = "QCP"
121
+ RAR = "RAR"
122
+ RMVB = "RMVB"
123
+ RPM = "RPM"
124
+ RSS = "RSS"
125
+ RTF = "RTF"
126
+ SHP = "SHP"
127
+ SHX = "SHX"
128
+ SO = "SO"
129
+ SQLITE = "SQLITE"
130
+ SRT = "SRT"
131
+ SVG = "SVG"
132
+ SWF = "SWF"
133
+ SXC = "SXC"
134
+ TAR = "TAR"
135
+ TCL = "TCL"
136
+ TCX = "TCX"
137
+ TIFF = "TIFF"
138
+ TORRENT = "TORRENT"
139
+ TSV = "TSV"
140
+ TTC = "TTC"
141
+ TTF = "TTF"
142
+ TXT = "TXT"
143
+ VCF = "VCF"
144
+ VOC = "VOC"
145
+ VTT = "VTT"
146
+ WARC = "WARC"
147
+ WASM = "WASM"
148
+ WAV = "WAV"
149
+ WEBM = "WEBM"
150
+ WEBP = "WEBP"
151
+ WOFF = "WOFF"
152
+ WOFF2 = "WOFF2"
153
+ X3D = "X3D"
154
+ XAR = "XAR"
155
+ XCF = "XCF"
156
+ XFDF = "XFDF"
157
+ XLF = "XLF"
158
+ XLS = "XLS"
159
+ XLSX = "XLSX"
160
+ XML = "XML"
161
+ XPM = "XPM"
162
+ XZ = "XZ"
163
+ ZIP = "ZIP"
164
+ ZST = "ZST"
165
+
166
+ def __str__(self):
167
+ return str(self.value)
168
+
169
+ def __repr__(self):
170
+ return str(self.value)