pangea-sdk 6.2.0b1__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 +51 -21
- pangea/asyncio/services/__init__.py +2 -0
- pangea/asyncio/services/ai_guard.py +91 -2
- pangea/asyncio/services/audit.py +14 -8
- pangea/asyncio/services/authn.py +33 -23
- pangea/asyncio/services/authz.py +6 -6
- pangea/asyncio/services/base.py +4 -0
- pangea/asyncio/services/file_scan.py +8 -2
- pangea/asyncio/services/intel.py +6 -2
- pangea/asyncio/services/prompt_guard.py +112 -2
- pangea/asyncio/services/redact.py +7 -3
- pangea/asyncio/services/sanitize.py +5 -1
- pangea/asyncio/services/share.py +5 -1
- pangea/asyncio/services/vault.py +19 -15
- 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 +58 -41
- pangea/response.py +15 -12
- pangea/services/__init__.py +2 -0
- pangea/services/ai_guard.py +497 -16
- pangea/services/audit/audit.py +15 -13
- pangea/services/audit/models.py +4 -0
- pangea/services/audit/signing.py +1 -1
- pangea/services/audit/util.py +10 -10
- pangea/services/authn/authn.py +33 -23
- pangea/services/authn/models.py +3 -0
- pangea/services/authz.py +10 -6
- pangea/services/base.py +5 -1
- pangea/services/embargo.py +6 -0
- pangea/services/file_scan.py +8 -2
- pangea/services/intel.py +4 -0
- pangea/services/management.py +8 -8
- pangea/services/prompt_guard.py +193 -2
- pangea/services/redact.py +7 -3
- 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 +17 -19
- pangea/tools.py +13 -9
- pangea/utils.py +3 -5
- pangea/verify_audit.py +23 -27
- {pangea_sdk-6.2.0b1.dist-info → pangea_sdk-6.2.0b2.dist-info}/METADATA +6 -6
- pangea_sdk-6.2.0b2.dist-info/RECORD +62 -0
- {pangea_sdk-6.2.0b1.dist-info → pangea_sdk-6.2.0b2.dist-info}/WHEEL +1 -1
- pangea_sdk-6.2.0b1.dist-info/RECORD +0 -62
pangea/services/ai_guard.py
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from
|
3
|
+
from collections.abc import Mapping
|
4
|
+
from typing import Annotated, Generic, Literal, Optional, Union, overload
|
5
|
+
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, RootModel
|
7
|
+
from typing_extensions import TypeVar
|
4
8
|
|
5
9
|
from pangea.config import PangeaConfig
|
6
|
-
from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
|
10
|
+
from pangea.response import APIRequestModel, APIResponseModel, PangeaDateTime, PangeaResponse, PangeaResponseResult
|
7
11
|
from pangea.services.base import ServiceBase
|
8
12
|
|
9
13
|
# This is named "prompt injection" in the API spec even though it is also used
|
@@ -24,14 +28,14 @@ class CodeDetectionOverride(APIRequestModel):
|
|
24
28
|
|
25
29
|
class LanguageDetectionOverride(APIRequestModel):
|
26
30
|
disabled: Optional[bool] = None
|
27
|
-
allow: Optional[
|
28
|
-
block: Optional[
|
29
|
-
report: Optional[
|
31
|
+
allow: Optional[list[str]] = None
|
32
|
+
block: Optional[list[str]] = None
|
33
|
+
report: Optional[list[str]] = None
|
30
34
|
|
31
35
|
|
32
36
|
class TopicDetectionOverride(APIRequestModel):
|
33
37
|
disabled: Optional[bool] = None
|
34
|
-
block: Optional[
|
38
|
+
block: Optional[list[str]] = None
|
35
39
|
|
36
40
|
|
37
41
|
class PromptInjectionOverride(APIRequestModel):
|
@@ -179,7 +183,7 @@ class PromptInjectionResult(APIResponseModel):
|
|
179
183
|
action: str
|
180
184
|
"""The action taken by this Detector"""
|
181
185
|
|
182
|
-
analyzer_responses:
|
186
|
+
analyzer_responses: list[AnalyzerResponse]
|
183
187
|
"""Triggered prompt injection analyzers."""
|
184
188
|
|
185
189
|
|
@@ -192,20 +196,20 @@ class PiiEntity(APIResponseModel):
|
|
192
196
|
|
193
197
|
|
194
198
|
class PiiEntityResult(APIResponseModel):
|
195
|
-
entities:
|
199
|
+
entities: list[PiiEntity]
|
196
200
|
"""Detected redaction rules."""
|
197
201
|
|
198
202
|
|
199
203
|
class MaliciousEntity(APIResponseModel):
|
200
204
|
type: str
|
201
205
|
value: str
|
202
|
-
action: str
|
206
|
+
action: Optional[str] = None
|
203
207
|
start_pos: Optional[int] = None
|
204
|
-
raw: Optional[
|
208
|
+
raw: Optional[dict[str, object]] = None
|
205
209
|
|
206
210
|
|
207
211
|
class MaliciousEntityResult(APIResponseModel):
|
208
|
-
entities:
|
212
|
+
entities: list[MaliciousEntity]
|
209
213
|
"""Detected harmful items."""
|
210
214
|
|
211
215
|
|
@@ -215,11 +219,11 @@ class CustomEntity(APIResponseModel):
|
|
215
219
|
action: str
|
216
220
|
"""The action taken on this Entity"""
|
217
221
|
start_pos: Optional[int] = None
|
218
|
-
raw: Optional[
|
222
|
+
raw: Optional[dict[str, object]] = None
|
219
223
|
|
220
224
|
|
221
225
|
class CustomEntityResult(APIResponseModel):
|
222
|
-
entities:
|
226
|
+
entities: list[CustomEntity]
|
223
227
|
"""Detected redaction rules."""
|
224
228
|
|
225
229
|
|
@@ -233,7 +237,7 @@ class SecretsEntity(APIResponseModel):
|
|
233
237
|
|
234
238
|
|
235
239
|
class SecretsEntityResult(APIResponseModel):
|
236
|
-
entities:
|
240
|
+
entities: list[SecretsEntity]
|
237
241
|
"""Detected redaction rules."""
|
238
242
|
|
239
243
|
|
@@ -266,9 +270,9 @@ class TextGuardDetectors(APIResponseModel):
|
|
266
270
|
prompt_injection: Optional[TextGuardDetector[PromptInjectionResult]] = None
|
267
271
|
pii_entity: Optional[TextGuardDetector[PiiEntityResult]] = None
|
268
272
|
malicious_entity: Optional[TextGuardDetector[MaliciousEntityResult]] = None
|
269
|
-
custom_entity: Optional[TextGuardDetector[
|
273
|
+
custom_entity: Optional[TextGuardDetector[object]] = None
|
270
274
|
secrets_detection: Optional[TextGuardDetector[SecretsEntityResult]] = None
|
271
|
-
profanity_and_toxicity: Optional[TextGuardDetector[
|
275
|
+
profanity_and_toxicity: Optional[TextGuardDetector[object]] = None
|
272
276
|
language_detection: Optional[TextGuardDetector[LanguageDetectionResult]] = None
|
273
277
|
topic_detection: Optional[TextGuardDetector[TopicDetectionResult]] = None
|
274
278
|
code_detection: Optional[TextGuardDetector[CodeDetectionResult]] = None
|
@@ -297,6 +301,405 @@ class TextGuardResult(PangeaResponseResult, Generic[_T]):
|
|
297
301
|
"""
|
298
302
|
|
299
303
|
|
304
|
+
class Areas(BaseModel):
|
305
|
+
model_config = ConfigDict(extra="forbid")
|
306
|
+
|
307
|
+
text_guard: bool
|
308
|
+
|
309
|
+
|
310
|
+
class AuditDataActivityConfig(BaseModel):
|
311
|
+
model_config = ConfigDict(extra="forbid")
|
312
|
+
|
313
|
+
enabled: bool
|
314
|
+
audit_service_config_id: str
|
315
|
+
areas: Areas
|
316
|
+
|
317
|
+
|
318
|
+
class PromptGuard(BaseModel):
|
319
|
+
model_config = ConfigDict(extra="forbid")
|
320
|
+
|
321
|
+
enabled: Optional[bool] = None
|
322
|
+
config_id: Optional[str] = None
|
323
|
+
confidence_threshold: Optional[float] = None
|
324
|
+
|
325
|
+
|
326
|
+
class IpIntel(BaseModel):
|
327
|
+
model_config = ConfigDict(extra="forbid")
|
328
|
+
|
329
|
+
enabled: Optional[bool] = None
|
330
|
+
config_id: Optional[str] = None
|
331
|
+
reputation_provider: Optional[str] = None
|
332
|
+
risk_threshold: Optional[float] = None
|
333
|
+
|
334
|
+
|
335
|
+
class UserIntel(BaseModel):
|
336
|
+
model_config = ConfigDict(extra="forbid")
|
337
|
+
|
338
|
+
enabled: Optional[bool] = None
|
339
|
+
config_id: Optional[str] = None
|
340
|
+
breach_provider: Optional[str] = None
|
341
|
+
|
342
|
+
|
343
|
+
class UrlIntel(BaseModel):
|
344
|
+
model_config = ConfigDict(extra="forbid")
|
345
|
+
|
346
|
+
enabled: Optional[bool] = None
|
347
|
+
config_id: Optional[str] = None
|
348
|
+
reputation_provider: Optional[str] = None
|
349
|
+
risk_threshold: Optional[float] = None
|
350
|
+
|
351
|
+
|
352
|
+
class DomainIntel(BaseModel):
|
353
|
+
model_config = ConfigDict(extra="forbid")
|
354
|
+
|
355
|
+
enabled: Optional[bool] = None
|
356
|
+
config_id: Optional[str] = None
|
357
|
+
reputation_provider: Optional[str] = None
|
358
|
+
risk_threshold: Optional[float] = None
|
359
|
+
|
360
|
+
|
361
|
+
class FileScan(BaseModel):
|
362
|
+
model_config = ConfigDict(extra="forbid")
|
363
|
+
|
364
|
+
enabled: Optional[bool] = None
|
365
|
+
config_id: Optional[str] = None
|
366
|
+
scan_provider: Optional[str] = None
|
367
|
+
risk_threshold: Optional[float] = None
|
368
|
+
|
369
|
+
|
370
|
+
class Redact(BaseModel):
|
371
|
+
model_config = ConfigDict(extra="forbid")
|
372
|
+
|
373
|
+
enabled: Optional[bool] = None
|
374
|
+
config_id: Optional[str] = None
|
375
|
+
|
376
|
+
|
377
|
+
class Vault(BaseModel):
|
378
|
+
model_config = ConfigDict(extra="forbid")
|
379
|
+
|
380
|
+
config_id: Optional[str] = None
|
381
|
+
|
382
|
+
|
383
|
+
class Lingua(BaseModel):
|
384
|
+
model_config = ConfigDict(extra="forbid")
|
385
|
+
|
386
|
+
enabled: Optional[bool] = None
|
387
|
+
|
388
|
+
|
389
|
+
class Code(BaseModel):
|
390
|
+
model_config = ConfigDict(extra="forbid")
|
391
|
+
|
392
|
+
enabled: Optional[bool] = None
|
393
|
+
|
394
|
+
|
395
|
+
class ConnectionsConfig(BaseModel):
|
396
|
+
model_config = ConfigDict(extra="forbid")
|
397
|
+
|
398
|
+
prompt_guard: Optional[PromptGuard] = None
|
399
|
+
ip_intel: Optional[IpIntel] = None
|
400
|
+
user_intel: Optional[UserIntel] = None
|
401
|
+
url_intel: Optional[UrlIntel] = None
|
402
|
+
domain_intel: Optional[DomainIntel] = None
|
403
|
+
file_scan: Optional[FileScan] = None
|
404
|
+
redact: Optional[Redact] = None
|
405
|
+
vault: Optional[Vault] = None
|
406
|
+
lingua: Optional[Lingua] = None
|
407
|
+
code: Optional[Code] = None
|
408
|
+
|
409
|
+
|
410
|
+
class PartialMasking(BaseModel):
|
411
|
+
masking_type: Optional[Literal["unmask", "mask"]] = "unmask"
|
412
|
+
unmasked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
413
|
+
unmasked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
414
|
+
masked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
415
|
+
masked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
416
|
+
chars_to_ignore: Optional[list[CharsToIgnoreItem]] = None
|
417
|
+
masking_char: Annotated[Optional[str], Field(max_length=1, min_length=1)] = "*"
|
418
|
+
|
419
|
+
|
420
|
+
class RuleRedactionConfig1(BaseModel):
|
421
|
+
model_config = ConfigDict(extra="forbid")
|
422
|
+
|
423
|
+
redaction_type: Literal[
|
424
|
+
"mask",
|
425
|
+
"partial_masking",
|
426
|
+
"replacement",
|
427
|
+
"hash",
|
428
|
+
"detect_only",
|
429
|
+
"fpe",
|
430
|
+
"mask",
|
431
|
+
"detect_only",
|
432
|
+
]
|
433
|
+
redaction_value: Optional[str] = None
|
434
|
+
partial_masking: Optional[PartialMasking] = None
|
435
|
+
hash: Optional[Hash] = None
|
436
|
+
fpe_alphabet: Optional[
|
437
|
+
Literal[
|
438
|
+
"numeric",
|
439
|
+
"alphalower",
|
440
|
+
"alphaupper",
|
441
|
+
"alpha",
|
442
|
+
"alphanumericlower",
|
443
|
+
"alphanumericupper",
|
444
|
+
"alphanumeric",
|
445
|
+
]
|
446
|
+
] = None
|
447
|
+
|
448
|
+
|
449
|
+
class PartialMasking1(BaseModel):
|
450
|
+
masking_type: Optional[Literal["unmask", "mask"]] = "unmask"
|
451
|
+
unmasked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
452
|
+
unmasked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
453
|
+
masked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
454
|
+
masked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
455
|
+
chars_to_ignore: Optional[list[CharsToIgnoreItem]] = None
|
456
|
+
masking_char: Annotated[Optional[str], Field(max_length=1, min_length=1)] = "*"
|
457
|
+
|
458
|
+
|
459
|
+
class RuleRedactionConfig2(BaseModel):
|
460
|
+
model_config = ConfigDict(extra="forbid")
|
461
|
+
|
462
|
+
redaction_type: Literal["replacement"]
|
463
|
+
redaction_value: str
|
464
|
+
partial_masking: Optional[PartialMasking1] = None
|
465
|
+
hash: Optional[Hash] = None
|
466
|
+
fpe_alphabet: Optional[
|
467
|
+
Literal[
|
468
|
+
"numeric",
|
469
|
+
"alphalower",
|
470
|
+
"alphaupper",
|
471
|
+
"alpha",
|
472
|
+
"alphanumericlower",
|
473
|
+
"alphanumericupper",
|
474
|
+
"alphanumeric",
|
475
|
+
]
|
476
|
+
] = None
|
477
|
+
|
478
|
+
|
479
|
+
class PartialMasking2(BaseModel):
|
480
|
+
masking_type: Optional[Literal["unmask", "mask"]] = "unmask"
|
481
|
+
unmasked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
482
|
+
unmasked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
483
|
+
masked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
484
|
+
masked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
485
|
+
chars_to_ignore: Optional[list[CharsToIgnoreItem]] = None
|
486
|
+
masking_char: Annotated[Optional[str], Field(max_length=1, min_length=1)] = "*"
|
487
|
+
|
488
|
+
|
489
|
+
class RuleRedactionConfig3(BaseModel):
|
490
|
+
model_config = ConfigDict(extra="forbid")
|
491
|
+
|
492
|
+
redaction_type: Literal["partial_masking"]
|
493
|
+
redaction_value: str
|
494
|
+
partial_masking: PartialMasking2
|
495
|
+
hash: Optional[Hash] = None
|
496
|
+
fpe_alphabet: Optional[
|
497
|
+
Literal[
|
498
|
+
"numeric",
|
499
|
+
"alphalower",
|
500
|
+
"alphaupper",
|
501
|
+
"alpha",
|
502
|
+
"alphanumericlower",
|
503
|
+
"alphanumericupper",
|
504
|
+
"alphanumeric",
|
505
|
+
]
|
506
|
+
] = None
|
507
|
+
|
508
|
+
|
509
|
+
class PartialMasking3(BaseModel):
|
510
|
+
masking_type: Optional[Literal["unmask", "mask"]] = "unmask"
|
511
|
+
unmasked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
512
|
+
unmasked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
513
|
+
masked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
514
|
+
masked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
515
|
+
chars_to_ignore: Optional[list[CharsToIgnoreItem]] = None
|
516
|
+
masking_char: Annotated[Optional[str], Field(max_length=1, min_length=1)] = "*"
|
517
|
+
|
518
|
+
|
519
|
+
class RuleRedactionConfig4(BaseModel):
|
520
|
+
model_config = ConfigDict(extra="forbid")
|
521
|
+
|
522
|
+
redaction_type: Literal["hash"]
|
523
|
+
redaction_value: str
|
524
|
+
partial_masking: PartialMasking3
|
525
|
+
hash: Optional[Hash] = None
|
526
|
+
fpe_alphabet: Optional[
|
527
|
+
Literal[
|
528
|
+
"numeric",
|
529
|
+
"alphalower",
|
530
|
+
"alphaupper",
|
531
|
+
"alpha",
|
532
|
+
"alphanumericlower",
|
533
|
+
"alphanumericupper",
|
534
|
+
"alphanumeric",
|
535
|
+
]
|
536
|
+
] = None
|
537
|
+
|
538
|
+
|
539
|
+
class CharsToIgnoreItem(RootModel[str]):
|
540
|
+
root: Annotated[str, Field(max_length=1, min_length=1)]
|
541
|
+
|
542
|
+
|
543
|
+
class PartialMasking4(BaseModel):
|
544
|
+
masking_type: Optional[Literal["unmask", "mask"]] = "unmask"
|
545
|
+
unmasked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
546
|
+
unmasked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
547
|
+
masked_from_left: Annotated[Optional[int], Field(ge=0)] = None
|
548
|
+
masked_from_right: Annotated[Optional[int], Field(ge=0)] = None
|
549
|
+
chars_to_ignore: Optional[list[CharsToIgnoreItem]] = None
|
550
|
+
masking_char: Annotated[Optional[str], Field(max_length=1, min_length=1)] = "*"
|
551
|
+
|
552
|
+
|
553
|
+
class Hash(BaseModel):
|
554
|
+
hash_type: Literal["md5", "sha256"]
|
555
|
+
"""The type of hashing algorithm"""
|
556
|
+
|
557
|
+
|
558
|
+
class RuleRedactionConfig5(BaseModel):
|
559
|
+
model_config = ConfigDict(extra="forbid")
|
560
|
+
|
561
|
+
redaction_type: Literal["fpe"]
|
562
|
+
redaction_value: str
|
563
|
+
partial_masking: PartialMasking4
|
564
|
+
hash: Optional[Hash] = None
|
565
|
+
fpe_alphabet: Optional[
|
566
|
+
Literal[
|
567
|
+
"numeric",
|
568
|
+
"alphalower",
|
569
|
+
"alphaupper",
|
570
|
+
"alpha",
|
571
|
+
"alphanumericlower",
|
572
|
+
"alphanumericupper",
|
573
|
+
"alphanumeric",
|
574
|
+
]
|
575
|
+
] = None
|
576
|
+
|
577
|
+
|
578
|
+
class Rule(BaseModel):
|
579
|
+
model_config = ConfigDict(extra="forbid")
|
580
|
+
redact_rule_id: str
|
581
|
+
redaction: Union[
|
582
|
+
RuleRedactionConfig1,
|
583
|
+
RuleRedactionConfig2,
|
584
|
+
RuleRedactionConfig3,
|
585
|
+
RuleRedactionConfig4,
|
586
|
+
RuleRedactionConfig5,
|
587
|
+
]
|
588
|
+
block: Optional[bool] = None
|
589
|
+
disabled: Optional[bool] = None
|
590
|
+
reputation_check: Optional[bool] = None
|
591
|
+
transform_if_malicious: Optional[bool] = None
|
592
|
+
|
593
|
+
|
594
|
+
class Settings(BaseModel):
|
595
|
+
rules: Optional[list[Rule]] = None
|
596
|
+
|
597
|
+
|
598
|
+
class DetectorSetting(BaseModel):
|
599
|
+
model_config = ConfigDict(extra="forbid")
|
600
|
+
|
601
|
+
detector_name: str
|
602
|
+
state: Literal["disabled", "enabled"]
|
603
|
+
settings: Settings
|
604
|
+
|
605
|
+
|
606
|
+
class RedactConnectorSettings(BaseModel):
|
607
|
+
fpe_tweak_vault_secret_id: Optional[str] = None
|
608
|
+
|
609
|
+
|
610
|
+
class ConnectorSettings(BaseModel):
|
611
|
+
model_config = ConfigDict(extra="forbid")
|
612
|
+
|
613
|
+
redact: Optional[RedactConnectorSettings] = None
|
614
|
+
|
615
|
+
|
616
|
+
class RecipeConfig(BaseModel):
|
617
|
+
model_config = ConfigDict(extra="forbid")
|
618
|
+
|
619
|
+
name: str
|
620
|
+
description: str
|
621
|
+
version: Optional[str] = ""
|
622
|
+
detectors: Optional[list[DetectorSetting]] = None
|
623
|
+
"""Setting for Detectors"""
|
624
|
+
connector_settings: Optional[ConnectorSettings] = None
|
625
|
+
|
626
|
+
|
627
|
+
class ServiceConfig(PangeaResponseResult):
|
628
|
+
id: Optional[str] = None
|
629
|
+
name: Optional[str] = None
|
630
|
+
audit_data_activity: Optional[AuditDataActivityConfig] = None
|
631
|
+
connections: Optional[ConnectionsConfig] = None
|
632
|
+
recipes: Optional[dict[str, RecipeConfig]] = None
|
633
|
+
|
634
|
+
|
635
|
+
class ServiceConfigFilter(BaseModel):
|
636
|
+
model_config = ConfigDict(extra="forbid")
|
637
|
+
|
638
|
+
id: Optional[str] = None
|
639
|
+
"""
|
640
|
+
Only records where id equals this value.
|
641
|
+
"""
|
642
|
+
id__contains: Optional[list[str]] = None
|
643
|
+
"""
|
644
|
+
Only records where id includes each substring.
|
645
|
+
"""
|
646
|
+
id__in: Optional[list[str]] = None
|
647
|
+
"""
|
648
|
+
Only records where id equals one of the provided substrings.
|
649
|
+
"""
|
650
|
+
created_at: Optional[PangeaDateTime] = None
|
651
|
+
"""
|
652
|
+
Only records where created_at equals this value.
|
653
|
+
"""
|
654
|
+
created_at__gt: Optional[PangeaDateTime] = None
|
655
|
+
"""
|
656
|
+
Only records where created_at is greater than this value.
|
657
|
+
"""
|
658
|
+
created_at__gte: Optional[PangeaDateTime] = None
|
659
|
+
"""
|
660
|
+
Only records where created_at is greater than or equal to this value.
|
661
|
+
"""
|
662
|
+
created_at__lt: Optional[PangeaDateTime] = None
|
663
|
+
"""
|
664
|
+
Only records where created_at is less than this value.
|
665
|
+
"""
|
666
|
+
created_at__lte: Optional[PangeaDateTime] = None
|
667
|
+
"""
|
668
|
+
Only records where created_at is less than or equal to this value.
|
669
|
+
"""
|
670
|
+
updated_at: Optional[PangeaDateTime] = None
|
671
|
+
"""
|
672
|
+
Only records where updated_at equals this value.
|
673
|
+
"""
|
674
|
+
updated_at__gt: Optional[PangeaDateTime] = None
|
675
|
+
"""
|
676
|
+
Only records where updated_at is greater than this value.
|
677
|
+
"""
|
678
|
+
updated_at__gte: Optional[PangeaDateTime] = None
|
679
|
+
"""
|
680
|
+
Only records where updated_at is greater than or equal to this value.
|
681
|
+
"""
|
682
|
+
updated_at__lt: Optional[PangeaDateTime] = None
|
683
|
+
"""
|
684
|
+
Only records where updated_at is less than this value.
|
685
|
+
"""
|
686
|
+
updated_at__lte: Optional[PangeaDateTime] = None
|
687
|
+
"""
|
688
|
+
Only records where updated_at is less than or equal to this value.
|
689
|
+
"""
|
690
|
+
|
691
|
+
|
692
|
+
class ServiceConfigsPage(PangeaResponseResult):
|
693
|
+
count: Optional[int] = None
|
694
|
+
"""The total number of service configs matched by the list request."""
|
695
|
+
last: Optional[str] = None
|
696
|
+
"""
|
697
|
+
Used to fetch the next page of the current listing when provided in a
|
698
|
+
repeated request's last parameter.
|
699
|
+
"""
|
700
|
+
items: Optional[list[ServiceConfig]] = None
|
701
|
+
|
702
|
+
|
300
703
|
class AIGuard(ServiceBase):
|
301
704
|
"""AI Guard service client.
|
302
705
|
|
@@ -455,3 +858,81 @@ class AIGuard(ServiceBase):
|
|
455
858
|
"log_fields": log_fields,
|
456
859
|
},
|
457
860
|
)
|
861
|
+
|
862
|
+
def get_service_config(self, id: str) -> PangeaResponse[ServiceConfig]:
|
863
|
+
"""
|
864
|
+
OperationId: ai_guard_post_v1beta_config
|
865
|
+
"""
|
866
|
+
return self.request.post("v1beta/config", data={"id": id}, result_class=ServiceConfig)
|
867
|
+
|
868
|
+
def create_service_config(
|
869
|
+
self,
|
870
|
+
name: str,
|
871
|
+
*,
|
872
|
+
id: str | None = None,
|
873
|
+
audit_data_activity: AuditDataActivityConfig | None = None,
|
874
|
+
connections: ConnectionsConfig | None = None,
|
875
|
+
recipes: Mapping[str, RecipeConfig] | None = None,
|
876
|
+
) -> PangeaResponse[ServiceConfig]:
|
877
|
+
"""
|
878
|
+
OperationId: ai_guard_post_v1beta_config_create
|
879
|
+
"""
|
880
|
+
return self.request.post(
|
881
|
+
"v1beta/config/create",
|
882
|
+
data={
|
883
|
+
"name": name,
|
884
|
+
"id": id,
|
885
|
+
"audit_data_activity": audit_data_activity,
|
886
|
+
"connections": connections,
|
887
|
+
"recipes": recipes,
|
888
|
+
},
|
889
|
+
result_class=ServiceConfig,
|
890
|
+
)
|
891
|
+
|
892
|
+
def update_service_config(
|
893
|
+
self,
|
894
|
+
id: str,
|
895
|
+
name: str,
|
896
|
+
*,
|
897
|
+
audit_data_activity: AuditDataActivityConfig | None = None,
|
898
|
+
connections: ConnectionsConfig | None = None,
|
899
|
+
recipes: Mapping[str, RecipeConfig] | None = None,
|
900
|
+
) -> PangeaResponse[ServiceConfig]:
|
901
|
+
"""
|
902
|
+
OperationId: ai_guard_post_v1beta_config_update
|
903
|
+
"""
|
904
|
+
return self.request.post(
|
905
|
+
"v1beta/config/update",
|
906
|
+
data={
|
907
|
+
"id": id,
|
908
|
+
"name": name,
|
909
|
+
"audit_data_activity": audit_data_activity,
|
910
|
+
"connections": connections,
|
911
|
+
"recipes": recipes,
|
912
|
+
},
|
913
|
+
result_class=ServiceConfig,
|
914
|
+
)
|
915
|
+
|
916
|
+
def delete_service_config(self, id: str) -> PangeaResponse[ServiceConfig]:
|
917
|
+
"""
|
918
|
+
OperationId: ai_guard_post_v1beta_config_delete
|
919
|
+
"""
|
920
|
+
return self.request.post("v1beta/config/delete", data={"id": id}, result_class=ServiceConfig)
|
921
|
+
|
922
|
+
def list_service_configs(
|
923
|
+
self,
|
924
|
+
*,
|
925
|
+
filter: ServiceConfigFilter | None = None,
|
926
|
+
last: str | None = None,
|
927
|
+
order: Literal["asc", "desc"] | None = None,
|
928
|
+
order_by: Literal["id", "created_at", "updated_at"] | None = None,
|
929
|
+
size: int | None = None,
|
930
|
+
) -> PangeaResponse[ServiceConfigsPage]:
|
931
|
+
"""
|
932
|
+
OperationId: ai_guard_post_v1beta_config_list
|
933
|
+
"""
|
934
|
+
return self.request.post(
|
935
|
+
"v1beta/config/list",
|
936
|
+
data={"filter": filter, "last": last, "order": order, "order_by": order_by, "size": size},
|
937
|
+
result_class=ServiceConfigsPage,
|
938
|
+
)
|
pangea/services/audit/audit.py
CHANGED
@@ -1,9 +1,14 @@
|
|
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 datetime
|
6
10
|
import json
|
11
|
+
from collections.abc import Mapping
|
7
12
|
from typing import Any, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union, cast, overload
|
8
13
|
|
9
14
|
from pydantic import TypeAdapter
|
@@ -63,7 +68,7 @@ from pangea.utils import canonicalize_nested_json
|
|
63
68
|
|
64
69
|
class AuditBase:
|
65
70
|
def __init__(
|
66
|
-
self, private_key_file: str = "", public_key_info:
|
71
|
+
self, private_key_file: str = "", public_key_info: Mapping[str, str] = {}, tenant_id: str | None = None
|
67
72
|
) -> None:
|
68
73
|
self.pub_roots: Dict[int, PublishedRoot] = {}
|
69
74
|
self.buffer_data: Optional[str] = None
|
@@ -98,7 +103,7 @@ class AuditBase:
|
|
98
103
|
return input # type: ignore[return-value]
|
99
104
|
|
100
105
|
def _process_log(self, event: dict, sign_local: bool) -> LogEvent:
|
101
|
-
if event.get("tenant_id"
|
106
|
+
if event.get("tenant_id") is None and self.tenant_id:
|
102
107
|
event["tenant_id"] = self.tenant_id
|
103
108
|
|
104
109
|
event = {k: v for k, v in event.items() if v is not None}
|
@@ -229,10 +234,7 @@ class AuditBase:
|
|
229
234
|
tree_sizes.add(result.root.size)
|
230
235
|
tree_sizes.difference_update(self.pub_roots.keys())
|
231
236
|
|
232
|
-
if tree_sizes
|
233
|
-
arweave_roots = get_arweave_published_roots(result.root.tree_name, tree_sizes)
|
234
|
-
else:
|
235
|
-
arweave_roots = {}
|
237
|
+
arweave_roots = get_arweave_published_roots(result.root.tree_name, tree_sizes) if tree_sizes else {}
|
236
238
|
|
237
239
|
return tree_sizes, arweave_roots
|
238
240
|
|
@@ -393,7 +395,7 @@ class Audit(ServiceBase, AuditBase):
|
|
393
395
|
token: str,
|
394
396
|
config: PangeaConfig | None = None,
|
395
397
|
private_key_file: str = "",
|
396
|
-
public_key_info:
|
398
|
+
public_key_info: Mapping[str, str] = {},
|
397
399
|
tenant_id: str | None = None,
|
398
400
|
logger_name: str = "pangea",
|
399
401
|
config_id: str | None = None,
|
@@ -465,7 +467,7 @@ class Audit(ServiceBase, AuditBase):
|
|
465
467
|
A PangeaResponse where the hash of event data and optional verbose
|
466
468
|
results are returned in the response.result field.
|
467
469
|
Available response fields can be found in our
|
468
|
-
[API documentation](https://pangea.cloud/docs/api/audit#/v1/log).
|
470
|
+
[API documentation](https://pangea.cloud/docs/api/audit#/v1/log-post).
|
469
471
|
|
470
472
|
Examples:
|
471
473
|
log_response = audit.log(
|
@@ -513,7 +515,7 @@ class Audit(ServiceBase, AuditBase):
|
|
513
515
|
Returns:
|
514
516
|
A PangeaResponse where the hash of event data and optional verbose
|
515
517
|
results are returned in the response.result field.
|
516
|
-
Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v1/log).
|
518
|
+
Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v1/log-post).
|
517
519
|
|
518
520
|
Examples:
|
519
521
|
response = audit.log_event({"message": "hello world"}, verbose=True)
|
@@ -551,7 +553,7 @@ class Audit(ServiceBase, AuditBase):
|
|
551
553
|
Returns:
|
552
554
|
A PangeaResponse where the hash of event data and optional verbose
|
553
555
|
results are returned in the response.result field.
|
554
|
-
Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v2/log).
|
556
|
+
Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v2/log-post).
|
555
557
|
|
556
558
|
Examples:
|
557
559
|
log_response = audit.log_bulk(
|
@@ -592,7 +594,7 @@ class Audit(ServiceBase, AuditBase):
|
|
592
594
|
Returns:
|
593
595
|
A PangeaResponse where the hash of event data and optional verbose
|
594
596
|
results are returned in the response.result field.
|
595
|
-
Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v2/log_async).
|
597
|
+
Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v2/log_async-post).
|
596
598
|
|
597
599
|
Examples:
|
598
600
|
log_response = audit.log_bulk_async(
|
@@ -667,8 +669,8 @@ class Audit(ServiceBase, AuditBase):
|
|
667
669
|
|
668
670
|
Returns:
|
669
671
|
A PangeaResponse[SearchOutput] where the first page of matched events is returned in the
|
670
|
-
response.result field. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v1/search).
|
671
|
-
Pagination can be found in the [search results endpoint](https://pangea.cloud/docs/api/audit#/v1/results).
|
672
|
+
response.result field. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/audit#/v1/search-post).
|
673
|
+
Pagination can be found in the [search results endpoint](https://pangea.cloud/docs/api/audit#/v1/results-post).
|
672
674
|
|
673
675
|
Examples:
|
674
676
|
response = audit.search(
|