pangea-sdk 3.9.0__py3-none-any.whl → 4.0.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 +4 -4
- pangea/asyncio/services/audit.py +30 -11
- pangea/asyncio/services/authn.py +49 -29
- pangea/asyncio/services/authz.py +13 -7
- pangea/asyncio/services/embargo.py +2 -2
- pangea/asyncio/services/file_scan.py +3 -3
- pangea/asyncio/services/intel.py +40 -22
- pangea/asyncio/services/redact.py +5 -3
- pangea/asyncio/services/vault.py +32 -28
- pangea/dump_audit.py +1 -1
- pangea/request.py +8 -5
- pangea/response.py +9 -16
- pangea/services/audit/audit.py +43 -20
- pangea/services/audit/models.py +3 -3
- pangea/services/audit/util.py +3 -3
- pangea/services/authn/authn.py +39 -29
- pangea/services/authn/models.py +9 -4
- pangea/services/authz.py +10 -8
- pangea/services/embargo.py +2 -2
- pangea/services/file_scan.py +2 -2
- pangea/services/intel.py +23 -21
- pangea/services/redact.py +3 -3
- pangea/services/vault/models/common.py +6 -6
- pangea/services/vault/models/symmetric.py +2 -2
- pangea/services/vault/vault.py +28 -28
- pangea/utils.py +1 -18
- pangea/verify_audit.py +267 -83
- {pangea_sdk-3.9.0.dist-info → pangea_sdk-4.0.0.dist-info}/METADATA +10 -9
- pangea_sdk-4.0.0.dist-info/RECORD +46 -0
- {pangea_sdk-3.9.0.dist-info → pangea_sdk-4.0.0.dist-info}/WHEEL +1 -1
- pangea_sdk-3.9.0.dist-info/RECORD +0 -46
pangea/asyncio/services/intel.py
CHANGED
@@ -67,7 +67,9 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
67
67
|
|
68
68
|
"""
|
69
69
|
input = m.FileReputationRequest(hash=hash, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider)
|
70
|
-
return await self.request.post(
|
70
|
+
return await self.request.post(
|
71
|
+
"v1/reputation", m.FileReputationResult, data=input.model_dump(exclude_none=True)
|
72
|
+
)
|
71
73
|
|
72
74
|
async def hash_reputation_bulk(
|
73
75
|
self,
|
@@ -103,7 +105,9 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
103
105
|
input = m.FileReputationBulkRequest( # type: ignore[call-arg]
|
104
106
|
hashes=hashes, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider
|
105
107
|
)
|
106
|
-
return await self.request.post(
|
108
|
+
return await self.request.post(
|
109
|
+
"v2/reputation", m.FileReputationBulkResult, data=input.model_dump(exclude_none=True)
|
110
|
+
)
|
107
111
|
|
108
112
|
async def filepath_reputation(
|
109
113
|
self,
|
@@ -144,7 +148,9 @@ class FileIntelAsync(ServiceBaseAsync):
|
|
144
148
|
hash = hashlib.sha256(data.read()).hexdigest()
|
145
149
|
|
146
150
|
input = m.FileReputationRequest(hash=hash, hash_type="sha256", verbose=verbose, raw=raw, provider=provider)
|
147
|
-
return await self.request.post(
|
151
|
+
return await self.request.post(
|
152
|
+
"v1/reputation", m.FileReputationResult, data=input.model_dump(exclude_none=True)
|
153
|
+
)
|
148
154
|
|
149
155
|
async def filepath_reputation_bulk(
|
150
156
|
self,
|
@@ -243,7 +249,9 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
243
249
|
)
|
244
250
|
"""
|
245
251
|
input = m.DomainReputationRequest(domain=domain, verbose=verbose, provider=provider, raw=raw)
|
246
|
-
return await self.request.post(
|
252
|
+
return await self.request.post(
|
253
|
+
"v1/reputation", m.DomainReputationResult, data=input.model_dump(exclude_none=True)
|
254
|
+
)
|
247
255
|
|
248
256
|
async def reputation_bulk(
|
249
257
|
self,
|
@@ -277,7 +285,7 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
277
285
|
"""
|
278
286
|
input = m.DomainReputationBulkRequest(domains=domains, verbose=verbose, provider=provider, raw=raw)
|
279
287
|
return await self.request.post(
|
280
|
-
"v2/reputation", m.DomainReputationBulkResult, data=input.
|
288
|
+
"v2/reputation", m.DomainReputationBulkResult, data=input.model_dump(exclude_none=True)
|
281
289
|
)
|
282
290
|
|
283
291
|
async def who_is(
|
@@ -310,7 +318,7 @@ class DomainIntelAsync(ServiceBaseAsync):
|
|
310
318
|
)
|
311
319
|
"""
|
312
320
|
input = m.DomainWhoIsRequest(domain=domain, verbose=verbose, provider=provider, raw=raw) # type: ignore[call-arg]
|
313
|
-
return await self.request.post("v1/whois", m.DomainWhoIsResult, data=input.
|
321
|
+
return await self.request.post("v1/whois", m.DomainWhoIsResult, data=input.model_dump(exclude_none=True))
|
314
322
|
|
315
323
|
|
316
324
|
class IpIntelAsync(ServiceBaseAsync):
|
@@ -369,7 +377,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
369
377
|
)
|
370
378
|
"""
|
371
379
|
input = m.IPReputationRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
372
|
-
return await self.request.post("v1/reputation", m.IPReputationResult, data=input.
|
380
|
+
return await self.request.post("v1/reputation", m.IPReputationResult, data=input.model_dump(exclude_none=True))
|
373
381
|
|
374
382
|
async def reputation_bulk(
|
375
383
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -398,7 +406,9 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
398
406
|
FIXME:
|
399
407
|
"""
|
400
408
|
input = m.IPReputationBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
401
|
-
return await self.request.post(
|
409
|
+
return await self.request.post(
|
410
|
+
"v2/reputation", m.IPReputationBulkResult, data=input.model_dump(exclude_none=True)
|
411
|
+
)
|
402
412
|
|
403
413
|
async def geolocate(
|
404
414
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -430,7 +440,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
430
440
|
)
|
431
441
|
"""
|
432
442
|
input = m.IPGeolocateRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
433
|
-
return await self.request.post("v1/geolocate", m.IPGeolocateResult, data=input.
|
443
|
+
return await self.request.post("v1/geolocate", m.IPGeolocateResult, data=input.model_dump(exclude_none=True))
|
434
444
|
|
435
445
|
async def geolocate_bulk(
|
436
446
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -459,7 +469,9 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
459
469
|
FIXME:
|
460
470
|
"""
|
461
471
|
input = m.IPGeolocateBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
462
|
-
return await self.request.post(
|
472
|
+
return await self.request.post(
|
473
|
+
"v2/geolocate", m.IPGeolocateBulkResult, data=input.model_dump(exclude_none=True)
|
474
|
+
)
|
463
475
|
|
464
476
|
async def get_domain(
|
465
477
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -491,7 +503,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
491
503
|
)
|
492
504
|
"""
|
493
505
|
input = m.IPDomainRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
494
|
-
return await self.request.post("v1/domain", m.IPDomainResult, data=input.
|
506
|
+
return await self.request.post("v1/domain", m.IPDomainResult, data=input.model_dump(exclude_none=True))
|
495
507
|
|
496
508
|
async def get_domain_bulk(
|
497
509
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -520,7 +532,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
520
532
|
FIXME:
|
521
533
|
"""
|
522
534
|
input = m.IPDomainBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
523
|
-
return await self.request.post("v2/domain", m.IPDomainBulkResult, data=input.
|
535
|
+
return await self.request.post("v2/domain", m.IPDomainBulkResult, data=input.model_dump(exclude_none=True))
|
524
536
|
|
525
537
|
async def is_vpn(
|
526
538
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -552,7 +564,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
552
564
|
)
|
553
565
|
"""
|
554
566
|
input = m.IPVPNRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
555
|
-
return await self.request.post("v1/vpn", m.IPVPNResult, data=input.
|
567
|
+
return await self.request.post("v1/vpn", m.IPVPNResult, data=input.model_dump(exclude_none=True))
|
556
568
|
|
557
569
|
async def is_vpn_bulk(
|
558
570
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -581,7 +593,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
581
593
|
FIXME:
|
582
594
|
"""
|
583
595
|
input = m.IPVPNBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
584
|
-
return await self.request.post("v2/vpn", m.IPVPNBulkResult, data=input.
|
596
|
+
return await self.request.post("v2/vpn", m.IPVPNBulkResult, data=input.model_dump(exclude_none=True))
|
585
597
|
|
586
598
|
async def is_proxy(
|
587
599
|
self, ip: str, verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -613,7 +625,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
613
625
|
)
|
614
626
|
"""
|
615
627
|
input = m.IPProxyRequest(ip=ip, verbose=verbose, raw=raw, provider=provider)
|
616
|
-
return await self.request.post("v1/proxy", m.IPProxyResult, data=input.
|
628
|
+
return await self.request.post("v1/proxy", m.IPProxyResult, data=input.model_dump(exclude_none=True))
|
617
629
|
|
618
630
|
async def is_proxy_bulk(
|
619
631
|
self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
|
@@ -642,7 +654,7 @@ class IpIntelAsync(ServiceBaseAsync):
|
|
642
654
|
FIXME:
|
643
655
|
"""
|
644
656
|
input = m.IPProxyBulkRequest(ips=ips, verbose=verbose, raw=raw, provider=provider)
|
645
|
-
return await self.request.post("v2/proxy", m.IPProxyBulkResult, data=input.
|
657
|
+
return await self.request.post("v2/proxy", m.IPProxyBulkResult, data=input.model_dump(exclude_none=True))
|
646
658
|
|
647
659
|
|
648
660
|
class UrlIntelAsync(ServiceBaseAsync):
|
@@ -702,7 +714,7 @@ class UrlIntelAsync(ServiceBaseAsync):
|
|
702
714
|
"""
|
703
715
|
|
704
716
|
input = m.URLReputationRequest(url=url, provider=provider, verbose=verbose, raw=raw)
|
705
|
-
return await self.request.post("v1/reputation", m.URLReputationResult, data=input.
|
717
|
+
return await self.request.post("v1/reputation", m.URLReputationResult, data=input.model_dump(exclude_none=True))
|
706
718
|
|
707
719
|
async def reputation_bulk(
|
708
720
|
self,
|
@@ -736,7 +748,9 @@ class UrlIntelAsync(ServiceBaseAsync):
|
|
736
748
|
"""
|
737
749
|
|
738
750
|
input = m.URLReputationBulkRequest(urls=urls, provider=provider, verbose=verbose, raw=raw)
|
739
|
-
return await self.request.post(
|
751
|
+
return await self.request.post(
|
752
|
+
"v2/reputation", m.URLReputationBulkResult, data=input.model_dump(exclude_none=True)
|
753
|
+
)
|
740
754
|
|
741
755
|
|
742
756
|
class UserIntelAsync(ServiceBaseAsync):
|
@@ -822,7 +836,9 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
822
836
|
verbose=verbose,
|
823
837
|
raw=raw,
|
824
838
|
)
|
825
|
-
return await self.request.post(
|
839
|
+
return await self.request.post(
|
840
|
+
"v1/user/breached", m.UserBreachedResult, data=input.model_dump(exclude_none=True)
|
841
|
+
)
|
826
842
|
|
827
843
|
async def user_breached_bulk(
|
828
844
|
self,
|
@@ -876,7 +892,9 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
876
892
|
verbose=verbose,
|
877
893
|
raw=raw,
|
878
894
|
)
|
879
|
-
return await self.request.post(
|
895
|
+
return await self.request.post(
|
896
|
+
"v2/user/breached", m.UserBreachedBulkResult, data=input.model_dump(exclude_none=True)
|
897
|
+
)
|
880
898
|
|
881
899
|
async def password_breached(
|
882
900
|
self,
|
@@ -919,7 +937,7 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
919
937
|
hash_type=hash_type, hash_prefix=hash_prefix, provider=provider, verbose=verbose, raw=raw
|
920
938
|
)
|
921
939
|
return await self.request.post(
|
922
|
-
"v1/password/breached", m.UserPasswordBreachedResult, data=input.
|
940
|
+
"v1/password/breached", m.UserPasswordBreachedResult, data=input.model_dump(exclude_none=True)
|
923
941
|
)
|
924
942
|
|
925
943
|
async def password_breached_bulk(
|
@@ -959,5 +977,5 @@ class UserIntelAsync(ServiceBaseAsync):
|
|
959
977
|
hash_type=hash_type, hash_prefixes=hash_prefixes, provider=provider, verbose=verbose, raw=raw
|
960
978
|
)
|
961
979
|
return await self.request.post(
|
962
|
-
"v2/password/breached", m.UserPasswordBreachedBulkResult, data=input.
|
980
|
+
"v2/password/breached", m.UserPasswordBreachedBulkResult, data=input.model_dump(exclude_none=True)
|
963
981
|
)
|
@@ -102,7 +102,7 @@ class RedactAsync(ServiceBaseAsync):
|
|
102
102
|
return_result=return_result,
|
103
103
|
redaction_method_overrides=redaction_method_overrides,
|
104
104
|
)
|
105
|
-
return await self.request.post("v1/redact", m.RedactResult, data=input.
|
105
|
+
return await self.request.post("v1/redact", m.RedactResult, data=input.model_dump(exclude_none=True))
|
106
106
|
|
107
107
|
async def redact_structured(
|
108
108
|
self,
|
@@ -162,7 +162,9 @@ class RedactAsync(ServiceBaseAsync):
|
|
162
162
|
return_result=return_result,
|
163
163
|
redaction_method_overrides=redaction_method_overrides,
|
164
164
|
)
|
165
|
-
return await self.request.post(
|
165
|
+
return await self.request.post(
|
166
|
+
"v1/redact_structured", m.StructuredResult, data=input.model_dump(exclude_none=True)
|
167
|
+
)
|
166
168
|
|
167
169
|
async def unredact(self, redacted_data: m.RedactedData, fpe_context: str) -> PangeaResponse[m.UnredactResult]:
|
168
170
|
"""
|
@@ -185,4 +187,4 @@ class RedactAsync(ServiceBaseAsync):
|
|
185
187
|
[API Documentation](https://pangea.cloud/docs/api/redact#unredact)
|
186
188
|
"""
|
187
189
|
input = m.UnredactRequest(redacted_data=redacted_data, fpe_context=fpe_context)
|
188
|
-
return await self.request.post("v1/unredact", m.UnredactResult, data=input.
|
190
|
+
return await self.request.post("v1/unredact", m.UnredactResult, data=input.model_dump(exclude_none=True))
|
pangea/asyncio/services/vault.py
CHANGED
@@ -151,7 +151,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
151
151
|
input = DeleteRequest(
|
152
152
|
id=id,
|
153
153
|
)
|
154
|
-
return await self.request.post("v1/delete", DeleteResult, data=input.
|
154
|
+
return await self.request.post("v1/delete", DeleteResult, data=input.model_dump(exclude_none=True))
|
155
155
|
|
156
156
|
# Get endpoint
|
157
157
|
async def get(
|
@@ -198,7 +198,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
198
198
|
verbose=verbose,
|
199
199
|
version_state=version_state,
|
200
200
|
)
|
201
|
-
return await self.request.post("v1/get", GetResult, data=input.
|
201
|
+
return await self.request.post("v1/get", GetResult, data=input.model_dump(exclude_none=True))
|
202
202
|
|
203
203
|
# List endpoint
|
204
204
|
async def list(
|
@@ -254,7 +254,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
254
254
|
)
|
255
255
|
"""
|
256
256
|
input = ListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
|
257
|
-
return await self.request.post("v1/list", ListResult, data=input.
|
257
|
+
return await self.request.post("v1/list", ListResult, data=input.model_dump(exclude_none=True))
|
258
258
|
|
259
259
|
# Update endpoint
|
260
260
|
async def update(
|
@@ -335,7 +335,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
335
335
|
expiration=expiration,
|
336
336
|
item_state=item_state,
|
337
337
|
)
|
338
|
-
return await self.request.post("v1/update", UpdateResult, data=input.
|
338
|
+
return await self.request.post("v1/update", UpdateResult, data=input.model_dump(exclude_none=True))
|
339
339
|
|
340
340
|
async def secret_store(
|
341
341
|
self,
|
@@ -405,7 +405,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
405
405
|
rotation_state=rotation_state,
|
406
406
|
expiration=expiration,
|
407
407
|
)
|
408
|
-
return await self.request.post("v1/secret/store", SecretStoreResult, data=input.
|
408
|
+
return await self.request.post("v1/secret/store", SecretStoreResult, data=input.model_dump(exclude_none=True))
|
409
409
|
|
410
410
|
async def pangea_token_store(
|
411
411
|
self,
|
@@ -475,7 +475,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
475
475
|
rotation_state=rotation_state,
|
476
476
|
expiration=expiration,
|
477
477
|
)
|
478
|
-
return await self.request.post("v1/secret/store", SecretStoreResult, data=input.
|
478
|
+
return await self.request.post("v1/secret/store", SecretStoreResult, data=input.model_dump(exclude_none=True))
|
479
479
|
|
480
480
|
# Rotate endpoint
|
481
481
|
async def secret_rotate(
|
@@ -515,7 +515,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
515
515
|
)
|
516
516
|
"""
|
517
517
|
input = SecretRotateRequest(id=id, secret=secret, rotation_state=rotation_state)
|
518
|
-
return await self.request.post("v1/secret/rotate", SecretRotateResult, data=input.
|
518
|
+
return await self.request.post("v1/secret/rotate", SecretRotateResult, data=input.model_dump(exclude_none=True))
|
519
519
|
|
520
520
|
# Rotate endpoint
|
521
521
|
async def pangea_token_rotate(self, id: str) -> PangeaResponse[SecretRotateResult]:
|
@@ -543,7 +543,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
543
543
|
)
|
544
544
|
"""
|
545
545
|
input = SecretRotateRequest(id=id) # type: ignore[call-arg]
|
546
|
-
return await self.request.post("v1/secret/rotate", SecretRotateResult, data=input.
|
546
|
+
return await self.request.post("v1/secret/rotate", SecretRotateResult, data=input.model_dump(exclude_none=True))
|
547
547
|
|
548
548
|
async def symmetric_generate(
|
549
549
|
self,
|
@@ -617,7 +617,9 @@ class VaultAsync(ServiceBaseAsync):
|
|
617
617
|
rotation_state=rotation_state,
|
618
618
|
expiration=expiration,
|
619
619
|
)
|
620
|
-
return await self.request.post(
|
620
|
+
return await self.request.post(
|
621
|
+
"v1/key/generate", SymmetricGenerateResult, data=input.model_dump(exclude_none=True)
|
622
|
+
)
|
621
623
|
|
622
624
|
async def asymmetric_generate(
|
623
625
|
self,
|
@@ -691,7 +693,9 @@ class VaultAsync(ServiceBaseAsync):
|
|
691
693
|
rotation_state=rotation_state,
|
692
694
|
expiration=expiration,
|
693
695
|
)
|
694
|
-
return await self.request.post(
|
696
|
+
return await self.request.post(
|
697
|
+
"v1/key/generate", AsymmetricGenerateResult, data=input.model_dump(exclude_none=True)
|
698
|
+
)
|
695
699
|
|
696
700
|
# Store endpoints
|
697
701
|
async def asymmetric_store(
|
@@ -774,7 +778,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
774
778
|
rotation_state=rotation_state,
|
775
779
|
expiration=expiration,
|
776
780
|
)
|
777
|
-
return await self.request.post("v1/key/store", AsymmetricStoreResult, data=input.
|
781
|
+
return await self.request.post("v1/key/store", AsymmetricStoreResult, data=input.model_dump(exclude_none=True))
|
778
782
|
|
779
783
|
async def symmetric_store(
|
780
784
|
self,
|
@@ -852,7 +856,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
852
856
|
rotation_state=rotation_state,
|
853
857
|
expiration=expiration,
|
854
858
|
)
|
855
|
-
return await self.request.post("v1/key/store", SymmetricStoreResult, data=input.
|
859
|
+
return await self.request.post("v1/key/store", SymmetricStoreResult, data=input.model_dump(exclude_none=True))
|
856
860
|
|
857
861
|
# Rotate endpoint
|
858
862
|
async def key_rotate(
|
@@ -901,7 +905,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
901
905
|
input = KeyRotateRequest(
|
902
906
|
id=id, public_key=public_key, private_key=private_key, key=key, rotation_state=rotation_state
|
903
907
|
)
|
904
|
-
return await self.request.post("v1/key/rotate", KeyRotateResult, data=input.
|
908
|
+
return await self.request.post("v1/key/rotate", KeyRotateResult, data=input.model_dump(exclude_none=True))
|
905
909
|
|
906
910
|
# Encrypt
|
907
911
|
async def encrypt(self, id: str, plain_text: str, version: Optional[int] = None) -> PangeaResponse[EncryptResult]:
|
@@ -932,8 +936,8 @@ class VaultAsync(ServiceBaseAsync):
|
|
932
936
|
version=1,
|
933
937
|
)
|
934
938
|
"""
|
935
|
-
input = EncryptRequest(id=id, plain_text=plain_text, version=version)
|
936
|
-
return await self.request.post("v1/key/encrypt", EncryptResult, data=input.
|
939
|
+
input = EncryptRequest(id=id, plain_text=plain_text, version=version)
|
940
|
+
return await self.request.post("v1/key/encrypt", EncryptResult, data=input.model_dump(exclude_none=True))
|
937
941
|
|
938
942
|
# Decrypt
|
939
943
|
async def decrypt(self, id: str, cipher_text: str, version: Optional[int] = None) -> PangeaResponse[DecryptResult]:
|
@@ -964,8 +968,8 @@ class VaultAsync(ServiceBaseAsync):
|
|
964
968
|
version=1,
|
965
969
|
)
|
966
970
|
"""
|
967
|
-
input = DecryptRequest(id=id, cipher_text=cipher_text, version=version)
|
968
|
-
return await self.request.post("v1/key/decrypt", DecryptResult, data=input.
|
971
|
+
input = DecryptRequest(id=id, cipher_text=cipher_text, version=version)
|
972
|
+
return await self.request.post("v1/key/decrypt", DecryptResult, data=input.model_dump(exclude_none=True))
|
969
973
|
|
970
974
|
# Sign
|
971
975
|
async def sign(self, id: str, message: str, version: Optional[int] = None) -> PangeaResponse[SignResult]:
|
@@ -997,7 +1001,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
997
1001
|
)
|
998
1002
|
"""
|
999
1003
|
input = SignRequest(id=id, message=message, version=version)
|
1000
|
-
return await self.request.post("v1/key/sign", SignResult, data=input.
|
1004
|
+
return await self.request.post("v1/key/sign", SignResult, data=input.model_dump(exclude_none=True))
|
1001
1005
|
|
1002
1006
|
# Verify
|
1003
1007
|
async def verify(
|
@@ -1038,7 +1042,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1038
1042
|
signature=signature,
|
1039
1043
|
version=version,
|
1040
1044
|
)
|
1041
|
-
return await self.request.post("v1/key/verify", VerifyResult, data=input.
|
1045
|
+
return await self.request.post("v1/key/verify", VerifyResult, data=input.model_dump(exclude_none=True))
|
1042
1046
|
|
1043
1047
|
async def jwt_verify(self, jws: str) -> PangeaResponse[JWTVerifyResult]:
|
1044
1048
|
"""
|
@@ -1065,7 +1069,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1065
1069
|
)
|
1066
1070
|
"""
|
1067
1071
|
input = JWTVerifyRequest(jws=jws)
|
1068
|
-
return await self.request.post("v1/key/verify/jwt", JWTVerifyResult, data=input.
|
1072
|
+
return await self.request.post("v1/key/verify/jwt", JWTVerifyResult, data=input.model_dump(exclude_none=True))
|
1069
1073
|
|
1070
1074
|
async def jwt_sign(self, id: str, payload: str) -> PangeaResponse[JWTSignResult]:
|
1071
1075
|
"""
|
@@ -1094,7 +1098,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1094
1098
|
)
|
1095
1099
|
"""
|
1096
1100
|
input = JWTSignRequest(id=id, payload=payload)
|
1097
|
-
return await self.request.post("v1/key/sign/jwt", JWTSignResult, data=input.
|
1101
|
+
return await self.request.post("v1/key/sign/jwt", JWTSignResult, data=input.model_dump(exclude_none=True))
|
1098
1102
|
|
1099
1103
|
# Get endpoint
|
1100
1104
|
async def jwk_get(self, id: str, version: Optional[str] = None) -> PangeaResponse[JWKGetResult]:
|
@@ -1125,7 +1129,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1125
1129
|
)
|
1126
1130
|
"""
|
1127
1131
|
input = JWKGetRequest(id=id, version=version)
|
1128
|
-
return await self.request.post("v1/get/jwk", JWKGetResult, data=input.
|
1132
|
+
return await self.request.post("v1/get/jwk", JWKGetResult, data=input.model_dump(exclude_none=True))
|
1129
1133
|
|
1130
1134
|
# State change
|
1131
1135
|
async def state_change(
|
@@ -1164,7 +1168,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1164
1168
|
)
|
1165
1169
|
"""
|
1166
1170
|
input = StateChangeRequest(id=id, state=state, version=version, destroy_period=destroy_period)
|
1167
|
-
return await self.request.post("v1/state/change", StateChangeResult, data=input.
|
1171
|
+
return await self.request.post("v1/state/change", StateChangeResult, data=input.model_dump(exclude_none=True))
|
1168
1172
|
|
1169
1173
|
# Folder create
|
1170
1174
|
async def folder_create(
|
@@ -1201,7 +1205,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1201
1205
|
)
|
1202
1206
|
"""
|
1203
1207
|
input = FolderCreateRequest(name=name, folder=folder, metadata=metadata, tags=tags)
|
1204
|
-
return await self.request.post("v1/folder/create", FolderCreateResult, data=input.
|
1208
|
+
return await self.request.post("v1/folder/create", FolderCreateResult, data=input.model_dump(exclude_none=True))
|
1205
1209
|
|
1206
1210
|
# Encrypt structured
|
1207
1211
|
async def encrypt_structured(
|
@@ -1249,7 +1253,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1249
1253
|
return await self.request.post(
|
1250
1254
|
"v1/key/encrypt/structured",
|
1251
1255
|
EncryptStructuredResult,
|
1252
|
-
data=input.
|
1256
|
+
data=input.model_dump(exclude_none=True),
|
1253
1257
|
)
|
1254
1258
|
|
1255
1259
|
# Decrypt structured
|
@@ -1298,7 +1302,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1298
1302
|
return await self.request.post(
|
1299
1303
|
"v1/key/decrypt/structured",
|
1300
1304
|
EncryptStructuredResult,
|
1301
|
-
data=input.
|
1305
|
+
data=input.model_dump(exclude_none=True),
|
1302
1306
|
)
|
1303
1307
|
|
1304
1308
|
async def encrypt_transform(
|
@@ -1348,7 +1352,7 @@ class VaultAsync(ServiceBaseAsync):
|
|
1348
1352
|
return await self.request.post(
|
1349
1353
|
"v1/key/encrypt/transform",
|
1350
1354
|
EncryptTransformResult,
|
1351
|
-
data=input.
|
1355
|
+
data=input.model_dump(exclude_none=True),
|
1352
1356
|
)
|
1353
1357
|
|
1354
1358
|
async def decrypt_transform(
|
@@ -1387,5 +1391,5 @@ class VaultAsync(ServiceBaseAsync):
|
|
1387
1391
|
return await self.request.post(
|
1388
1392
|
"v1/key/decrypt/transform",
|
1389
1393
|
DecryptTransformResult,
|
1390
|
-
data=input.
|
1394
|
+
data=input.model_dump(exclude_none=True),
|
1391
1395
|
)
|
pangea/dump_audit.py
CHANGED
@@ -19,7 +19,7 @@ from pangea.utils import default_encoder
|
|
19
19
|
|
20
20
|
|
21
21
|
def dump_event(output: io.TextIOWrapper, row: SearchEvent, resp: PangeaResponse[SearchOutput]):
|
22
|
-
row_data = filter_deep_none(row.
|
22
|
+
row_data = filter_deep_none(row.model_dump())
|
23
23
|
if resp.result and resp.result.root:
|
24
24
|
row_data["tree_size"] = resp.result.root.size
|
25
25
|
output.write(json.dumps(row_data, default=default_encoder) + "\n")
|
pangea/request.py
CHANGED
@@ -5,7 +5,7 @@ import copy
|
|
5
5
|
import json
|
6
6
|
import logging
|
7
7
|
import time
|
8
|
-
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type, Union
|
8
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple, Type, Union
|
9
9
|
|
10
10
|
import requests
|
11
11
|
from requests.adapters import HTTPAdapter, Retry
|
@@ -190,7 +190,7 @@ class PangeaRequestBase(object):
|
|
190
190
|
raise pe.PangeaAPIException(f"{summary} ", response)
|
191
191
|
|
192
192
|
|
193
|
-
TResult = TypeVar("TResult", bound=PangeaResponseResult
|
193
|
+
TResult = TypeVar("TResult", bound=PangeaResponseResult)
|
194
194
|
|
195
195
|
|
196
196
|
class PangeaRequest(PangeaRequestBase):
|
@@ -324,14 +324,17 @@ class PangeaRequest(PangeaRequestBase):
|
|
324
324
|
return self.session.post(url, headers=headers, data=data_send, files=files)
|
325
325
|
|
326
326
|
def _http_post_process(
|
327
|
-
self,
|
327
|
+
self,
|
328
|
+
data: Union[str, Dict] = {},
|
329
|
+
files: Optional[Sequence[Tuple[str, Tuple[Any, str, str]]]] = None,
|
330
|
+
multipart_post: bool = True,
|
328
331
|
):
|
329
332
|
if files:
|
330
333
|
if multipart_post is True:
|
331
334
|
data_send: str = json.dumps(data, default=default_encoder) if isinstance(data, dict) else data
|
332
335
|
multi = [("request", (None, data_send, "application/json"))]
|
333
|
-
multi.extend(files)
|
334
|
-
files = multi
|
336
|
+
multi.extend(files)
|
337
|
+
files = multi
|
335
338
|
return None, files
|
336
339
|
else:
|
337
340
|
# Post to presigned url as form
|
pangea/response.py
CHANGED
@@ -7,8 +7,8 @@ from typing import Any, Dict, Generic, List, Optional, Type, Union
|
|
7
7
|
|
8
8
|
import aiohttp
|
9
9
|
import requests
|
10
|
-
from pydantic import BaseModel
|
11
|
-
from typing_extensions import TypeVar
|
10
|
+
from pydantic import BaseModel, ConfigDict, PlainSerializer
|
11
|
+
from typing_extensions import Annotated, TypeVar
|
12
12
|
|
13
13
|
from pangea.utils import format_datetime
|
14
14
|
|
@@ -50,24 +50,17 @@ class TransferMethod(str, enum.Enum):
|
|
50
50
|
return str(self.value)
|
51
51
|
|
52
52
|
|
53
|
+
PangeaDateTime = Annotated[datetime.datetime, PlainSerializer(format_datetime)]
|
54
|
+
|
55
|
+
|
53
56
|
# API response should accept arbitrary fields to make them accept possible new parameters
|
54
57
|
class APIResponseModel(BaseModel):
|
55
|
-
|
56
|
-
arbitrary_types_allowed = True
|
57
|
-
# allow parameters despite they are not declared in model. Make SDK accept server new parameters
|
58
|
-
extra = "allow"
|
58
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
59
59
|
|
60
60
|
|
61
61
|
# API request models doesn't not allow arbitrary fields
|
62
62
|
class APIRequestModel(BaseModel):
|
63
|
-
|
64
|
-
arbitrary_types_allowed = True
|
65
|
-
extra = (
|
66
|
-
"allow" # allow parameters despite they are not declared in model. Make SDK accept server new parameters
|
67
|
-
)
|
68
|
-
json_encoders = {
|
69
|
-
datetime.datetime: format_datetime,
|
70
|
-
}
|
63
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
71
64
|
|
72
65
|
|
73
66
|
class PangeaResponseResult(APIResponseModel):
|
@@ -169,10 +162,10 @@ class ResponseHeader(APIResponseModel):
|
|
169
162
|
"""
|
170
163
|
|
171
164
|
|
172
|
-
T = TypeVar("T", bound=PangeaResponseResult
|
165
|
+
T = TypeVar("T", bound=PangeaResponseResult)
|
173
166
|
|
174
167
|
|
175
|
-
class PangeaResponse(Generic[T]
|
168
|
+
class PangeaResponse(ResponseHeader, Generic[T]):
|
176
169
|
raw_result: Optional[Dict[str, Any]] = None
|
177
170
|
raw_response: Optional[Union[requests.Response, aiohttp.ClientResponse]] = None
|
178
171
|
result: Optional[T] = None
|