pangea-sdk 6.1.1__py3-none-any.whl → 6.2.0b2__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 +9 -1
- pangea/asyncio/__init__.py +1 -0
- pangea/asyncio/file_uploader.py +4 -2
- pangea/asyncio/request.py +199 -35
- pangea/asyncio/services/__init__.py +3 -0
- pangea/asyncio/services/ai_guard.py +91 -2
- pangea/asyncio/services/audit.py +307 -2
- pangea/asyncio/services/authn.py +12 -2
- pangea/asyncio/services/base.py +4 -0
- pangea/asyncio/services/file_scan.py +7 -1
- pangea/asyncio/services/intel.py +6 -2
- pangea/asyncio/services/management.py +576 -0
- pangea/asyncio/services/prompt_guard.py +112 -2
- pangea/asyncio/services/redact.py +269 -4
- pangea/asyncio/services/sanitize.py +5 -1
- pangea/asyncio/services/share.py +5 -1
- pangea/asyncio/services/vault.py +4 -0
- pangea/audit_logger.py +3 -1
- pangea/deep_verify.py +13 -13
- pangea/deprecated.py +1 -1
- pangea/dump_audit.py +2 -3
- pangea/exceptions.py +8 -5
- pangea/file_uploader.py +4 -0
- pangea/request.py +205 -52
- pangea/response.py +15 -12
- pangea/services/__init__.py +3 -0
- pangea/services/ai_guard.py +497 -16
- pangea/services/audit/audit.py +310 -8
- pangea/services/audit/models.py +279 -0
- pangea/services/audit/signing.py +1 -1
- pangea/services/audit/util.py +10 -10
- pangea/services/authn/authn.py +12 -2
- pangea/services/authn/models.py +3 -0
- pangea/services/authz.py +4 -0
- pangea/services/base.py +5 -1
- pangea/services/embargo.py +6 -0
- pangea/services/file_scan.py +7 -1
- pangea/services/intel.py +4 -0
- pangea/services/management.py +720 -0
- pangea/services/prompt_guard.py +193 -2
- pangea/services/redact.py +477 -7
- pangea/services/sanitize.py +5 -1
- pangea/services/share/share.py +13 -7
- pangea/services/vault/models/asymmetric.py +4 -0
- pangea/services/vault/models/common.py +4 -0
- pangea/services/vault/models/symmetric.py +4 -0
- pangea/services/vault/vault.py +2 -4
- pangea/tools.py +13 -9
- pangea/utils.py +3 -5
- pangea/verify_audit.py +23 -27
- {pangea_sdk-6.1.1.dist-info → pangea_sdk-6.2.0b2.dist-info}/METADATA +4 -4
- pangea_sdk-6.2.0b2.dist-info/RECORD +62 -0
- pangea_sdk-6.1.1.dist-info/RECORD +0 -60
- {pangea_sdk-6.1.1.dist-info → pangea_sdk-6.2.0b2.dist-info}/WHEEL +0 -0
@@ -1,13 +1,20 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
|
-
from
|
9
|
+
from collections.abc import Mapping, Sequence
|
10
|
+
from typing import Dict, List, Literal, Optional, Union, cast, overload
|
11
|
+
|
12
|
+
from pydantic import TypeAdapter
|
6
13
|
|
7
14
|
import pangea.services.redact as m
|
8
15
|
from pangea.asyncio.services.base import ServiceBaseAsync
|
9
16
|
from pangea.config import PangeaConfig
|
10
|
-
from pangea.response import PangeaResponse
|
17
|
+
from pangea.response import PangeaResponse, PangeaResponseResult
|
11
18
|
|
12
19
|
|
13
20
|
class RedactAsync(ServiceBaseAsync):
|
@@ -64,7 +71,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
64
71
|
rules: Optional[List[str]] = None,
|
65
72
|
rulesets: Optional[List[str]] = None,
|
66
73
|
return_result: Optional[bool] = None,
|
67
|
-
redaction_method_overrides:
|
74
|
+
redaction_method_overrides: Mapping[str, m.RedactionMethodOverrides] | None = None,
|
68
75
|
llm_request: Optional[bool] = None,
|
69
76
|
vault_parameters: Optional[m.VaultParameters] = None,
|
70
77
|
) -> PangeaResponse[m.RedactResult]:
|
@@ -119,7 +126,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
119
126
|
rules: Optional[List[str]] = None,
|
120
127
|
rulesets: Optional[List[str]] = None,
|
121
128
|
return_result: Optional[bool] = None,
|
122
|
-
redaction_method_overrides:
|
129
|
+
redaction_method_overrides: Mapping[str, m.RedactionMethodOverrides] | None = None,
|
123
130
|
llm_request: bool | None = None,
|
124
131
|
vault_parameters: m.VaultParameters | None = None,
|
125
132
|
) -> PangeaResponse[m.StructuredResult]:
|
@@ -200,3 +207,261 @@ class RedactAsync(ServiceBaseAsync):
|
|
200
207
|
"""
|
201
208
|
input = m.UnredactRequest(redacted_data=redacted_data, fpe_context=fpe_context)
|
202
209
|
return await self.request.post("v1/unredact", m.UnredactResult, data=input.model_dump(exclude_none=True))
|
210
|
+
|
211
|
+
async def get_service_config(self, config_id: str) -> PangeaResponse[m.ServiceConfigResult]:
|
212
|
+
"""
|
213
|
+
Get a service config.
|
214
|
+
|
215
|
+
|
216
|
+
OperationId: redact_post_v1beta_config
|
217
|
+
"""
|
218
|
+
response = await self.request.post("v1beta/config", PangeaResponseResult, data={"id": config_id})
|
219
|
+
response.result = TypeAdapter(m.ServiceConfigResult).validate_python(response.json["result"])
|
220
|
+
return cast(PangeaResponse[m.ServiceConfigResult], response)
|
221
|
+
|
222
|
+
@overload
|
223
|
+
async def create_service_config(
|
224
|
+
self,
|
225
|
+
name: str,
|
226
|
+
*,
|
227
|
+
version: Literal["1.0.0"],
|
228
|
+
enabled_rules: Sequence[str] | None = None,
|
229
|
+
redactions: Mapping[str, m.Redaction] | None = None,
|
230
|
+
vault_service_config_id: str | None = None,
|
231
|
+
salt_vault_secret_id: str | None = None,
|
232
|
+
rules: Mapping[str, m.RuleV1] | None = None,
|
233
|
+
rulesets: Mapping[str, m.RulesetV1] | None = None,
|
234
|
+
supported_languages: Sequence[Literal["en"]] | None = None,
|
235
|
+
) -> PangeaResponse[m.ServiceConfigResult]:
|
236
|
+
"""
|
237
|
+
Create a v1.0.0 service config.
|
238
|
+
|
239
|
+
OperationId: redact_post_v1beta_config_create
|
240
|
+
|
241
|
+
Args:
|
242
|
+
vault_service_config_id: Service config used to create the secret
|
243
|
+
salt_vault_secret_id: Pangea only allows hashing to be done using a salt value to prevent brute-force attacks.
|
244
|
+
"""
|
245
|
+
|
246
|
+
@overload
|
247
|
+
async def create_service_config(
|
248
|
+
self,
|
249
|
+
name: str,
|
250
|
+
*,
|
251
|
+
version: Literal["2.0.0"] | None = None,
|
252
|
+
enabled_rules: Sequence[str] | None = None,
|
253
|
+
enforce_enabled_rules: bool | None = None,
|
254
|
+
redactions: Mapping[str, m.Redaction] | None = None,
|
255
|
+
vault_service_config_id: str | None = None,
|
256
|
+
salt_vault_secret_id: str | None = None,
|
257
|
+
fpe_vault_secret_id: str | None = None,
|
258
|
+
rules: Mapping[str, m.RuleV2] | None = None,
|
259
|
+
rulesets: Mapping[str, m.RulesetV2] | None = None,
|
260
|
+
supported_languages: Sequence[Literal["en"]] | None = None,
|
261
|
+
) -> PangeaResponse[m.ServiceConfigResult]:
|
262
|
+
"""
|
263
|
+
Create a v2.0.0 service config.
|
264
|
+
|
265
|
+
OperationId: redact_post_v1beta_config_create
|
266
|
+
|
267
|
+
Args:
|
268
|
+
enforce_enabled_rules: Always run service config enabled rules across all redact calls regardless of flags?
|
269
|
+
vault_service_config_id: Service config used to create the secret
|
270
|
+
salt_vault_secret_id: Pangea only allows hashing to be done using a salt value to prevent brute-force attacks.
|
271
|
+
fpe_vault_secret_id: The ID of the key used by FF3 Encryption algorithms for FPE.
|
272
|
+
"""
|
273
|
+
|
274
|
+
async def create_service_config(
|
275
|
+
self,
|
276
|
+
name: str,
|
277
|
+
*,
|
278
|
+
version: Literal["1.0.0", "2.0.0"] | None = None,
|
279
|
+
enabled_rules: Sequence[str] | None = None,
|
280
|
+
enforce_enabled_rules: bool | None = None,
|
281
|
+
fpe_vault_secret_id: str | None = None,
|
282
|
+
redactions: Mapping[str, m.Redaction] | None = None,
|
283
|
+
rules: Mapping[str, m.RuleV1 | m.RuleV2] | None = None,
|
284
|
+
rulesets: Mapping[str, m.RulesetV1 | m.RulesetV2] | None = None,
|
285
|
+
salt_vault_secret_id: str | None = None,
|
286
|
+
supported_languages: Sequence[Literal["en"]] | None = None,
|
287
|
+
vault_service_config_id: str | None = None,
|
288
|
+
) -> PangeaResponse[m.ServiceConfigResult]:
|
289
|
+
"""
|
290
|
+
Create a service config.
|
291
|
+
|
292
|
+
OperationId: redact_post_v1beta_config_create
|
293
|
+
|
294
|
+
Args:
|
295
|
+
enforce_enabled_rules: Always run service config enabled rules across all redact calls regardless of flags?
|
296
|
+
fpe_vault_secret_id: The ID of the key used by FF3 Encryption algorithms for FPE.
|
297
|
+
salt_vault_secret_id: Pangea only allows hashing to be done using a salt value to prevent brute-force attacks.
|
298
|
+
vault_service_config_id: Service config used to create the secret
|
299
|
+
"""
|
300
|
+
|
301
|
+
response = await self.request.post(
|
302
|
+
"v1beta/config/create",
|
303
|
+
PangeaResponseResult,
|
304
|
+
data={
|
305
|
+
"name": name,
|
306
|
+
"version": version,
|
307
|
+
"enabled_rules": enabled_rules,
|
308
|
+
"enforce_enabled_rules": enforce_enabled_rules,
|
309
|
+
"fpe_vault_secret_id": fpe_vault_secret_id,
|
310
|
+
"redactions": redactions,
|
311
|
+
"rules": rules,
|
312
|
+
"rulesets": rulesets,
|
313
|
+
"salt_vault_secret_id": salt_vault_secret_id,
|
314
|
+
"supported_languages": supported_languages,
|
315
|
+
"vault_service_config_id": vault_service_config_id,
|
316
|
+
},
|
317
|
+
)
|
318
|
+
response.result = TypeAdapter(m.ServiceConfigResult).validate_python(response.json["result"])
|
319
|
+
return cast(PangeaResponse[m.ServiceConfigResult], response)
|
320
|
+
|
321
|
+
@overload
|
322
|
+
async def update_service_config(
|
323
|
+
self,
|
324
|
+
config_id: str,
|
325
|
+
*,
|
326
|
+
version: Literal["1.0.0"],
|
327
|
+
name: str,
|
328
|
+
updated_at: str,
|
329
|
+
enabled_rules: Sequence[str] | None = None,
|
330
|
+
redactions: Mapping[str, m.Redaction] | None = None,
|
331
|
+
vault_service_config_id: str | None = None,
|
332
|
+
salt_vault_secret_id: str | None = None,
|
333
|
+
rules: Mapping[str, m.RuleV1] | None = None,
|
334
|
+
rulesets: Mapping[str, m.RulesetV1] | None = None,
|
335
|
+
supported_languages: Sequence[Literal["en"]] | None = None,
|
336
|
+
) -> PangeaResponse[m.ServiceConfigResult]:
|
337
|
+
"""
|
338
|
+
Update a v1.0.0 service config.
|
339
|
+
|
340
|
+
OperationId: redact_post_v1beta_config_update
|
341
|
+
|
342
|
+
Args:
|
343
|
+
vault_service_config_id: Service config used to create the secret
|
344
|
+
salt_vault_secret_id: Pangea only allows hashing to be done using a salt value to prevent brute-force attacks.
|
345
|
+
"""
|
346
|
+
|
347
|
+
@overload
|
348
|
+
async def update_service_config(
|
349
|
+
self,
|
350
|
+
config_id: str,
|
351
|
+
*,
|
352
|
+
version: Literal["2.0.0"] | None = None,
|
353
|
+
name: str,
|
354
|
+
updated_at: str,
|
355
|
+
enabled_rules: Sequence[str] | None = None,
|
356
|
+
enforce_enabled_rules: bool | None = None,
|
357
|
+
redactions: Mapping[str, m.Redaction] | None = None,
|
358
|
+
vault_service_config_id: str | None = None,
|
359
|
+
salt_vault_secret_id: str | None = None,
|
360
|
+
fpe_vault_secret_id: str | None = None,
|
361
|
+
rules: Mapping[str, m.RuleV2] | None = None,
|
362
|
+
rulesets: Mapping[str, m.RulesetV2] | None = None,
|
363
|
+
supported_languages: Sequence[Literal["en"]] | None = None,
|
364
|
+
) -> PangeaResponse[m.ServiceConfigResult]:
|
365
|
+
"""
|
366
|
+
Update a v2.0.0 service config.
|
367
|
+
|
368
|
+
OperationId: redact_post_v1beta_config_update
|
369
|
+
|
370
|
+
Args:
|
371
|
+
enforce_enabled_rules: Always run service config enabled rules across all redact calls regardless of flags?
|
372
|
+
vault_service_config_id: Service config used to create the secret
|
373
|
+
salt_vault_secret_id: Pangea only allows hashing to be done using a salt value to prevent brute-force attacks.
|
374
|
+
fpe_vault_secret_id: The ID of the key used by FF3 Encryption algorithms for FPE.
|
375
|
+
"""
|
376
|
+
|
377
|
+
async def update_service_config(
|
378
|
+
self,
|
379
|
+
config_id: str,
|
380
|
+
*,
|
381
|
+
version: Literal["1.0.0", "2.0.0"] | None = None,
|
382
|
+
name: str,
|
383
|
+
updated_at: str,
|
384
|
+
enabled_rules: Sequence[str] | None = None,
|
385
|
+
enforce_enabled_rules: bool | None = None,
|
386
|
+
fpe_vault_secret_id: str | None = None,
|
387
|
+
redactions: Mapping[str, m.Redaction] | None = None,
|
388
|
+
rules: Mapping[str, m.RuleV1 | m.RuleV2] | None = None,
|
389
|
+
rulesets: Mapping[str, m.RulesetV1 | m.RulesetV2] | None = None,
|
390
|
+
salt_vault_secret_id: str | None = None,
|
391
|
+
supported_languages: Sequence[Literal["en"]] | None = None,
|
392
|
+
vault_service_config_id: str | None = None,
|
393
|
+
) -> PangeaResponse[m.ServiceConfigResult]:
|
394
|
+
"""
|
395
|
+
Update a service config.
|
396
|
+
|
397
|
+
OperationId: redact_post_v1beta_config_update
|
398
|
+
|
399
|
+
Args:
|
400
|
+
enforce_enabled_rules: Always run service config enabled rules across all redact calls regardless of flags?
|
401
|
+
fpe_vault_secret_id: The ID of the key used by FF3 Encryption algorithms for FPE.
|
402
|
+
salt_vault_secret_id: Pangea only allows hashing to be done using a salt value to prevent brute-force attacks.
|
403
|
+
vault_service_config_id: Service config used to create the secret
|
404
|
+
"""
|
405
|
+
|
406
|
+
response = await self.request.post(
|
407
|
+
"v1beta/config/update",
|
408
|
+
PangeaResponseResult,
|
409
|
+
data={
|
410
|
+
"id": config_id,
|
411
|
+
"updated_at": updated_at,
|
412
|
+
"name": name,
|
413
|
+
"version": version,
|
414
|
+
"enabled_rules": enabled_rules,
|
415
|
+
"enforce_enabled_rules": enforce_enabled_rules,
|
416
|
+
"fpe_vault_secret_id": fpe_vault_secret_id,
|
417
|
+
"redactions": redactions,
|
418
|
+
"rules": rules,
|
419
|
+
"rulesets": rulesets,
|
420
|
+
"salt_vault_secret_id": salt_vault_secret_id,
|
421
|
+
"supported_languages": supported_languages,
|
422
|
+
"vault_service_config_id": vault_service_config_id,
|
423
|
+
},
|
424
|
+
)
|
425
|
+
response.result = TypeAdapter(m.ServiceConfigResult).validate_python(response.json["result"])
|
426
|
+
return cast(PangeaResponse[m.ServiceConfigResult], response)
|
427
|
+
|
428
|
+
async def delete_service_config(self, config_id: str) -> PangeaResponse[m.ServiceConfigResult]:
|
429
|
+
"""
|
430
|
+
Delete a service config.
|
431
|
+
|
432
|
+
OperationId: redact_post_v1beta_config_delete
|
433
|
+
|
434
|
+
Args:
|
435
|
+
config_id: An ID for a service config
|
436
|
+
"""
|
437
|
+
|
438
|
+
response = await self.request.post("v1beta/config/delete", PangeaResponseResult, data={"id": config_id})
|
439
|
+
response.result = TypeAdapter(m.ServiceConfigResult).validate_python(response.json["result"])
|
440
|
+
return cast(PangeaResponse[m.ServiceConfigResult], response)
|
441
|
+
|
442
|
+
async def list_service_configs(
|
443
|
+
self,
|
444
|
+
*,
|
445
|
+
filter: m.ServiceConfigFilter | None = None,
|
446
|
+
last: str | None = None,
|
447
|
+
order: Literal["asc", "desc"] | None = None,
|
448
|
+
order_by: Literal["id", "created_at", "updated_at"] | None = None,
|
449
|
+
size: int | None = None,
|
450
|
+
) -> PangeaResponse[m.ServiceConfigListResult]:
|
451
|
+
"""
|
452
|
+
List service configs.
|
453
|
+
|
454
|
+
OperationId: redact_post_v1beta_config_list
|
455
|
+
|
456
|
+
Args:
|
457
|
+
last: Reflected value from a previous response to obtain the next page of results.
|
458
|
+
order: Order results asc(ending) or desc(ending).
|
459
|
+
order_by: Which field to order results by.
|
460
|
+
size: Maximum results to include in the response.
|
461
|
+
"""
|
462
|
+
|
463
|
+
return await self.request.post(
|
464
|
+
"v1beta/config/list",
|
465
|
+
m.ServiceConfigListResult,
|
466
|
+
data={"filter": filter, "last": last, "order": order, "order_by": order_by, "size": size},
|
467
|
+
)
|
@@ -1,5 +1,9 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
9
|
import io
|
@@ -116,7 +120,7 @@ class SanitizeAsync(ServiceBaseAsync):
|
|
116
120
|
files: Optional[List[Tuple]] = None
|
117
121
|
if file or file_path:
|
118
122
|
if file_path:
|
119
|
-
file = open(file_path, "rb")
|
123
|
+
file = open(file_path, "rb") # noqa: SIM115
|
120
124
|
if transfer_method == TransferMethod.POST_URL and (sha256 is None or crc32c is None or size is None):
|
121
125
|
params = get_file_upload_params(file) # type: ignore[arg-type]
|
122
126
|
crc32c = params.crc_hex if crc32c is None else crc32c
|
pangea/asyncio/services/share.py
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
9
|
import io
|
@@ -194,7 +198,7 @@ class ShareAsync(ServiceBaseAsync):
|
|
194
198
|
|
195
199
|
async def get_archive(
|
196
200
|
self,
|
197
|
-
ids:
|
201
|
+
ids: list[str],
|
198
202
|
format: Optional[m.ArchiveFormat] = None,
|
199
203
|
transfer_method: Optional[TransferMethod] = None,
|
200
204
|
bucket_id: Optional[str] = None,
|
pangea/asyncio/services/vault.py
CHANGED
pangea/audit_logger.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import logging
|
4
6
|
|
5
7
|
import pangea.exceptions as pe
|
@@ -20,7 +22,7 @@ class AuditLogger(logging.Logger):
|
|
20
22
|
"""
|
21
23
|
|
22
24
|
def __init__(self, *args, **kwargs):
|
23
|
-
super(
|
25
|
+
super().__init__(*args, **kwargs)
|
24
26
|
|
25
27
|
def set_auditor(self, auditor: Audit):
|
26
28
|
"""Sets the internal Pangea Audit Service client instance
|
pangea/deep_verify.py
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
3
|
|
4
|
+
from __future__ import annotations
|
5
|
+
|
4
6
|
import argparse
|
5
7
|
import io
|
6
8
|
import math
|
7
9
|
import os
|
8
10
|
import sys
|
11
|
+
from collections.abc import Iterator
|
9
12
|
from itertools import groupby
|
10
|
-
from typing import
|
13
|
+
from typing import Optional, TypedDict, Union
|
11
14
|
|
12
15
|
import pangea.services.audit.util as audit_util
|
13
16
|
from pangea.services import Audit
|
@@ -24,7 +27,7 @@ class Errors(TypedDict):
|
|
24
27
|
buffer_missing: int
|
25
28
|
|
26
29
|
|
27
|
-
root_hashes:
|
30
|
+
root_hashes: dict[int, str] = {}
|
28
31
|
|
29
32
|
|
30
33
|
def num_lines(f: io.TextIOWrapper) -> int:
|
@@ -124,10 +127,7 @@ def get_root_hash(audit: Audit, tree_size: int) -> str:
|
|
124
127
|
|
125
128
|
|
126
129
|
def print_error(msg: str, level: str = "error"):
|
127
|
-
if level == "warning"
|
128
|
-
dot = "🟡"
|
129
|
-
else:
|
130
|
-
dot = "🔴"
|
130
|
+
dot = "🟡" if level == "warning" else "🔴"
|
131
131
|
print(f"{dot} {msg:200s}")
|
132
132
|
|
133
133
|
|
@@ -148,14 +148,14 @@ def deep_verify(audit: Audit, file: io.TextIOWrapper) -> Errors:
|
|
148
148
|
}
|
149
149
|
|
150
150
|
events = file_events(root_hashes, file)
|
151
|
-
events_by_idx: Union[
|
151
|
+
events_by_idx: Union[list[Event], Iterator[Event]]
|
152
152
|
cold_indexes = SequenceFollower()
|
153
153
|
for leaf_index, events_by_idx in groupby(events, lambda event: event.get("leaf_index")):
|
154
154
|
events_by_idx = list(events_by_idx)
|
155
155
|
buffer_lines = (cnt, cnt + len(events_by_idx) - 1)
|
156
156
|
if leaf_index is None:
|
157
157
|
print_error(
|
158
|
-
f"Lines {buffer_lines[0]}-{buffer_lines[1]} ({buffer_lines[1]-buffer_lines[0]+1}): Buffer was not persisted"
|
158
|
+
f"Lines {buffer_lines[0]}-{buffer_lines[1]} ({buffer_lines[1] - buffer_lines[0] + 1}): Buffer was not persisted"
|
159
159
|
)
|
160
160
|
errors["not_persisted"] += len(events_by_idx)
|
161
161
|
cnt += len(events_by_idx)
|
@@ -164,8 +164,8 @@ def deep_verify(audit: Audit, file: io.TextIOWrapper) -> Errors:
|
|
164
164
|
cold_indexes.add(leaf_index)
|
165
165
|
|
166
166
|
cold_path_size: Optional[int] = None
|
167
|
-
hot_indexes:
|
168
|
-
for
|
167
|
+
hot_indexes: set[int] = set()
|
168
|
+
for _i, event in enumerate(events_by_idx):
|
169
169
|
cnt += 1
|
170
170
|
tree_size = get_tree_size(event)
|
171
171
|
if tree_size not in root_hashes:
|
@@ -203,11 +203,11 @@ def deep_verify(audit: Audit, file: io.TextIOWrapper) -> Errors:
|
|
203
203
|
errors["missing"] += len(hot_indexes_diff)
|
204
204
|
print(f"missing hot indexes: {hot_indexes_diff}")
|
205
205
|
print(f"hot_indexes: {hot_indexes} ")
|
206
|
-
print(
|
206
|
+
print("events:")
|
207
207
|
for e in events_by_idx:
|
208
208
|
print(e)
|
209
209
|
print_error(
|
210
|
-
f"Lines {buffer_lines[0]}-{buffer_lines[1]} ({buffer_lines[1]-buffer_lines[0]}), Buffer #{cold_idx}: {len(hot_indexes_diff)} event(s) missing"
|
210
|
+
f"Lines {buffer_lines[0]}-{buffer_lines[1]} ({buffer_lines[1] - buffer_lines[0]}), Buffer #{cold_idx}: {len(hot_indexes_diff)} event(s) missing"
|
211
211
|
)
|
212
212
|
|
213
213
|
cold_holes = cold_indexes.holes()
|
@@ -232,7 +232,7 @@ def create_parser():
|
|
232
232
|
"-f",
|
233
233
|
required=True,
|
234
234
|
type=argparse.FileType("r"),
|
235
|
-
help="Event input file. Must be a collection of
|
235
|
+
help="Event input file. Must be a collection of JSON Objects separated by newlines",
|
236
236
|
)
|
237
237
|
return parser
|
238
238
|
|
pangea/deprecated.py
CHANGED
pangea/dump_audit.py
CHANGED
@@ -7,7 +7,6 @@ import json
|
|
7
7
|
import os
|
8
8
|
import sys
|
9
9
|
from datetime import datetime
|
10
|
-
from typing import Tuple
|
11
10
|
|
12
11
|
import dateutil.parser
|
13
12
|
|
@@ -103,7 +102,7 @@ def dump_after(audit: Audit, output: io.TextIOWrapper, start: datetime, last_eve
|
|
103
102
|
|
104
103
|
def dump_page(
|
105
104
|
audit: Audit, output: io.TextIOWrapper, start: datetime, end: datetime, first: bool = False
|
106
|
-
) ->
|
105
|
+
) -> tuple[datetime, int, bool, str, int]:
|
107
106
|
PAGE_SIZE = 1000
|
108
107
|
print(start, end)
|
109
108
|
print("Dumping...")
|
@@ -175,7 +174,7 @@ def parse_args(parser: argparse.ArgumentParser):
|
|
175
174
|
raise ValueError("domain missing")
|
176
175
|
|
177
176
|
if args.output is None:
|
178
|
-
args.output = open(f"dump-{datetime.now().strftime('%Y%m%d%H%M%S')}.jsonl", "w")
|
177
|
+
args.output = open(f"dump-{datetime.now().strftime('%Y%m%d%H%M%S')}.jsonl", "w") # noqa: SIM115
|
179
178
|
|
180
179
|
args.start = make_aware_datetime(args.start)
|
181
180
|
args.end = make_aware_datetime(args.end)
|
pangea/exceptions.py
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
3
|
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
4
7
|
from typing import List, Optional
|
5
8
|
|
6
9
|
from pangea.response import AcceptedResult, ErrorField, PangeaResponse
|
@@ -44,7 +47,7 @@ class PangeaAPIException(PangeaException):
|
|
44
47
|
response: PangeaResponse
|
45
48
|
|
46
49
|
def __init__(self, message: str, response: PangeaResponse):
|
47
|
-
super(
|
50
|
+
super().__init__(message)
|
48
51
|
self.response = response
|
49
52
|
|
50
53
|
@property
|
@@ -92,7 +95,7 @@ class UnauthorizedException(PangeaAPIException):
|
|
92
95
|
|
93
96
|
def __init__(self, service_name: str, response: PangeaResponse):
|
94
97
|
message = f"User is not authorized to access service {service_name}"
|
95
|
-
super(
|
98
|
+
super().__init__(message, response)
|
96
99
|
|
97
100
|
|
98
101
|
class NotFound(PangeaAPIException):
|
@@ -100,20 +103,20 @@ class NotFound(PangeaAPIException):
|
|
100
103
|
|
101
104
|
def __init__(self, url: str, response: PangeaResponse):
|
102
105
|
message = f"Resource url:'{url}' not found"
|
103
|
-
super(
|
106
|
+
super().__init__(message, response)
|
104
107
|
|
105
108
|
|
106
109
|
class ServiceNotEnabledException(PangeaAPIException):
|
107
110
|
def __init__(self, service_name: str, response: PangeaResponse):
|
108
111
|
message = f"{service_name} is not enabled. Go to console.pangea.cloud/service/{service_name} to enable"
|
109
|
-
super(
|
112
|
+
super().__init__(message, response)
|
110
113
|
|
111
114
|
|
112
115
|
class MissingConfigID(PangeaAPIException):
|
113
116
|
"""No config ID was provided in either token scopes or explicitly"""
|
114
117
|
|
115
118
|
def __init__(self, service_name: str, response: PangeaResponse):
|
116
|
-
super(
|
119
|
+
super().__init__(
|
117
120
|
f"Token did not contain a config scope for service {service_name}. Create a new token or provide a config ID explicitly in the service base",
|
118
121
|
response,
|
119
122
|
)
|